0

Edit : not a duplicate of Piping remote file in ExpressJS . In the referenced question, the distant file is accessible through an url and a GET method. This is not the case here, I am receiving the file in a response payload after a POST request.

I have a frontend that allows the user to download a document. For unrelated reasons, this document is generated by an external service each time the user requests it (based on some contextual data). So the pipeline is like this:

  1. User click link in front end
  2. Front-end send GET request to back-end
  3. back-end get relevant internal data and send a POST request to external API
  4. External API sends a response containing the doc itself, with appropriate content-disposition=attachment and content-type headers, and the document in the body of the response.
  5. My back-end forwards this to the front-end
  6. User is prompted with a download link

Steps 1 through 4 work. What my problem is:

  • The user is prompted with a download popup, the file is of the right type (pdf in my example) but the pdf file is an empty page
  • If I send the same request as my backend to the external API but through postman, I get the file I want with the right content.
  • If I send the same request as my frontend to the backend but through postman, I get also get an empty pdf file.

My guess is I am not forwarding correctly the response from the external API to the front-end.

My code :

function getDocFromExternalApi(req, res) {
    sendMyRequest().then(externalApiResponse => {
        res.status(200).header({ //headers appears to be what is expected
            'content-disposition': externalApiResponse.headers['content-disposition'], //= 'attachement; filename="someFileName.pdf"'
            'content-type': externalApiResponse.headers['content-type'] // = 'application/pdf'
        }).send(externalApiResponse.data) //externalApiResponse.data contains the file
    })
}

I also tried adding the charset to content-type and an appropriate content-length header, but no dice either.

The full response from the external API : https://pastebin.com/5FX72eAX

Tom
  • 1,357
  • 2
  • 13
  • 32
  • What's externalApiResponse? you could simply pipe it in the response if it was a stream... Also, have you made certain the externalApiResponse.data is correct? – Salketer Apr 28 '20 at 14:04
  • Does this answer your question? [Piping remote file in ExpressJS](https://stackoverflow.com/questions/18432779/piping-remote-file-in-expressjs) – Salketer Apr 28 '20 at 14:04
  • `externalApiResponse.data` is correct, in postman I get my file with the expected content from this data. The pipe might solve my problem, will try it and keep the post updated. Thanks ! – Tom Apr 28 '20 at 14:12
  • @Salketer data is not a stream, and don't seem to be convertible to one, so piping not possible. The difference with the question you linked is that I don't have an url to a distant file, I am receiving it in the payload. – Tom Apr 28 '20 at 14:32
  • Every string can, but no worries... You can use send normaly. My guess is that externalApiResponse.data does not contain what you are expecting it to. A console.log does show the full pdf bytes? – Salketer Apr 28 '20 at 14:34
  • Yes it does, here is the full response I am getting from the externalAPI (data field at the bottom) : https://pastebin.com/5FX72eAX – Tom Apr 28 '20 at 14:37
  • lookout there's an authorisation token in your pastebin!! – Salketer Apr 28 '20 at 14:39
  • What an idiot, thank you for the heads up. Happily there is no sensitive data accessible through this token as I can't delete it on pastebin. – Tom Apr 28 '20 at 14:45
  • Could be that you aren't changing the content-type correctly. Use res.set() https://expressjs.com/en/api.html#res.set – Salketer Apr 28 '20 at 14:45
  • `header()` is just an alias for `set()`. I tried `set()` to double check, and also verified the response headers in my browser, all headers appear to be correct. (Also invalidate the credentials linked to the leaked token, thank you again) – Tom Apr 28 '20 at 15:02
  • There has to be something wrong somewhere anyways... What's the response postman receives? – Salketer Apr 28 '20 at 15:05
  • I just identified that the postman response has a `gzip` header which is not present when I call the API from node. I have no idea how this is possible since this is the same call but I will investigate on that for now. Thank you for your help, I will update with any relevant info. – Tom Apr 28 '20 at 15:13
  • Problem solved, the problem was in the sdk provided by the external API, it was not giving a `returnType` param to its axios request (so the problem was in `sendMyRequest()`, which was a sdk method). Thank you for your help yesterday. The strange thing is that the data was still here, I was just unable to read it. Weird. – Tom Apr 29 '20 at 08:15

0 Answers0