Raw body payload in AWS API Gateway Body Mapping Template - json

For some reason I'm having a hard time getting the raw body from within the event. It's logging the $input.body as json for a application/json content-type. The docs say that that should contain the raw payload.
Here my Integration Request Body Mapping Template:
{
"body" : $input.json('$'),
"rawBody": $input.body,
"headers": {
#foreach($header in $input.params().header.keySet())
"$header": "$util.escapeJavaScript($input.params().header.get($header))" #if($foreach.hasNext),#end
#end
},
"method": "$context.httpMethod",
"params": {
#foreach($param in $input.params().path.keySet())
"$param": "$util.escapeJavaScript($input.params().path.get($param))" #if($foreach.hasNext),#end
#end
},
"query": {
#foreach($queryParam in $input.params().querystring.keySet())
"$queryParam": "$util.escapeJavaScript($input.params().querystring.get($queryParam))" #if($foreach.hasNext),#end
#end
}
}
Here's the payload example:
{
"event": {
"body": {
"hello": "meow"
},
"rawBody": {
"hello": "meow"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US",
"Cache-Control": "no-cache",
"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": "7nuy7lymef.execute-api.us-east-1.amazonaws.com",
"Origin": "file://",
"Postman-Token": "0ce7c6f4-3864-c9b4-f2db-739737b2ba49",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Postman/4.2.2 Chrome/47.0.2526.73 Electron/0.36.2 Safari/537.36",
"Via": "1.1 1eea0bca59557555878da4d9775c509f.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "SDjaGcuJ5eVkOMMCn6M3vGaVicA1fuA7h0bUYE4ARlKupO60eeYNFA==",
"X-Forwarded-For": "206.71.230.14, 205.251.250.135",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
"x_example_header": "my awesome header"
},
"method": "POST",
"params": {},
"query": {
"example_param": "myawesomeparam"
}
},
"context": {
"callbackWaitsForEmptyEventLoop": false,
"logGroupName": "/aws/lambda/reggi-log-post",
"logStreamName": "2016/06/08/[$LATEST]aad04e0e46614c288ac8ca43d0a95076",
"functionName": "reggi-log-post",
"memoryLimitInMB": "128",
"functionVersion": "$LATEST",
"invokeid": "6e4e1e13-2dc1-11e6-a1f7-4dad3a8eb122",
"awsRequestId": "6e4e1e13-2dc1-11e6-a1f7-4dad3a8eb122",
"invokedFunctionArn": "arn:aws:lambda:us-east-1:562508364089:function:reggi-log-post"
}
}
Is there any way to access the raw body from this request?
Is there any way to change the content-type to accept all types?

The following blog post explains in detail how to get around this problem. https://nicholasjackson.io/2016/12/13/using-graphql-with-aws-lambda/
It's written specifically in the context of GraphQL, but it will work for any content type. In short:
Go to the Binary Support section. Enable binary support for your chosen media type and save.
Return to the your method in Resources section and open Integration Request. Add/edit the body mapping template for your chosen content type and put the following:
"rawBody": "$util.escapeJavaScript($util.base64Decode($input.body))"
Save and redeploy the API.
Adding binary support encodes the request as a base64 string. The body mapping template decodes it.

$input.body contains the raw payload. You need to put quotes around it like "rawBody": "$input.body". Otherwise the body will be interpreted as part of the json document.

Related

How do I setup jmeter to make POST request with bearer token, api key and other parameters?

