Docs / API Gateway V2 (HTTP API)

API Gateway V2 (HTTP API)

LocalEmu supports API Gateway V2 (HTTP APIs) with Lambda proxy integrations and HTTP proxy integrations. Create APIs, define routes, attach Lambda functions, and invoke them through the local gateway.

How It Works

API Gateway V2 HTTP APIs are created with awsemu apigatewayv2 commands. You create an API, add routes with integrations, deploy a stage, and invoke through the local endpoint.

The invoke URL pattern for LocalEmu is:

Invoke URL
http://localhost:4566/_aws/execute-api-v2/<api-id>/<stage>/<path>

Route Matching

Routes are matched in order of specificity:

Priority Route Type Example
1 (highest) Exact match GET /users/profile
2 Parameterized GET /users/{id}
3 Greedy path GET /users/{proxy+}
4 (lowest) Default catch-all $default

Full Example

Create an HTTP API with a Lambda integration, add a route, and invoke it.

Step 1: Create the API

Terminal
$ API_ID=$(awsemu apigatewayv2 create-api \
    --name my-http-api \
    --protocol-type HTTP \
    --query ApiId --output text)

$ echo $API_ID
a1b2c3d4e5

Step 2: Create a Lambda function

Terminal
# Create a simple Lambda function
$ cat > /tmp/handler.py <<'PYEOF'
def handler(event, context):
    name = event.get("pathParameters", {}).get("name", "world")
    return {
        "statusCode": 200,
        "body": f"Hello, {name}!"
    }
PYEOF

$ cd /tmp && zip handler.zip handler.py

$ awsemu lambda create-function \
    --function-name hello-fn \
    --runtime python3.12 \
    --handler handler.handler \
    --role arn:aws:iam::000000000000:role/lambda-role \
    --zip-file fileb:///tmp/handler.zip

Step 3: Wait for Lambda to be ready

Terminal
# Wait for Lambda to reach Active state
$ awsemu lambda wait function-active-v2 \
    --function-name hello-fn

Lambda must be in the Active state before you can invoke it through API Gateway. Always wait after create-function.

Step 4: Create integration, route, and stage

Terminal
# Create a Lambda integration
$ INTEG_ID=$(awsemu apigatewayv2 create-integration \
    --api-id $API_ID \
    --integration-type AWS_PROXY \
    --integration-uri arn:aws:lambda:us-east-1:000000000000:function:hello-fn \
    --payload-format-version 2.0 \
    --query IntegrationId --output text)

# Create a route
$ awsemu apigatewayv2 create-route \
    --api-id $API_ID \
    --route-key "GET /hello/{name}" \
    --target integrations/$INTEG_ID

# Create the $default stage (auto-deploy)
$ awsemu apigatewayv2 create-stage \
    --api-id $API_ID \
    --stage-name '$default' \
    --auto-deploy

Step 5: Invoke

Terminal
$ curl http://localhost:4566/_aws/execute-api-v2/$API_ID/\$default/hello/LocalEmu
Hello, LocalEmu!

Lambda Payload Formats

API Gateway V2 supports two payload format versions for Lambda integrations. The format is set per integration via the payloadFormatVersion parameter.

V2 Payload Format (default for HTTP APIs)

When payloadFormatVersion is 2.0, the Lambda receives an event like this:

V2 Event (payloadFormatVersion: 2.0)
{
  "version": "2.0",
  "rawPath": "/hello/LocalEmu",
  "pathParameters": {
    "name": "LocalEmu"
  },
  "requestContext": {
    "http": {
      "method": "GET",
      "path": "/hello/LocalEmu"
    },
    "stage": "$default",
    "apiId": "a1b2c3d4e5"
  },
  "isBase64Encoded": false
}

V1 Payload Format

When payloadFormatVersion is 1.0, the Lambda receives the REST API-style event:

V1 Event (payloadFormatVersion: 1.0)
{
  "version": "1.0",
  "resource": "/hello/{name}",
  "path": "/hello/LocalEmu",
  "httpMethod": "GET",
  "pathParameters": {
    "name": "LocalEmu"
  },
  "requestContext": {
    "resourcePath": "/hello/{name}",
    "httpMethod": "GET",
    "stage": "$default"
  }
}

HTTP Proxy Integrations

In addition to Lambda, API Gateway V2 supports HTTP_PROXY integrations that forward requests to an external URL.

Terminal
# Create an HTTP_PROXY integration that forwards to an external URL
$ PROXY_ID=$(awsemu apigatewayv2 create-integration \
    --api-id $API_ID \
    --integration-type HTTP_PROXY \
    --integration-method GET \
    --integration-uri https://httpbin.org/get \
    --query IntegrationId --output text)

$ awsemu apigatewayv2 create-route \
    --api-id $API_ID \
    --route-key "GET /proxy" \
    --target integrations/$PROXY_ID

Notes