_Note: My function is working correctly on the real AWS Lambda service!_
Could anyone suggestion why 'sam local start-api' is failing to parse responses but call the function directly works fine?
Parse failure results in 500 response:
bash
2017/10/02 09:43:22 Function returned an invalid response (must include one of: body, headers or statusCode in the response object): invalid character '-' after top-level value
Function invoke appears to be working:
````bash
$ sam local invoke "Hapihello" -e event.json
2017/10/02 09:46:21 Successfully parsed template.yml
2017/10/02 09:46:21 Connected to Docker 1.30
2017/10/02 09:46:21 Fetching lambci/lambda:nodejs6.10 image for nodejs6.10 runtime...
nodejs6.10: Pulling from lambci/lambda
Digest: sha256:7eb4ced6a15ae3c30effc4ec0cd3aabb2bd57c9a8330b37920c3d5d722d81083
Status: Image is up to date for lambci/lambda:nodejs6.10
2017/10/02 09:46:22 Invoking index.handler (nodejs6.10)
START RequestId: 70e1b93c-0e32-19ce-53b1-537a0d2d6381 Version: $LATEST
2017-10-02T08:46:24.192Z 70e1b93c-0e32-19ce-53b1-537a0d2d6381 Registering plugins!!!!
2017-10-02T08:46:24.540Z 70e1b93c-0e32-19ce-53b1-537a0d2d6381 Setting Host to 8ed23ddcaefb:8000
2017-10-02 08:46:24,545, [response] http://8ed23ddcaefb:8000: get /Property-API/0.0.1/api-docs {} 200 (18ms)
END RequestId: 70e1b93c-0e32-19ce-53b1-537a0d2d6381
REPORT RequestId: 70e1b93c-0e32-19ce-53b1-537a0d2d6381 Duration: 1140.68 ms Billed Duration: 0 ms Memory Size: 0 MB Max Memory Used: 60 MB
{"statusCode":200,"body":"{\"swagger\":\"2.0\",\"info\":{\"version\":\"0.0.1\",\"title\":\"Property API\",\"description\":\"An API to query
````
I'm running
For me the API server starts fine and serves events but they fail with a strange parse error:
````bash
alexb@DESKTOP-5HFQQQL MINGW64 ~/PhpstormProjects/swaggerizeTest (master)
$ sam local start-api
2017/10/02 09:43:13 Connected to Docker 1.30
2017/10/02 09:43:13 Fetching lambci/lambda:nodejs6.10 image for nodejs6.10 runtime...
nodejs6.10: Pulling from lambci/lambda
Digest: sha256:7eb4ced6a15ae3c30effc4ec0cd3aabb2bd57c9a8330b37920c3d5d722d81083
Status: Image is up to date for lambci/lambda:nodejs6.10
Mounting index.handler (nodejs6.10) at http://127.0.0.1:3000/Property-API/0.0.1/api-docs [GET]
Mounting static files from public at /
You can now browse to the above endpoints to invoke your functions.
You do not need to restart/reload SAM CLI while working on your functions,
changes will be reflected instantly/automatically. You only need to restart
SAM CLI if you update your AWS SAM template.
2017/10/02 09:43:20 Invoking index.handler (nodejs6.10)
START RequestId: 1241967b-5342-17a2-79d5-7d76b518bc81 Version: $LATEST
2017-10-02T08:43:22.361Z 1241967b-5342-17a2-79d5-7d76b518bc81 Registering plugins!!!!
2017-10-02T08:43:22.712Z 1241967b-5342-17a2-79d5-7d76b518bc81 Setting Host to 4b2cfc67527a:8000
END RequestId: 1241967b-5342-17a2-79d5-7d76b518bc81
REPORT RequestId: 1241967b-5342-17a2-79d5-7d76b518bc81 Duration: 1241.16 ms Billed Duration: 0 ms Memory Size: 0 MB Max Memory Used: 59 MB
2017/10/02 09:43:22 Function returned an invalid response (must include one of: body, headers or statusCode in the response object): invalid character '-' after top-level value
````
The contents of my template.yml:
````bash
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
Hapihello:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs6.10
Events:
ApiDocs:
Type: Api
Properties:
Path: /Property-API/0.0.1/api-docs
Method: get
````
The contents of my index.js:
````javascript
'use strict';
const server = require('./server');
/**
server.makeReady((err) => {
if (err) throw err;
// map lambda event to hapi request
const options = {
method: event.httpMethod,
url: event.path,
payload: event.body,
headers: event.headers,
validate: false
};
server.inject(options, function (res) {
const response = {
statusCode: res.statusCode,
body: JSON.stringify(res.result),
};
callback(null, response);
});
});
};
````
The contents of my server.js:
````javascript
'use strict';
let Hapi = require('hapi');
let Swaggerize = require('swaggerize-hapi');
let Path = require('path');
const config = require('./config'); // application configuration
const monitor = require('./monitor'); // Monitoring, logging
let Server = new Hapi.Server();
Server.connection({
port: 8000
});
const plugins = [config, monitor];
let loaded = false;
Server.makeReady = function(onServerReady){
if(!loaded){
console.log('Registering plugins!!!!');
Server.register({
register: Swaggerize,
options: {
api: Path.resolve('./config/swagger.json'),
handlers: Path.resolve('./handlers')
}
}, function () {
Server.plugins.swagger.setHost(Server.info.host + ':' + Server.info.port);
console.log('Setting Host to %s:%d', Server.info.host, Server.info.port);
});
Server.register(plugins, onServerReady);
loaded = true;
}
else{
onServerReady(null);
}
};
module.exports = Server;
````
Many thanks for any suggestions / advice
Alex
not sure if this can be the prob but maybe it has to do with the Path: /Property-API/0.0.1/api-docs that it can not read the "-" did you try just making it an easy path like / or /production. just a sugestion
Just tried it with another URL which doesn't have a hyphen in the URL but same error.
Thanks for the suggestion though.
hmmm,
I had the same error but with a 'p' and found out it had something to do with my Json parsing but not sure if that is the same in your case.
{in: " 42 \x01", err: &SyntaxError{"invalid character '\x01' after top-level value", 5}}, something to do with unmarsheling in the .go file as i can see quicklly from here: https://golang.org/src/encoding/json/decode_test.go line 430
The error signifies that SAM Local couldn't parse your response properly. Since invoke works, I suspect there is a problem with generating the event from the HTTP request you're sending. This problem may be solved by #143, but to be sure I need to view event.json
Thanks,
I used the generate-event command to create the event.json file the tweaked proxy and path's manually. I didn't really know what I was doing but this seemed sensible haha
javascript
{
"body": "{ \"test\": \"body\"}",
"resource": "/{proxy+}",
"requestContext": {
"resourceId": "123456",
"apiId": "1234567890",
"resourcePath": "/{proxy+}",
"httpMethod": "POST",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"accountId": "123456789012",
"identity": {
"apiKey": null,
"userArn": null,
"cognitoAuthenticationType": null,
"caller": null,
"userAgent": "Custom User Agent String",
"user": null,
"cognitoIdentityPoolId": null,
"cognitoIdentityId": null,
"cognitoAuthenticationProvider": null,
"sourceIp": "127.0.0.1",
"accountId": null
},
"stage": "prod"
},
"queryStringParameters": {
"foo": "bar"
},
"headers": {
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
"Accept-Language": "en-US,en;q=0.8",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Mobile-Viewer": "false",
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
"CloudFront-Viewer-Country": "US",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Upgrade-Insecure-Requests": "1",
"X-Forwarded-Port": "443",
"Host": "1234567890.execute-api.us-east-1.amazonaws.com",
"X-Forwarded-Proto": "https",
"X-Amz-Cf-Id": "aaaaaaaaaae3VYQb9jd-nvCd-de396Uhbp027Y2JvkCPNLmGJHqlaA==",
"CloudFront-Is-Tablet-Viewer": "false",
"Cache-Control": "max-age=0",
"User-Agent": "Custom User Agent String",
"CloudFront-Forwarded-Proto": "https",
"Accept-Encoding": "gzip, deflate, sdch"
},
"pathParameters": {
"proxy": "/Property-API/0.0.1/api-docs"
},
"httpMethod": "GET",
"stageVariables": {
"baz": "qux"
},
"path": "/Property-API/0.0.1/api-docs"
}
I'm also encountering something like this issue.
2018/01/07 19:26:04 Function returned an invalid response (must include one of: body, headers or statusCode in the response object): json: cannot unmarshal string into Go value of type struct { StatusCode json.Number "json:\"statusCode\""; Headers map[string]string "json:\"headers\""; Body json.Number "json:\"body\"" }
It has to do w/ the callback object. If I try to pass in something that is not a JSON object, such as a plain string message.
callback(null, "success");
then i get the error:
2018/01/07 19:35:02 Function returned an invalid response (must include one of: body, headers or statusCode in the response object): json: cannot unmarshal string into Go value of type struct { StatusCode json.Number "json:\"statusCode\""; Headers map[string]string "json:\"headers\""; Body json.Number "json:\"body\"" }
If I create the callback object as an json object similar to the error message, then it does return 200 OK and quiets down.
however, looking at lambda docs - it seems to indicate that returning a value of any type (string, structure or nothing) should be a valid behavior.
See Set up Lambda Proxy Integrations in API Gateway
The expectation is that your handler will return a special JSON document that can be used by API Gateway to construct a proper HTTP response:
{
"isBase64Encoded": true|false,
"statusCode": httpStatusCode,
"headers": { "headerName": "headerValue", ... },
"body": "..."
}
@abatkin thanks for pointing that out. i did not realize sam integration extended to including api gateway but now the response format warning makes sense.
If you turn off all logging output, does the issue go away? I know there is an issue with the Java runtime where the sam runtime takes some of the log messages in as part of the response. This sounds like a similar issue
Can you try the latest release - https://github.com/awslabs/aws-sam-cli/releases/tag/v0.3.0? I believe this is fixed. Feel free to re-open Issue if not.
@sanathkr This issue still exists on sam 0.14.2. And the root cause, as mentioned by @sbuzonas , is due to log messages. Setting root log level to ERROR solved this problem.
@seanyinx Logging within your Java function? If so, yes this can happen because of how docker-lambda containers handle and return response & logs via the same stream. If the logs gets interspersed with your response, then SAM CLI will fail to parse your response.
@sanathkr yes, thank you for clarification.
Most helpful comment
I'm also encountering something like this issue.
2018/01/07 19:26:04 Function returned an invalid response (must include one of: body, headers or statusCode in the response object): json: cannot unmarshal string into Go value of type struct { StatusCode json.Number "json:\"statusCode\""; Headers map[string]string "json:\"headers\""; Body json.Number "json:\"body\"" }It has to do w/ the callback object. If I try to pass in something that is not a JSON object, such as a plain string message.
callback(null, "success");then i get the error:
2018/01/07 19:35:02 Function returned an invalid response (must include one of: body, headers or statusCode in the response object): json: cannot unmarshal string into Go value of type struct { StatusCode json.Number "json:\"statusCode\""; Headers map[string]string "json:\"headers\""; Body json.Number "json:\"body\"" }If I create the callback object as an json object similar to the error message, then it does return 200 OK and quiets down.
however, looking at lambda docs - it seems to indicate that returning a value of any type (string, structure or nothing) should be a valid behavior.