Can someone please show me how to make POST request in jmeter if I have a bearer token, x-api key, api url, and json body in this format:
{
"resourceType": "Bundle",
"type": "transaction",
"entry": [
{
"fullUrl": "08b4-4ee4-b51b-803e20ae8126",
"resource": {
"resourceType": "Player",
"name": [
{
"family": "Jameson",
"given": [
"Matt"
]
}
],
"request": {
"method": "POST",
"url": "Player"
}
}
]
}
Also how do I setup parameters as shown in image:
Image below shows how I set it up in postman, all parameters
https://ibb.co/C8dwQ2m
Add HTTP Request sampler to your Test Plan and put the URL and the JSON payload there
All the values which are at your screenshot stand for HTTP Headers so add a HTTP Header Manager and specify the values there:

event.body in lambda function is not an object even though application/json header exists

I have an API Gateway / lambda function set up with a LAMBDA_PROXY integration.
I have a POST resource which is sending a JSON object in the body like the following:
{
"version": 123,
"attributes": [
{
"id": 1123,
"type": "integer",
"defaultValue": 88
}
]
}
The POST request is sent with a Content-Type: application/json header.
I expect the lambda function to receive event.body as an object so that I will be able to reference the object like this:
const version = event.body.version;
In fact, this does not work and I am forced to run a JSON.parse() on event.body.
At first I was thinking that the content-type header was not getting to the lambda but then I printed to the log event.headers and the header is in fact there:
{
"Accept": "*/*",
"content-type": "application/json",
"Host": "jfpvip409c.execute-api.eu-west-1.amazonaws.com",
"User-Agent": "curl/7.65.0",
"X-Amzn-Trace-Id": "Root=1-5fe9940a-3f3634ce4ccd26f5211c21d1",
"X-Forwarded-For": "192.118.35.111",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
}
Can somebody please help me understand why this is the case ?
Thanks in advance
nsteiner

Why doesn't Autodesk Forge 'workflowAttribute' appear in webhook updates for Model Derivative work?

According to Forge API Reference, there is a workflowAttribute available to 'set some custom workflow information'. Its part of the misc object in the Body Structure of the POST request used to submit a job.
I am using the following request:
convertResponse = await axios({
method: "post",
url:
"https://developer.api.autodesk.com/modelderivative/v2/designdata/job",
headers: {
"Content-Type": "application/json",
Authorization: access_token
},
data: JSON.stringify({
input: { urn: url_safe_encoded_urn },
output: {
destination: { region: "us" },
formats: [
{
type: "svf",
views: ["2d", "3d"],
advanced: { generateMasterViews: true }
}
]
},
misc: {
workflow: "designgen-forge",
workflowAttribute: { projectId }
}
})
});
But when the webHook calls my callback function, I see nothing like hookAttribute available in the data:
{
"version": "1.0",
"resourceUrn": "dXJuOmFkc2sub2JqZWN0czpvcy5vYmplY3Q6c3VmZm9say1nZW5kZXNpZ25sb3ZlLWRldi10ZW1wLzkxZjhhNGZmLTM5NTYtNGM5Yi05NzkyLThiMWMxNDQyZGJkNyUyRnJldml0LTkxZjhhNGZmLTM5NTYtNGM5Yi05NzkyLThiMWMxNDQyZGJkNy5ydnQ",
"hook": {
"hookId": "6d770063-d5dc-4c66-8ed8-e84207ade07d",
"tenant": "designgen-forge",
"callbackUrl": "https://bigchief.ngrok.io/dev/workitemcomplete",
"createdBy": "9DqOEPqAd4ZZYQ2MAxuT2VQwMfAJrBGp",
"event": "extraction.updated",
"createdDate": "2020-10-20T20:14:31.874+0000",
"system": "derivative",
"creatorType": "Application",
"status": "active",
"scope": {
"workflow": "designgen-forge"
},
"urn": "urn:adsk.webhooks:events.hook:6d770063-d5dc-4c66-8ed8-e84207ade07d",
"__self__": "/systems/derivative/events/extraction.updated/hooks/6d770063-d5dc-4c66-8ed8-e84207ade07d"
},
"payload": {
"TimeStamp": 1603289180515,
"Env": "production",
"URN": "<my urn>",
"EventType": "UPDATED",
"Payload": {
"status": "inprogress",
"bubble": {
"guid": "<my guid>",
"owner": "<my guid>",
"hasThumbnail": "true",
"startedAt": "Wed Oct 21 14:05:39 UTC 2020",
"type": "design",
"urn": "<my urn>",
"success": "75%",
"progress": "50% complete",
"region": "US",
"status": "inprogress",
"children": []
},
"scope": "fd2d74bb-1d5a-407c-a344-20dffa327504",
"registerKey": []
}
}
}
I would imagine that is the intent of the workflowAttribute object to populate something in the callback data, otherwise, whats the point. Am I not specifying it correctly? Or is this not implemented? If not, webhooks become nearly unusable, I suppose the alternative is to make and destroy a webhook for each request, which is so ugly its not really a solution.
Thank you for bringing this to our attention. We could reproduce the issue as well - i.e. that the content of the workflowAttribute provided in the body of POST job request will not show up in the webhook callback.
It's being looked into, and I hope it will work soon, but I cannot yet provide a deadline for that.
In the meantime, the workaround could be either:
a) keep track of the extra data (in your case projectId) associated with the urn of the given file on the server or in a database (you might already be using one)
b) create separate webhooks, as you suggested, with different id for the "scope" -> "workflow" parameter and provide the data as the "hookAttribute" - that will show up in the callback
Update on 2020-12-14: it's working now - see https://forge.autodesk.com/blog/custom-data-translation-webhook

