SAM AWS Lambda Python: I create a function that receive a file with multipart/form-data
but when I send the following request
curl --location --request POST 'https://....execute-api.....amazonaws.com/Prod/ocrReceipt' \
--header 'Connection: keep-alive' \
--header 'Pragma: no-cache' \
--header 'Cache-Control: no-cache' \
--header 'Accept: application/json, text/plain, */*' \
--header 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36' \
--header 'Accept-Language: en-US,en;q=0.9,he;q=0.8' \
--form 'file=#"/D:/receipt.png"'
I get the event with missing Content-Length and "isBase64Encoded": false
and my code fail because I do fp = io.BytesIO(base64.b64decode(body)) # decode
when I access the same function with the Function URL I don't get this error (i.e. Content-Length is set and "isBase64Encoded": true
How can I config the gateway api to accept multipart/form-data properly?
I tried to set multipart/form-data and multipart/* in API > Settings > Binary Media Types
but it doesn't help
Not that is says You can configure binary support for your API by specifying which media types should be treated as binary types. API Gateway will look at the Content-Type and Accept HTTP headers to decide how to handle the body.
Did I set the correct value?
Can I fix it by some setting in the SAM template?
Event:
{"resource": "/ocrReceipt", "path": "/ocrReceipt", "httpMethod": "POST", "headers": {"Accept": "application/json, text/plain, */*", "Accept-Encoding": "gzip, deflate, br", "Accept-Language": "en-US,en;q=0.9,he;q=0.8", "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-ASN": "1680", "CloudFront-Viewer-Country": "IL", "Content-Type": "multipart/form-data; boundary=--------------------------592233465752962090703619", "Host": "6y5o0gb78g.execute-api.eu-west-3.amazonaws.com", "Origin": "https://doc2txt.com", "Postman-Token": "f39dea09-b71f-47bb-aa8a-57783df2ddf1", "Pragma": "no-cache", "Referer": "https://doc2txt.com/", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", "Via": "1.1 759e09affff41285e9585e1a31532bd4.cloudfront.net (CloudFront)", "X-Amz-Cf-Id": "5jCh7W91ayJWUf_75DfWr-IfCj2CvCobvTlshBjoqaElhVWsNmlFuA==", "X-Amzn-Trace-Id": "Root=1-63b7df99-5a343d1a16ca5cde72a47d66", "X-Forwarded-For": "176.12.157.166, 130.176.1.83", "X-Forwarded-Port": "443", "X-Forwarded-Proto": "https"}, "multiValueHeaders": {"Accept": ["application/json, text/plain, */*"], "Accept-Encoding": ["gzip, deflate, br"], "Accept-Language": ["en-US,en;q=0.9,he;q=0.8"], "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-ASN": ["1680"], "CloudFront-Viewer-Country": ["IL"], "Content-Type": ["multipart/form-data; boundary=--------------------------592233465752962090703619"], "Host": ["6y5o0gb78g.execute-api.eu-west-3.amazonaws.com"], "Origin": ["https://doc2txt.com"], "Postman-Token": ["f39dea09-b71f-47bb-aa8a-57783df2ddf1"], "Pragma": ["no-cache"], "Referer": ["https://doc2txt.com/"], "User-Agent": ["Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36"], "Via": ["1.1 759e09affff41285e9585e1a31532bd4.cloudfront.net (CloudFront)"], "X-Amz-Cf-Id": ["5jCh7W91ayJWUf_75DfWr-IfCj2CvCobvTlshBjoqaElhVWsNmlFuA=="], "X-Amzn-Trace-Id": ["Root=1-63b7df99-5a343d1a16ca5cde72a47d66"], "X-Forwarded-For": ["176.12.157.166, 130.176.1.83"], "X-Forwarded-Port": ["443"], "X-Forwarded-Proto": ["https"]}, "queryStringParameters": null, "multiValueQueryStringParameters": null, "pathParameters": null, "stageVariables": null, "requestContext": {"resourceId": "7g6rs7", "resourcePath": "/ocrReceipt", "httpMethod": "POST", "extendedRequestId": "eT_iDFWXCGYFfyQ=", "requestTime": "06/Jan/2023:08:45:26 +0000", "path": "/Prod/ocrReceipt", "accountId": "899418482974", "protocol": "HTTP/1.1", "stage": "Prod", "domainPrefix": "6y5o0gb78g", "requestTimeEpoch": 1672994726594, "requestId": "8a23ce92-11fe-4e54-bbb0-5ad355130833", "identity": {"cognitoIdentityPoolId": null, "accountId": null, "cognitoIdentityId": null, "caller": null, "sourceIp": "176.12.157.166", "principalOrgId": null, "accessKey": null, "cognitoAuthenticationType": null, "cognitoAuthenticationProvider": null, "userArn": null, "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", "user": null}, "domainName": "6y5o0gb78g.execute-api.eu-west-3.amazonaws.com", "apiId": "6y5o0gb78g"}, "body": "...", "isBase64Encoded": false}
template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
python3.8
Sample SAM Template for ocrSam
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
MemorySize: 128
Resources:
Doc2txtFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
Timeout: 60
Role: arn:aws:iam::899418482974:role/service-role/ocrReceipt-role-v2edsg0i
PackageType: Image
Architectures:
- x86_64
Events:
Doc2txt:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /ocrReceipt
Method: ANY
Metadata:
Dockerfile: Dockerfile
DockerContext: ./doc2txt
DockerTag: python3.8-v1
Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
Doc2txtApi:
Description: "API Gateway endpoint URL for Prod stage for Doc2txt function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/ocrReceipt/"
Doc2txtFunction:
Description: "Doc2txt Lambda Function ARN"
Value: !GetAtt Doc2txtFunction.Arn
Doc2txtFunctionIamRole:
Description: "Implicit IAM Role created for Doc2txt function"
Value: arn:aws:iam::899418482974:role/service-role/ocrReceipt-role-v2edsg0i #!GetAtt Doc2txtFunctionRole.Arn
EDIT:
I was able to get "isBase64Encoded": true with the following:
Globals:
Api:
BinaryMediaTypes:
- "*/*"
I was able to get "isBase64Encoded": true with the following:
Globals:
Api:
BinaryMediaTypes:
- "*/*"
apparently the content-lenght is not necessary, so I just remove it from the code:
headers = {
"content-type": headers["Content-Type"],
# "content-length": headers["Content-Length"],
}
fs = cgi.FieldStorage(fp=fp, environ=environ, headers=headers)
Related
I am using Zalando/LogBook in my Spring Boot with Maven project, I have added dependency logbook-spring-boot-starter in my pom.xml.
Everything is working fine, i have a userId field which after validating the authorization token in Spring Filter Chain i want to set it with each input request that LogBook Intercept.
Is there a way to add custom userId header in each request once it validates Spring Filter Chain.
<dependency>
<groupId>org.zalando</groupId>
<artifactId>logbook-spring-boot-starter</artifactId>
<version>2.14.0</version>
</dependency>
Presently I have
{
"origin": "remote",
"type": "request",
"correlation": "f99b6ba7d39911aa",
"protocol": "HTTP/1.1",
"remote": "0:0:0:0:0:0:0:1",
"method": "GET",
"uri": "/",
"host": "localhost",
"path": "",
"scheme": "http",
"port": "8080",
"headers": {
"user-agent": [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
]
}
}
What i want is
{
"origin": "remote",
"type": "request",
"correlation": "f99b6ba7d39911aa",
"userId" : "123",
"protocol": "HTTP/1.1",
"remote": "0:0:0:0:0:0:0:1",
"method": "GET",
"uri": "/",
"host": "localhost",
"path": "",
"scheme": "http",
"port": "8080",
"headers": {
"user-agent": [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
]
}
}
I updated the API (rest) via the amplify CLI to add a path and function (go 1.x), and within the function, I was able to retrieve the user ID via the following:
event.RequestContext.Identity.CognitoAuthenticationProvider
and this worked just fine.
I repeated the same steps above, however, when trying to retrieve the user id (sub) from the same as above, nothing is being retrieved. I'm not sure why, I've checked API gateway, and the settings seem to be the same, but maybe I'm missing something?
Any idea how to get the user id/sub in the function?
further info:
When accessing the "invoke URL" for the former function, an error message shows:
{"message":"Missing Authentication Token"}
However, this is not the case when accessing the invoke URL for the latter function. The latter function is not expecting an authentication token, how can that be changed?
EDIT: as requested, the JSON response for event.RequestContext:
{
"accountId": "000000000000",
"resourceId": "00aaaa",
"stage": "dev",
"domainName": "a00aaaaa00.execute-api.eu-west-2.amazonaws.com",
"domainPrefix": "a00aaaaa00",
"requestId": "000aa0a0-000a-0000-0000-aa0000a00aaa",
"protocol": "HTTP/1.1",
"identity": {
"cognitoIdentityPoolId": "",
"accountId": "",
"cognitoIdentityId": "",
"caller": "",
"apiKey": "",
"apiKeyId": "",
"accessKey": "",
"sourceIp": "00.000.000.000",
"cognitoAuthenticationType": "",
"cognitoAuthenticationProvider": "",
"userArn": "",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36",
"user": ""
},
"resourcePath": "/xxxxpath",
"path": "/dev/xxxxpath",
"authorizer": null,
"httpMethod": "POST",
"requestTime": "14/May/2022:23:09:05 +0000",
"requestTimeEpoch": 1652569745072,
"apiId": "a00aaaaa00"
}
Thanks
I have a very simple handler that I'm using to familiarize myself with serverless lambda functions.
const example: APIGatewayProxyHandler = async event => {
console.log(JSON.stringify(event, null, 2));
return {
statusCode: 200,
body: JSON.stringify({
message: 'Success',
}),
};
};
Here is my serverless.yml file:
service: lambda-example
frameworkVersion: '2'
provider:
name: aws
runtime: nodejs12.x
plugins:
- serverless-offline
functions:
example:
handler: lib/handler.example
events:
- http:
path: example
method: get
integration: lambda
When I hit the API it works just fine...
{
statusCode: 200,
body: "{"message":"Success"}"
}
I'm using this URL to trigger the event http://localhost:3000/dev/example?url=https://google.com/ and I'm console logging the event itself when the endpoint is hit...
{
"body": {},
"method": "GET",
"principalId": "offlineContext_authorizer_principalId",
"stage": "dev",
"cognitoPoolClaims": {
"sub": ""
},
"enhancedAuthContext": {
"principalId": "offlineContext_authorizer_principalId"
},
"headers": {
"Host": "localhost:3000",
"Connection": "keep-alive",
"Cache-Control": "max-age=0",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Sec-Fetch-Site": "none",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-User": "?1",
"Sec-Fetch-Dest": "document",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.9,la;q=0.8"
},
"query": {
"url": "https://google.com/"
},
"path": {},
"identity": {
"accountId": "offlineContext_accountId",
"apiKey": "offlineContext_apiKey",
"apiKeyId": "offlineContext_apiKeyId",
"caller": "offlineContext_caller",
"cognitoAuthenticationProvider": "offlineContext_cognitoAuthenticationProvider",
"cognitoAuthenticationType": "offlineContext_cognitoAuthenticationType",
"sourceIp": "127.0.0.1",
"user": "offlineContext_user",
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36",
"userArn": "offlineContext_userArn"
},
"stageVariables": {},
"requestPath": "/example"
}
I'm interested in accessing the 'query' attribute of this object but TypeScript gets mad at me when I try...
console.log(event.query);
===
Property 'query' does not exist on type 'APIGatewayProxyEvent'.
The query attribute very clearly exists on the event object as shown in my console log so I'm assuming I'm incorrectly typing this function, but I can't seem to find the proper type. What am I doing wrong here?
Additional Info (package.json):
"dependencies": {
"axios": "^0.21.0",
"cheerio": "^1.0.0-rc.3"
},
"devDependencies": {
"#types/aws-lambda": "^8.10.64",
"#types/cheerio": "^0.22.22",
"#types/node": "^14.14.2",
"#typescript-eslint/eslint-plugin": "^4.5.0",
"#typescript-eslint/parser": "^4.5.0",
"eslint": "^7.12.0",
"eslint-config-prettier": "^6.14.0",
"husky": "^4.3.0",
"prettier": "^2.1.2",
"prettier-plugin-organize-imports": "^1.1.1",
"serverless-dotenv-plugin": "^3.1.0",
"serverless-offline": "^6.8.0",
"typescript": "^4.0.3"
}
It turns out the problem was the
integration: lambda
addition to my serverless.yml file. When I removed this line the APIGatewayProxyHandler interface worked as expected.
I am using the serverless framework to deploy a simple lambda (written in node/ express) behind api gateway...
In a GET I can see the origin header, but in a POST I cannot - it's not passed into my lambda function!
Anyone know why not and how to make it pass?
Background:
I did notice that in the POST the origin appears to be appended to the query string in the logs:
originalUrl: '/dev/endpoint?Origin=MY%20ORIGIN%20HERE',
So, I could extract the origin from the query string values, but I want to know if this is the correct way to do things on the serverless framework or should I be setting something to allow the API Gateway to send the origin through on a POST like it does on a GET ? Why are the 2 verbs behaving differently?
My Code/ Config:
the function definition in the serverless.yml looks like:
myGetFunction:
handler: lambda/index.handler
events:
- http:
path: /endpoint
method: get
cors: true
myPostFunction:
handler: lambda/index.handler
events:
- http:
path: /endpoint
method: post
cors: true
If I just put the following in my index.handler:
app.use((req, res) => {
console.log('LOG REQUEST', req)
res.send('interesting')
})
In my handler function, I only want to get the origin request header that was sent. In the GET it's easy: the cloudwatch logs show that it's available in the GET request in the headers object:
headers:
{
accept: '*/*',
'accept-encoding': 'gzip, deflate',
'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': 'GB',
host: 'X.execute-api.us-east-1.amazonaws.com',
origin: 'MY ORIGIN HERE',
BUT: in the POST all the other headers are there, but origin is blank.
I did a bit of digging on this and ran into a couple realizations.
By default, it seems that no "origin" header passed in the API Gateway events. (I created a fresh serverless project, and just echoed back exactly what the API gateway event was.) So this is coming from some other source. I figured it may be a custom domain, and tested that. No dice.
My only other guess is that you have this behind some other layer (CloudFront?) that is forwarding these headers for you. If that ends up being the case, I would suggest you look and see if you can make it forward these headers for the POST request as it is for the GET request.
My only other final thought if none of the above is true is that there is some magic going on in some of the express middleware. I doubt this is the case.
For reference, this was my full serverless.yml and handler.js I tested with as well as a full unaltered event object I got in the endpoint.
service: so-test
provider:
name: aws
runtime: nodejs8.10
functions:
myGetFunction:
handler: handler.hello
events:
- http:
path: /endpoint
method: get
cors: true
myPostFunction:
handler: handler.hello
events:
- http:
path: /endpoint
method: post
cors: true
And the nodejs code:
'use strict';
module.exports.hello = async (event, context) => {
return {
statusCode: 200,
body: JSON.stringify({
message: 'Go Serverless v1.0! Your function executed successfully!',
input: event,
}),
};
};
Finally the response object
{
"message": "Go Serverless v1.0! Your function executed successfully!",
"input": {
"resource": "/endpoint",
"path": "/test/endpoint",
"httpMethod": "GET",
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.9",
"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",
"Host": "so-test.serverless-examples.com",
"upgrade-insecure-requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"Via": "2.0 f92491812e422470607f365e923929b5.cloudfront.net (CloudFront)",
"X-Amz-Cf-Id": "6AwZPV3uCYxseJIAmsGzhApzRostCiLXwwM3XsbSJP4K8hQx11MSgw==",
"X-Amzn-Trace-Id": "Root=1-5c086dd9-bce03ab0c216116fa6de9786",
"X-Forwarded-For": "55.55.55.555, 70.132.32.155",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"multiValueHeaders": {
"Accept": [
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"
],
"Accept-Encoding": [
"gzip, deflate, br"
],
"Accept-Language": [
"en-US,en;q=0.9"
],
"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"
],
"Host": [
"so-test.serverless-examples.com"
],
"upgrade-insecure-requests": [
"1"
],
"User-Agent": [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
],
"Via": [
"2.0 f92491812e422470607f365e923929b5.cloudfront.net (CloudFront)"
],
"X-Amz-Cf-Id": [
"6AwZPV3uCYxseJIAmsGzhApzRostCiLXwwM3XsbSJP4K8hQx11MSgw=="
],
"X-Amzn-Trace-Id": [
"Root=1-5c086dd9-bce03ab0c216116fa6de9786"
],
"X-Forwarded-For": [
"55.55.55.555, 70.132.32.155"
],
"X-Forwarded-Port": [
"443"
],
"X-Forwarded-Proto": [
"https"
]
},
"queryStringParameters": null,
"multiValueQueryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
"resourceId": "mftg6x",
"resourcePath": "/endpoint",
"httpMethod": "GET",
"extendedRequestId": "RdYZ7HaxoAMFQYQ=",
"requestTime": "06/Dec/2018:00:31:21 +0000",
"path": "/test/endpoint",
"accountId": "800708648372",
"protocol": "HTTP/1.1",
"stage": "dev",
"domainPrefix": "so-test",
"requestTimeEpoch": 1544056281163,
"requestId": "410632a3-f8ee-11e8-a7e2-7d886f93a0e4",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"sourceIp": "55.55.55.555",
"accessKey": null,
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
"user": null
},
"domainName": "so-test.serverless-examples.com",
"apiId": "txctij0cnp"
},
"body": null,
"isBase64Encoded": false
}
}
We are testing an add-in for Excel that has a form that is POSTed to https://httpbin.org/anything. The form will not POST in Excel 2016 version 15.39 (171010) for Mac (High Sierra ver 10.13.1). Here are the HTML form’s essentials:
<script type="text/javascript">
//submit form
$("#testForm").submit();
</script>
</head>
<body>
<form method="POST" id="testForm" action="https://httpbin.org/anything" accept-charset="UTF-8" target="_blank">
<div>
<input type='hidden' name='mergeDataFormat' value='csv'>
</div>
<div>
<input type="hidden" name="mergeData" id="mergeData" value='Name,Street,"City, State",ZIP Code'>
</div>
<input type="submit" value="Send" id="submitForm" />
</form>
AppDomain was set in the Manifest:
<AppDomains>
<AppDomain>https://httpbin.org/</AppDomain>
...
</AppDomains>
This is what we see in Charles HTTP monitor ver 4.2:
GET /anything HTTP/1.1
Host httpbin.org
Connection keep-alive
User-Agent Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Reque
sts 1
Accept text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding gzip, deflate, br
Accept-Language en-US,en;q=0.9
Cookie _gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1
HTTP/1.1 200 OK
Server: meinheld/0.6.1
Date: Wed, 15 Nov 2017 18:07:11 GMT
Content-Type: application/json
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Powered-By: Flask
X-Processed-Time: 0.00142621994019
Content-Length: 726
Via: 1.1 vegur
Connection: Keep-alive
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.9",
"Connection": "close",
"Cookie": "_gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
},
"json": null,
"method": "GET",
"origin": "<ip-address-here>",
"url": "https://httpbin.org/anything"
}
After pressing the Send button, the httpbin.org page pops up to show this:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "en-US,en;q=0.9",
"Connection": "close",
"Cookie": "_gauges_unique_day=1; _gauges_unique_month=1; _gauges_unique_year=1; _gauges_unique=1",
"Host": "httpbin.org",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
},
"json": null,
"method": "GET",
"origin": "<ip-address-here>",
"url": "https://httpbin.org/anything"
}
It seems like there was no POST to the URL. No errors seen in Excel. The form can be POSTed successfully to the same URL in a browser on the Mac. This issue is seen only in Excel 2016 for Mac. The same code works fine in Excel 2016 for Windows (7 and 10) and Excel online. Any insights to help resolve this is much appreciated.
See related question Is the Excel add-in incompatible with Excel 2016 for Mac when using POST method for forms?
Update Excel 2016 on Mac to version 16.9.0 (18011602). We are able to POST from Excel 2016 for Mac! Thanks to the entire MS team.
Please refer this post for latest on this. Seems to be a duplicate issue.