Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lambda together with API Gateway #69

Closed
Mojo90 opened this issue Feb 10, 2017 · 7 comments
Closed

Lambda together with API Gateway #69

Mojo90 opened this issue Feb 10, 2017 · 7 comments
Labels

Comments

@Mojo90
Copy link

Mojo90 commented Feb 10, 2017

I use a stack where API Gateway invokes Lambda Function via aws_proxy and this works great. The docs of aws says Requests will be proxied to Lambda with request details available in the "context" of your handler function.
So I am wondering if I can invoke it the same way local with this plugin? I did a few tests and generally the invocation works good but didn't get it to run as I needed to.
e.g. apigateway gets a get request to path hello and this invokes the lambda function with a proxy and you get a corresponding answer (normal rest api).

@ashiina
Copy link
Owner

ashiina commented Feb 11, 2017

Hi! So I believe you are asking for some request details to be set inside context?
If that is the case, I totally agree. But I would want to see the official specifications of when&what information is set into context.

As far as I have researched:

  1. the request details from API Gateway are set inside the event, not context
    http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html

With the Lambda proxy integration, API Gateway maps the entire client request to the input event parameter of the back-end Lambda function as follows:

  1. The official documentation of the context object does not mention anything about request details from API Gateway
    http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html

I'd appreciate it if you can show me where you found the documentation.
Thanks!

@Mojo90
Copy link
Author

Mojo90 commented Feb 11, 2017

To be honest I searched for a while now and it was not from the docs it was from tooltips in API Gateway:
screen shot 2017-02-11 at 16 11 51

So I think you already pointed to the correct URL to this Section: Input Format of a Lambda Function for Proxy Integration http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-set-up-simple-proxy.html#api-gateway-simple-proxy-for-lambda-input-format

I tried it with an event based on above url but I get a 500 error with [Error: "value" required in setHeader("x-apigateway-context", value).]

@mitchell-johnson
Copy link

mitchell-johnson commented Feb 12, 2017

What is stopping you from adding the full content of the API gateway request to your sample input data eg:

module.exports = {
    resource: '/{proxy+}',
    path: '/proxy',
    httpMethod: 'POST',
    headers: {
        Accept: '*/*',
        'Accept-Encoding': 'deflate, gzip',
        'CloudFront-Forwarded-Proto': 'https',
        'CloudFront-Is-Desktop-Viewer': 'true',
        'CloudFront-Is-Mobile-Viewer': 'false',
        'CloudFront-Is-SmartTV-Viewer': 'false',
        'CloudFront-Is-Tablet-Viewer': 'false',
        'CloudFront-Viewer-Country': 'US',
        'Content-Type': 'application/json',
        Host: 'xxx.execute-api.ap-southeast-2.amazonaws.com',
        Via: '1.1 xxx.cloudfront.net (CloudFront)',
        'X-Amz-Cf-Id': 'xxx',
        'X-Forwarded-For': '69.63.188.127, 54.239.134.6',
        'X-Forwarded-Port': '443',
        'X-Forwarded-Proto': 'https',
        'X-Hub-Signature': 'sha1=xxx'
    },
    queryStringParameters: null,
    pathParameters: {
        proxy: 'proxy'
    },
    stageVariables: null,
    requestContext: {
        accountId: 'xxx',
        resourceId: '10999l',
        stage: 'Prod',
        requestId: '23dcdd78-eebf-11e6-97f8-25bc6590f380',
        identity: {
            cognitoIdentityPoolId: null,
            accountId: null,
            cognitoIdentityId: null,
            caller: null,
            apiKey: null,
            sourceIp: '69.63.188.127',
            accessKey: null,
            cognitoAuthenticationType: null,
            cognitoAuthenticationProvider: null,
            userArn: null,
            userAgent: null,
            user: null
        },
        resourcePath: '/{proxy+}',
        httpMethod: 'POST',
        apiId: 'jq8asr1y7f'
    },
    body: '{"object":"page","entry":[{"id":"xxx","time":1486641538051,"messaging":[{"sender":{"id":"xxx"},"recipient":{"id":"xxx"},"timestamp":1486596726994,"message":{"mid":"mid.1486596726994:606c1bfc42","seq":221055,"text":"test"}}]}]}',
    isBase64Encoded: false
}

@Mojo90
Copy link
Author

Mojo90 commented Feb 12, 2017

@mitchell-johnson As I mentioned, I tried with such an event but got a 500-Error and the comment: [Error: "value" required in setHeader("x-apigateway-context", value).]

@ashiina
Copy link
Owner

ashiina commented Feb 16, 2017

@Mojo90 I just tested this myself, and it turns out that as the Document states, all the request information is stored in the event of the handler.
Therefore, as @mitchell-johnson states, you should be able to pass it into lambda-local as an input data.
You should also try and look at all of the event and context data, and you should be able to verify this yourself.

The text on the console (the screenshot you pasted) turns out to be wrong... A silly mistake on AWS's part.