How can I test a CSP report-uri endpoint?

I've added a Content Security Policy to my website and made a report-uri endpoint with AWS API Gateway, Lambda, and DynamoDB. I've tested it with Postman using the following JSON
{
"resource": "/",
"path": "/",
"requestContext": {
"resourcePath": "/",
"httpMethod": "POST",
"path": "/latest"
},
"headers": {
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"accept-encoding": "gzip, deflate, br",
"Host": "70ixmpl4fl.execute-api.us-east-2.amazonaws.com",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36",
"X-Amzn-Trace-Id": "Root=1-5e66d96f-7491f09xmpl79d18acf3d050"
},
"multiValueHeaders": {
"accept": [
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
],
"accept-encoding": [
"gzip, deflate, br"
]
},
"queryStringParameters": null,
"multiValueQueryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"body": {
"csp-report": {
"document-uri": "https://example.com/signup.html",
"referrer": "",
"blocked-uri": "https://example.com/css/style.css",
"violated-directive": "style-src cdn.example.com",
"original-policy": "default-src 'none'; style-src cdn.example.com; report-uri /_/csp-reports"
}
},
"isBase64Encoded": false
}
It seems to work properly when using Postman. But when I added the endpoint to my Content Security Policy and attempt to violate the policy, I can't seem to get it to report correctly.
Does the JSON above adequately demonstrate what a real CSP violation would look like?
I've looked around and haven't seen much about developing your own endpoint. Any resources or other advice is greatly appreciated.
It depends on the browser
some browser sends the Json and CSP violation report some sends thec csp-report.
Few browser sends the request base64 encoded.
Specifically in chrome browser it sends base64 encoded and as Json format. In your payload.
Hopefully it answers your question.

How to encode special characters in Wiremock request body?

I'm using Wiremock server to mock responses and using JSON format to mock responses.
{
"request":
{
"url": "/token",
"method": "POST",
"bodyPatterns" : [{
"contains": "username=test_user#gmail.com&password=passwordtest_security_token"
}]
},
"response":
{
"status": 200,
"headers":
{
"Content-Type" : "application/json"
},
"jsonBody": {"message": "ok"}
}
This is not working as the '#' in the email is not encoded. I need to pass "test_user%40gmail" for the request to work.
Here the change is only at one place. But for other mocks, request bodies have many special characters**(#,%*\n\s)**. Is there any way to handle the encoding part in the Wiremock.
Also, is there way to encode the string in url?
In the above example there is an accolade missing which prevents is from loading in WireMock. The below example is complete:
{
"request": {
"url": "/token",
"method": "POST",
"bodyPatterns": [{
"contains": "username=test_user#gmail.com&password=passwordtest_security_token"
}
]
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"message": "ok"
}
}
}
In your question you highlighted that you need to use %40 instead of #. I have been unable to replicate this scenario. As I'm unsure if you're posting through a form, or raw string.
In the case that you use a regular Form Data option this results in failure to match.
But sending it as a raw body the result is quite the opposite. The example behaves exactly as you would described it should. Below is a screenshot of my Postman result: