I need to do a signed POST request from Angular to AWS API gateway and send multipart/form-data with document and additional parameters.
I create FormData that as follows:
const formData = new FormData();
formData.append('document', document, document.name);
formData.append('document_metadata', new Blob(
[JSON.stringify(metaData)],
{
type: 'application/json'
})
);
Now, to do a request to AWS Gateway, I need to sign the request with all attributes being sent as body, meaning I need to somehow pass FormData to signature. The problem is that you can't get values of FormData without them being streamed.
to do that, I used approach mentioned here Get HTTP Body of Form in JavaScript. So I stream the file, decode it's values and combine it. This gives me the string that would be send with the request and with it I can sign the request ( with the help of https://github.com/mar753/aws-signature-v4 ).
async getFormDataStream(formData: FormData) {
const response = new Response(formData);
const stream = response.body;
const reader = stream.getReader();
const decoder = new TextDecoder('utf-8');
const parent = this;
let tempData = '';
const headers: Headers = response.headers;
headers.forEach((value, key) => {
if(key ==='content-type') {
this.customContentType = value;
}
});
await reader.read()
.then(function processData(result) {
tempData = tempData + decoder.decode(result.value);
if (result.done) {
parent.customFormData = tempData;
console.log('stream done');
return;
}
return reader.read().then(processData);
})
.catch((err) => {
console.log('catch stream cancellation:', err);
});
}
Now I create the headers and request:
const headers = {
headers: new HttpHeaders({
'X-Amz-Date': signature['X-Amz-Date'],
'X-Amz-Security-Token': user.sessionToken,
'x-api-access-token': user.getJwtToken(),
'x-api-id-token': user.getJwtToken(),
'Content-Type': this.customContentType, // contentType with boundary is generated from stream
authorization: signature.Authorization
};
this.http.post(APIGatewayEndpoint, this.customFormData, header); // customFormData is generated with stream
Everything I did so far works, I pass the Authorization without a problem and save the file. But the problem is that everything except for .txt file gets corrupted and I can't open it. I have to guesses what might be wrong:
- Document gets corrupted while decoding it with stream and SpringBoot can't parse it correctly
- SpringBoot isn't parsing raw data correctly?
Any help regarding the above would be appreciated as I'm stuck without options at the moment.