Search code examples
amazon-web-servicesswaggeraws-api-gateway

Hardcode a header into AWS API Gateway


We have an API Gateway which mobile app requests are prxied through before ending up at our core API. We have a webapp that goes straight to the core API.

We simply want to distinguish which requests are coming from the mobile app. We dont want to have to change and resubmit the mobile app. So instead, I want to hardcode a header into the API Gateway e.g. "X-IS-MOBILE": "true"

I first tried added it in the parameters:

swagger: "2.0"
info:
  version: "2019-07-22T10:33:53Z"
  title: "Mobile API Integration"
host: "mobile.domain.link"
basePath: "/v3"
schemes:
- "https"
paths:
  /app-info:
    post:
      operationId: "appInfo"
      consumes:
      - "application/json"
      produces:
      - "application/json"
      parameters:
      - in: header
        name: "X-IS-MOBILE"
        type: boolean
        default: true
      - in: "body"
        name: "AppInfoPayload"
        required: true
        schema:
          $ref: "#/definitions/AppInfoPayload"
      responses:
        "200":
          description: "200 response"
          schema:
            $ref: "#/definitions/AppInfoView"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
            Access-Control-Allow-Headers:
              type: "string"
        "400":
          description: "400 response"
          schema:
            $ref: "#/definitions/ApiError"
        "401":
          description: "401 response"
          schema:
            $ref: "#/definitions/ApiError"
        "500":
          description: "500 response"
          schema:
            $ref: "#/definitions/ApiError"
      x-amazon-apigateway-integration:
        httpMethod: "POST"
        uri: "https://api.domain.link/v1/app-info"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        type: "http_proxy"
    options:
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Headers:
              type: "string"
      x-amazon-apigateway-integration:
        httpMethod: "OPTIONS"
        uri: "https://api.domain.link/v1/app-info"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        type: "http_proxy"

This did NOT work. When I checked the core API logs, there was no X-IS-MOBILE in the headers.

I then tried using requestTemplates in x-amazon-apigateway-integration:

swagger: "2.0"
info:
  version: "2019-07-22T10:33:53Z"
  title: "Mobile API Integration"
host: "mobile.domain.link"
basePath: "/v3"
schemes:
- "https"
paths:
  /app-info:
    post:
      operationId: "appInfo"
      consumes:
      - "application/json"
      produces:
      - "application/json"
      parameters:
      - in: "body"
        name: "AppInfoPayload"
        required: true
        schema:
          $ref: "#/definitions/AppInfoPayload"
      responses:
        "200":
          description: "200 response"
          schema:
            $ref: "#/definitions/AppInfoView"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
            Access-Control-Allow-Headers:
              type: "string"
        "400":
          description: "400 response"
          schema:
            $ref: "#/definitions/ApiError"
        "401":
          description: "401 response"
          schema:
            $ref: "#/definitions/ApiError"
        "500":
          description: "500 response"
          schema:
            $ref: "#/definitions/ApiError"
      x-amazon-apigateway-integration:
        httpMethod: "POST"
        uri: "https://api.domain.link/v1/app-info"
        requestTemplates:
          'application/json': |
            {
              "headers": {
                  "X-IS-MOBILE": "true"
              },
              "body": $input.json('$')
            }
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        type: "http_proxy"
    options:
      produces:
      - "application/json"
      responses:
        "200":
          description: "200 response"
          schema:
            $ref: "#/definitions/Empty"
          headers:
            Access-Control-Allow-Origin:
              type: "string"
            Access-Control-Allow-Methods:
              type: "string"
            Access-Control-Allow-Headers:
              type: "string"
      x-amazon-apigateway-integration:
        httpMethod: "OPTIONS"
        uri: "https://api.domain.link/v1/app-info"
        responses:
          default:
            statusCode: "200"
        passthroughBehavior: "when_no_match"
        type: "http_proxy"

The relevant code is:

        requestTemplates:
          'application/json': |
            {
              "headers": {
                  "X-IS-MOBILE": "true"
              },
              "body": $input.json('$')
            }

Again, this did NOT work, there is no X-IS-MOBILE in the core API logs. What am I doing wrong?


Solution

  • So, in your first attempt, you are adding the X-IS-MOBILE header to the incoming request headers parameter for validation purposes (ie, if required and not present, the APIGW will reply with 400 Bad Request).

    On the second attempt, there are a couple of problems with the requestTemplates:

    1. it is not applicable to http_proxy integration type, only to http;
    2. the code itself is incorrect, should be:
          x-amazon-apigateway-integration:
            httpMethod: "POST"
            uri: "https://api.domain.link/v1/app-info"
            requestTemplates:
              'application/json': |
                #set($context.requestOverride.header.x-is-mobile = 'true')
                $input.json('$')
            responses:
              default:
                statusCode: "200"
            passthroughBehavior: "when_no_match"
            type: "http"
    

    See the relevant documentation and examples here.

    However, if you want/need to use the http_proxy integration type, you can still add the header mapping to the integration request, using requestParameters instead:

          x-amazon-apigateway-integration:
            httpMethod: "POST"
            uri: "https://api.domain.link/v1/app-info"
            requestParameters:
              integration.request.header.x-is-mobile: "'true'"
            responses:
              default:
                statusCode: "200"
            passthroughBehavior: "when_no_match"
            type: "http_proxy"