API Gateway - Опубликовать multipart\form-data
Кажется, мой вопрос может быть немного похож на на этот.
У меня есть API в моем API-шлюзе, и я делаю прокси-сервер HTTP до конечной точки, в которой хранятся файлы POST multipart/form-data.
Если я вызываю конечную точку http напрямую (не через шлюз API) - используя почтальон, он работает так, как ожидалось, однако использование конечной точки шлюза API (через почтальон) терпит неудачу.
Я сравнивал оба запроса (через журналы Fiddler и CloudWatch), которые кажутся одинаковыми:
Запрос прямого вызова API (рабочий):
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--
Запрос от шлюза API (не работает):
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--
Я пробовал несколько вещей со стороны шлюза, включая изменение Integration Request
для отображения нового тела для одного и того же типа содержимого, без везения.
Насколько мне известно, мне нужен только passthrough
этот вызов, поэтому почему он становится немного запутанным - не должно быть необходимости в манипулировании данными/перехвате?
Ошибка, которую я получаю, - это 400 - плохой запрос (жалоба на file
не найдена), но, как вы можете видеть в запросе, это там.
Любые идеи?
ИЗМЕНИТЬ
Журналы из CloudWatch на одном POST-сервере APIGateway
![введите описание изображения здесь]()
Ошибка все еще 400 - файл не найден
Ответы
Ответ 1
API-шлюз в настоящее время не поддерживает многочастные данные формы. Это рассматривается для будущего развития. В то же время вам нужно будет изменить ваш клиент для использования нескольких запросов или одного запроса из одной части.
Обновление: API Gateway теперь поддерживает двоичные данные. Просто определите multipart/form-data
как двоичный медиа-тип для вашего API и передайте полезную нагрузку непосредственно в функцию Lambda. Оттуда вы можете проанализировать тело, чтобы получить содержимое вашего файла. Должны быть доступны библиотеки, которые помогут разобрать составное тело (например, parse-multipart в Node.js).
Ответ 2
Похоже, что произошли изменения, и API Gateway больше не выполняет строгое сопоставление всего значения заголовка Content-Type, поэтому теперь все для "двоичной" поддержки работает должным образом.
Установите для своего API значение POST (или PUT) и установите для интеграции Lambda значение "proxy". Перейдите в настройки для своего API и добавьте типы мультимедиа, которые вы хотите использовать как "двоичные". Я добавил multipart/signed
. Полученный тип мультимедиа на самом деле: Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha256"; boundary="----54645645645664564563424768"
Content-Type: multipart/signed; protocol="application/pkcs7-signature"; micalg="sha256"; boundary="----54645645645664564563424768"
API GW по-прежнему воспринимает это как "двоичный" и доставляет его как base64 в мою Lambda.
В вашей лямбде вы поймаете это:
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
}
Ответ 3
У меня была такая же проблема при интеграции с моим сервером Tomcat, я обнаружил ниже изменения, необходимые для ее исправления.
-
Добавьте Content-Type в свой API-заголовок HTTP-запроса в API-шлюзе через консоль или добавьте его в документацию Open API, например
{
"/yourApi":{
"post":{
"operationId":"uploadImageUsingPOST",
"produces":[
"application/json"
],
"parameters":[
{
"name":"Content-Type",
"in":"header",
"required":false,
"type":"string"
},
{
//Other headers
}]
}
}
-
Выше шага также добавьте Content-Type в ваш HTTP-заголовок API-интерфейса запроса на интеграцию, если не добавите его туда, добавьте еще один заголовок Accept = '/' в api-шлюзе через консоль или или добавьте его в документацию открытого API-интерфейса, например
"requestParameters":{
"integration.request.header.Accept":"'*/*'",
"integration.request.header.Content-Type":"method.request.header.Content-Type",
//Other headers
}
-
Установите Обработка контента как Passthrough в вашем запросе интеграции API.
-
Добавьте multipart/form-data как Binary Media Types в настройках API через консоль или через открытую документацию API.
"x-amazon-apigateway-binary-media-types": [
"multipart/form-data"
]
-
Разверните вышеупомянутые изменения на желаемом этапе, когда вы собираетесь загрузить изображение как составное.
Api-шлюз передаст ваш многокомпонентный файл в виде двоичного массива, и вы все равно можете использовать @RequestBody MultipartFile multipartFile в своем контроллере, и Spring проанализирует этот двоичный файл как многочастный для вас.
Ответ 4
Для тех, кто все еще нуждается в некоторой помощи, это теперь официально зарегистрировано:
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-configure-with-console.html
Подводя итог, можно сделать следующие шаги:
- Перейдите на вкладку настроек API-шлюза для своего API и добавьте "multipart/form-data" в раздел "Типы двоичных носителей".
- Добавьте "Content-Type" и "Accept" в заголовки запроса для вашего прокси-метода.
- Добавьте те же самые заголовки к заголовкам запроса интеграции
- повторно развернуть
ура