Scheint meine Frage vielleicht ein wenig ähnlich zu dieser .
Ich habe eine API in meinem API-Gateway und mache einen HTTP-Proxy bis zu einem Endpunkt der Multipart-/Formulardatendateien von POST.
Wenn ich den http-Endpunkt direkt anrufe (nicht über das API-Gateway) - mit Postman funktioniert er wie erwartet, jedoch schlägt der API-Gateway-Endpunkt (über Postman) fehl.
Ich habe beide Anforderungen verglichen (über Fiddler- und CloudWatch-Protokolle), die identisch zu sein scheinen:
Anforderung eines direkten API-Aufrufs (funktioniert):
POST https://domainname/api/v1/documents HTTP/1.1
Host: api.service
Connection: keep-alive
Content-Length: 202
Authorization: AuthToken
Postman-Token: a75869d6-1d64-6b9f-513d-a80ac192c8e1
Cache-Control: no-cache
Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
docMetaInfo: some extra data needed
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryB85rsPlMffA2fziS
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
------WebKitFormBoundaryB85rsPlMffA2fziS
Content-Disposition: form-data; name=""; filename="Test.txt"
Content-Type: text/plain
This is a test Text File
------WebKitFormBoundaryB85rsPlMffA2fziS--
Anforderung vom API-Gateway (funktioniert nicht):
POST https://GATEWAY_domainname/api/v1/documents HTTP/1.1
Host: api-Gateway.service
Connection: keep-alive
Content-Length: 202
Authorization: AuthToken
Postman-Token: e25536fa-3dfa-ddcb-8ca6-3f3552d2bc40
Cache-Control: no-cache
Origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
docMetaInfo: some extra data needed
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundarybX9MyWBsuLGm6QIC
x-api-key: *********************
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
------WebKitFormBoundarybX9MyWBsuLGm6QIC
Content-Disposition: form-data; name=""; filename="Test.txt"
Content-Type: text/plain
This is a test Text File
------WebKitFormBoundarybX9MyWBsuLGm6QIC--
Ich habe ein paar Dinge von der Gateway-Seite aus versucht, einschließlich des Änderns von Integration Request
, um einen neuen Body für denselben Inhaltstyp zuzuordnen, kein Glück.
Soweit mir bekannt ist, sollte ich nur diese Variable passthrough
brauchen, weshalb es etwas verwirrend wird - es sollte keine Datenmanipulation abfangen notwendig sein?
Der Fehler, den ich erhalte, ist 400 - eine fehlerhafte Anforderung (die sich ärgert, dass die file
nicht gefunden wurde), aber wie Sie in der Anfrage sehen können, ist sie da.
Irgendwelche Ideen?
EDIT Protokolle von CloudWatch auf demselben APIGateway-POST
/ -
Fehler ist immer noch 400 - keine Datei gefunden
API Gateway unterstützt derzeit keine mehrteiligen Formulardaten. Dies wird für die zukünftige Entwicklung in Betracht gezogen. In der Zwischenzeit müssen Sie Ihren Client so ändern, dass er mehrere Anfragen oder eine einzige einteilige Anfrage verwendet.
Update : API Gateway unterstützt jetzt binäre Payloads. Definieren Sie einfach "multipart/form-data" als binären Medientyp für Ihre API, und geben Sie die Nutzdaten direkt an eine Lambda-Funktion weiter. Von dort aus können Sie den Körper analysieren, um Ihren Dateiinhalt zu erhalten. Es sollten Bibliotheken verfügbar sein, die beim Parsen des mehrteiligen Hauptteils helfen ('parse-multipart' in NodeJS zum Beispiel).
Für diejenigen, die noch Hilfe benötigen, ist dies jetzt offiziell dokumentiert:
Zusammenfassend sind die Schritte wie folgt:
Prost
Ich hatte das gleiche Problem bei der Integration in meinen Tomcat-Server. Nachfolgend sind die Änderungen aufgeführt, die zur Fehlerbehebung erforderlich sind.
Füge Content-Type in die HTTP Request Headers deines API-Gateways über die Konsole ein oder füge sie in die offene API-Dokumentation wie
{
"/yourApi":{
"post":{
"operationId":"uploadImageUsingPOST",
"produces":[
"application/json"
],
"parameters":[
{
"name":"Content-Type",
"in":"header",
"required":false,
"type":"string"
},
{
//Other headers
}]
}
}
Fügen Sie oben auch den Inhaltstyp in die HTTP-Header der Integrationsanforderung Ihrer API ein. Wenn nicht, fügen Sie dort auch einen weiteren Header hinzu. Accept = '/ ' in api gateway per konsole oder in offene api dokumentation wie hinzufügen
"requestParameters":{
"integration.request.header.Accept":"'*/*'",
"integration.request.header.Content-Type":"method.request.header.Content-Type",
//Other headers
}
Stellen Sie die Inhaltsbehandlung in der Integrationsanforderung Ihrer API als Passthrough ein.
Fügen Sie Multipart-/Formulardaten als binäre Medientypen in den Einstellungen Ihrer API über die Konsole oder durch Öffnen der API-Dokumentation hinzu
"x-Amazon-apigateway-binary-media-types": [
"multipart/form-data"
]
Stellen Sie die obigen Änderungen in der gewünschten Phase bereit, in der Sie das Bild als Multipart hochladen möchten.
Das API-Gateway übergibt Ihre mehrteilige Datei als binäres Array, und Sie können weiterhin @RequestBody MultipartFile multipartFile in Ihrem Controller verwenden, und spring analysiert diese Binärdatei für Sie in multipart.
Es scheint eine Änderung stattgefunden zu haben und API Gateway führt keine strikte Übereinstimmung des gesamten Content-Type-Header-Werts mehr durch, sodass nun alles für die "binäre" Unterstützung wie erwartet funktioniert.
Stellen Sie Ihre API auf POST (oder PUT) und die Lambda-Integration auf "Proxy". Gehen Sie zu Einstellungen für Ihre API und fügen Sie die Medientypen hinzu, die Sie als "binär" verwenden möchten. Ich habe multipart/signed
..__ hinzugefügt. Der erhaltene Medientyp ist tatsächlich: Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha256"; boundary="----54645645645664564563424768"
Das API-GW nimmt dies immer noch als "binary" auf und liefert es als base64 an meinen Lambda.
In deiner Lambda wirst du dann folgendes fangen:
Context:
{
"callbackWaitsForEmptyEventLoop": true,
"logGroupName": "/aws/lambda/api-invoice",
"logStreamName": "2018/04/27/[$LATEST]3454",
"functionName": "api-invoice",
"memoryLimitInMB": "128",
"functionVersion": "$LATEST",
"invokeid": "345-49e2-11e8-34-345",
"awsRequestId": "345-49e2-11e8-34-345",
"invokedFunctionArn": "arn:aws:lambda:eu-west-1:12345:function:api-invoice"
}
-------
Event:
{
"resource": "/peppol/as2",
"path": "/peppol/as2",
"httpMethod": "POST",
"headers": {
"Accept": "*/*",
"AS2-From": "PEPPOL_AP",
"AS2-To": "234567890",
"AS2-Version": "1.1",
"cache-control": "no-cache",
"Content-Type": "multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=\"sha256\"; boundary=\"----54645645645664564563424768\"",
"Date": "Fri, 27 Apr 2018 06:17:10 GMT",
"Disposition-Notification-Options": "signed-receipt-protocol=optional, pkcs7-signature; signed-receipt-micalg=optional, sha1,md5",
"Disposition-Notification-To": "[email protected]",
"Host": "123.execute-api.eu-west-1.amazonaws.com",
"Message-ID": "<[email protected]>",
"MIME-Version": "1.0",
"Postman-Token": "ert-59c1-45656-94d1-456546",
"Recipient-Address": "as2s://123.execute-api.eu-west-1.amazonaws.com/dev/peppol/as2",
"Subject": "234567890;PEPPOL_AP",
"User-Agent": "PostmanRuntime/7.1.1",
"Via": "1.1 ert-",
"X-Amzn-Trace-Id": "Root=1-4556-ertfd6554",
"X-CLIENT-IP": "172.17.0.1",
"X-Forwarded-For": "xx.xxx.xx.80",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"queryStringParameters": null,
"pathParameters": null,
"stageVariables": null,
"requestContext": {
"resourceId": "80r6gp",
"resourcePath": "/peppol/as2",
"httpMethod": "POST",
"extendedRequestId": "sdsdd343434=",
"requestTime": "27/Apr/2018:06:17:11 +0000",
"path": "/dev/peppol/as2",
"accountId": "123",
"protocol": "HTTP/1.1",
"stage": "dev",
"requestTimeEpoch": 1524809831262,
"requestId": "354-49e2-3445-b2ba-535345",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": null,
"cognitoIdentityId": null,
"caller": null,
"sourceIp": "xx.xxx.xx.80",
"accessKey": null,
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": null,
"userAgent": "PostmanRuntime/7.1.1",
"user": null
},
"apiId": "123"
},
"body": "VGhpcyBpcyBhbiBTL01/ [snip] /S0NCg==",
"isBase64Encoded": true
}