I too came across this problem and realized that when fetch redirects to the presigned S3 URL you can't prevent it from sending the Authorization headers from your API.
Eventually I have able to get this working by using the responseInterceptor configuration argument for Swagger with a custom function that detects the bad request (400) response from S3 and then re-issues the fetch request with credentials: 'omit'.
Here is my custom response interceptor for Swagger:
// swagger-ui-extensions.js
function serializeHeaderValue(value) {
const isMulti = value.includes(', ');
return isMulti ? value.split(', ') : value;
}
function serializeHeaders(headers = {}) {
return Array.from(headers.entries()).reduce((acc, [header, value]) => {
acc[header] = serializeHeaderValue(value);
return acc;
}, {});
}
function myResponseInterceptor(response) {
// NOTE: Additional checks should probably be added whether to re-issue the fetch. This was just an initial starting point.
if (response.ok === false && response.status === 400 && response.headers['server'] === 'AmazonS3') {
// Here is the important part, re-issue fetch but don't allow our Authentication header to flow
response = fetch(response.url, { credentials: 'omit' })
.then(nativeResponse => {
// We can't return the native response because Swagger UI attempts to assign the header property (and potentially other properties
// too) on the response. So return a serialized clone of the native response. FYI, this is the same exact logic from Swagger's fake
// implementation of fetch.
const getBody = nativeResponse.blob || nativeResponse.buffer;
return getBody.call(nativeResponse).then(body => {
return {
ok: nativeResponse.ok,
url: nativeResponse.url,
status: nativeResponse.status,
statusText: nativeResponse.statusText,
headers: serializeHeaders(nativeResponse.headers),
data: body
};
});
});
}
return response;
}
Then I had to specify my custom myResponseInterceptor when initializing the Swagger UI in index.html
// (other code omitted for brevity...)
// Make sure to include your custom JS in the page
// <script src="./swagger-ui-extensions.js"></script>
// Specifying the custom responseInterceptor here...
configObject.responseInterceptor = myResponseInterceptor;
// Begin Swagger UI call region
const ui = SwaggerUIBundle(configObject);
ui.initOAuth(oauthConfigObject);
// End Swagger UI call region
window.ui = ui;
I was using ASP.NET Core and used these instructions to provide my own index.html for Swagger UI:
https://github.com/domaindrivendev/Swashbuckle.AspNetCore#customize-indexhtml
After all that, this surprisingly worked and I was able to see the redirected response from S3 in Swagger.