2
votes

How can I ensure requests to URLs with whatever (bad) query string data in them, make it to my lambda behind api gateway and not be blocked at api gateway?

I have an endpoint on API gateway which responds to requests such as the one below where the query string parameter url should exist.

https://the-api-id.amazonaws.com?url=https://stackoverflow.com

The query string parameter url receives a URL which is usually url encoded so not a problem. Other times the URL arrives unencoded and therefore potentially non URL safe characters are present.

Unfortunately I am downstream from other services which occasionally send me bad data and one of the responsibilities of this particular hop is to detect and attempt to rectify/clean it. I cannot prevent the request to my API gateway endpoint containing non url safe characters.

The problem is such that if bad data exists in the URL, it would appear that API gateway rejects the request and doesn't forward it to my lambda even though it's using Lambda Proxy and I've not set up anything I'm aware of at the api gateway level to stop requests going through.

If you takes the serverless framework example at the bottom of this question, it can be easily reproduced.

Simply deploy then visit

https://the-api-id.execute-api.us-east-1.amazonaws.com/dev/

And you'll see the expected text/html response.

However, if you were to visit the following where I've put { and } in, unencoded (as is commonly received by my endpoint) you'll see that API gateway returns a 400 status response and doesn't appear to forward the request to the lambda function.

https://the-api-id.execute-api.us-east-1.amazonaws.com/dev/?url={clickurl}

I ticked "Enable CloudWatch Logs" in the api gateway console, and a log group was created but it doesn't appear to get any records so that appears to be a dead end.

I have tried regional and edge optimised endpoints and both api gateway and cloudfront respond with the same thing.

How can I ensure requests to URLs with whatever (bad) query string data in them, make it to my lambda behind api gateway and not be blocked at api gateway?


Below is just boilerplate to play around with a working example using the serverless framework if you were so inclined.


serverless.yml

---
service: example-400
frameworkVersion: '2'

provider:
  name: aws
  runtime: nodejs12.x

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /
          method: get

handler.js

'use strict';

module.exports.hello = async event => {
  return {
    statusCode: 200,
    body: JSON.stringify(
      {
        message: 'Go Serverless v1.0! Your function executed successfully!',
        input: event,
      },
      null,
      2
    ),
  };
};

Then run

serverless deploy
1
have you created a mapping template to send that param over? docs.aws.amazon.com/apigateway/latest/developerguide/… - LostJon

1 Answers

0
votes

You can set up multiple http events for the same lambda function in your serverless.yml file.

Each http event can have its own definition and/or path to give you the opportunity to capture the event depending on which endpoint your user hits, even with or without query params:

# 'functions' in serverless.yml
functions:
  createUser: # Function name
    handler: handler.users # Reference to file handler.js & exported function 'users'
    events: # All events associated with this function
      - http:
          path: users/create
          method: post
      - http:
          path: users/update
          method: put
      - http:
          path: users/delete
          method: delete

Define an http event for the function you need and declare one for each path you need with and without the query param.

The trick is going to be in the lambda itself where you're going to have to set up a few conditions or try/catch statements to deal with the fact that in some cases you won't have a queryparam and in others you will but that's not too hard to deal with.