http://willhamill.com/2016/12/12/aws-api-gateway-lambda-proxy-request-and-response-objects

@ashiina
Copy link
Owner

ashiina commented Feb 16, 2017

[Error: "value" required in setHeader("x-apigateway-context", value).]

This sounds like a completely different issue. If you want help with this you should post your actual Lambda code.

@Mojo90
Copy link
Author

Mojo90 commented Feb 16, 2017

I am currently using swagger-node with aws-serverless-express.
To reproduce this error:

If you don't have used swagger before install it with:

$ npm install -g swagger

create swagger-node project (use express):

$ swagger project create hello-world
$ cd hello-world/
$ npm i --save aws-serverless-express

update app.js:

'use strict';

var SwaggerExpress = require('swagger-express-mw');
var app = require('express')();
module.exports = app; // for testing

var awsServerlessExpressMiddleware = require('aws-serverless-express/middleware');

app.use(awsServerlessExpressMiddleware.eventContext());

var config = {
  appRoot: __dirname // required config
};

SwaggerExpress.create(config, function(err, swaggerExpress) {
  if (err) { throw err; }

  // install middleware
  swaggerExpress.register(app);

  var port = process.env.PORT || 10010;
  app.listen(port);

  if (swaggerExpress.runner.swagger.paths['/hello']) {
    console.log('try this:\ncurl http://127.0.0.1:' + port + '/hello?name=Scott');
  }
});

add lambda.js:

const awsServerlessExpress = require('aws-serverless-express');
const app = require('./app');
const server = awsServerlessExpress.createServer(app);

exports.handler = (event, context) => awsServerlessExpress.proxy(server, event, context);

add test-event.js:

module.exports = module.exports = {
    resource: '/{proxy+}',
    path: '/proxy',
    httpMethod: 'POST',
    headers: {
        Accept: '*/*',
        'Accept-Encoding': 'deflate, gzip',
        'CloudFront-Forwarded-Proto': 'https',
        'CloudFront-Is-Desktop-Viewer': 'true',
        'CloudFront-Is-Mobile-Viewer': 'false',
        'CloudFront-Is-SmartTV-Viewer': 'false',
        'CloudFront-Is-Tablet-Viewer': 'false',
        'CloudFront-Viewer-Country': 'US',
        'Content-Type': 'application/json',
        Host: 'xxx.execute-api.ap-southeast-2.amazonaws.com',
        Via: '1.1 xxx.cloudfront.net (CloudFront)',
        'X-Amz-Cf-Id': 'xxx',
        'X-Forwarded-For': '69.63.188.127, 54.239.134.6',
        'X-Forwarded-Port': '443',
        'X-Forwarded-Proto': 'https',
        'X-Hub-Signature': 'sha1=xxx'
    },
    queryStringParameters: null,
    pathParameters: {
        proxy: 'proxy'
    },
    stageVariables: null,
    requestContext: {
        accountId: 'xxx',
        resourceId: '10999l',
        stage: 'Prod',
        requestId: '23dcdd78-eebf-11e6-97f8-25bc6590f380',
        identity: {
            cognitoIdentityPoolId: null,
            accountId: null,
            cognitoIdentityId: null,
            caller: null,
            apiKey: null,
            sourceIp: '69.63.188.127',
            accessKey: null,
            cognitoAuthenticationType: null,
            cognitoAuthenticationProvider: null,
            userArn: null,
            userAgent: null,
            user: null
        },
        resourcePath: '/{proxy+}',
        httpMethod: 'POST',
        apiId: 'jq8asr1y7f'
    },
    body: '{"object":"page","entry":[{"id":"xxx","time":1486641538051,"messaging":[{"sender":{"id":"xxx"},"recipient":{"id":"xxx"},"timestamp":1486596726994,"message":{"mid":"mid.1486596726994:606c1bfc42","seq":221055,"text":"test"}}]}]}',
    isBase64Encoded: false
};

now run:

$ lambda-local -l lambda.js -e test-event.js

output:

info: Logs
info: ------
info: START RequestId: 7fe40093-8ca7-22f3-6c7f-b8ade54aac7d
EADDRINUSE /tmp/server0.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server1.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server2.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server3.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server4.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server5.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server6.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server7.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server8.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server9.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server10.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server11.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server12.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server13.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server14.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server15.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server16.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server17.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server18.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server19.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server20.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server21.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server22.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server23.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server24.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server25.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server26.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server27.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server28.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server29.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server30.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server31.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server32.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server33.sock incrementing socketPathSuffix.
EADDRINUSE /tmp/server34.sock incrementing socketPathSuffix.
[Error: `value` required in setHeader("x-apigateway-context", value).]
info: END
info: Message
info: ------
info: {
	"statusCode": 500,
	"body": "",
	"headers": {}
}
info: -----
info: lambda-local successfully complete.

so does not work for me. At least a 404 should occur, as a 404 occurs when executing lambda function in aws console and no event data with proxy information is setted. Thx for your time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants