node-http-proxy How to proxy pdfkit response? - node.js

I'm trying to figure out how to proxy a request of a pdf file generated at runtime with pdfkit.
Response headers of the backend service are set to
res.setHeader('Content-type', 'application/pdf');
// only if req.params.view != undefined
res.setHeader('Content-disposition', 'attachment; filename=' + req.params.template + '_' + id + '.pdf');
This allows to view the pdf inside browser (by just sending out the first header) or download it by also sending the second header.
While pdfkit generates the file it is piped to the response.
If I try it by contacting the backend directly it works, while using the proxy it's raising a ECONNRESET error.
I guess it might depend on the client terminating the request before to receive the chunked response, how can I allow the backend service to pipe the request as the backend is processing the pdf?
I'm surely missing something... thank you!!

Related

How to add header when piping JPEG image content from axios.get() response

I am using building a node express HTTP web service that calls a web service that returns a JPEG file. The web service works to proxy the JPEG file but I need to add some content headers to the returned GET request that I respond via pipe. Any suggestions?
app.get('/rendition', function (req, res){
let uri = `https://example.com/thumbnail2x`;
axios.get(uri).then(function(response){
// how do I add a header here?
response.data.pipe(res);
});
})

serverless express can't retrieve pdf file (base64 encoding)

I have setup an express/serverless application to retrieve a pdf file on a GET request. But I just retrieve a corrupted repsonse pdf response. I just wondering If my settings are correct to achieve a correct response.
I'm using aws-serverless-express and want to return my pdf buffer to the client browser (it should open in the browser)
My code:
status = 200;
let fileName = "demo.pdf";
res.setHeader('Content-disposition', 'inline; filename="' + fileName + '"');
res.setHeader('Content-type', 'application/pdf');
res.setHeader('isBase64Encoded', true);//isBase64Encoded: true
let pdf = pdfBuffer.toString('base64');
res.status(status).send(pdf);
so I'm sending a base64 encoded string to APIGW. I'm not actually sure if I can set the isBase64Encoded flag via header. I read this before but I'm not so certain about that
I have done this whole procedure before, but didn't make use of aws-serverless-express (where I Could set the isBase64Encoded flag easily)
I'm also using serverless-apigw-binary to automatically setup APIGW for the correct decoding of the base64 encoded data
lambda is automatically encoding to base64, so I had to remove it and directly send the buffer.
I came across similar problem while using serverless Express. AWS Gateway needs a http response like this:
{
"header":{....}
"body": "/9j/4AAQSkZ...",
"isBase64Encoded": true
}
It's useless to put isBase64Encoded in the Http Response Header, AWS API Gateway only checks if the isBase64Encoded is outside the Http header. If it's true, then decode the body before sending it to a HTTP client.
Express (its response object) doesn't seem to allow to add something outside HTTP Header in a Http Response.
If you don't want to give up using Express, the workaround is to do the decoding in the browser, which is pretty easy:
var decodedData = Buffer.from(body,'base64')

Is There a Way to Check Sent Headers with Node/ Express 2.x?

Is there a way of checking what specific headers have been sent using node/ express 2.x?
I have a file download that works perfectly most of the time, but in a few specific instances I get an error in Chrome (no errors in node):
Duplicate headers received from server
The response from the server contained duplicate headers. This problem is generally the result of a misconfigured website or proxy. Only the website or proxy administrator can fix this issue.
Error 349 (net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION): Multiple distinct Content-Disposition headers received. This is disallowed to protect against HTTP response splitting attacks.
For testing purposes, I'd like to see if a specific header has been sent or not, is there a way of doing this with node.js?
...And because someone's going to ask me about the code I use to set headers, I'm piping a stream as the download and are only setting headers in one spot.
res.setHeader('Content-disposition', 'attachment; filename=' + filename)
res.setHeader('Content-Length', stats.size)
res.setHeader('Content-type', 'application/pdf')
stream.pipe(res)
The HTTP response is a WritableStream. When the stream closes, a finish event is emitted. Thus listening to it does the trick:
res.on('finish', function() {
console.log(res._headers);
});
Much more flexible. Can be put in a middleware or a resource handler.
As #generalhenry stated on my question comments:
stream.pipe(res).on('end', function () {
console.log(res._headers);
});
The above line worked for me.
res.set("Content-disposition", "attachment; filename=\""+file.name+"\"")
This worked for me.

Express (node.js) seems to be replacing my content-type with application/json

I've written an express web app route that is essentially a proxy - it pipes the contents of an input stream (a zip file) into the server response's output stream.
I'd like the browser to prompt the user for download or whatever is most appropriate for a zip file. However, when I load this route in a browser, the contents of the input stream (the zip file's contents) show up in the browser window as text, rather than prompting a download. l
This is the code sending the response:
res.statusCode = 200;
res.setHeader ('Content-Length', size);
res.setHeader ('Content-Type', 'application/zip');
console.log ("content-type is " + res.header('Content-Type'));
inputStream.pipe (res);
The console.log statement above outputs "content-type is application/zip".
However, when I examine the request in Chrome's network tab, I see that the response's content-type is "application/json". This implies that express, or something else, is overriding my content-type header, or perhaps has already sent it.
Does anyone know what is changing the content-type on me, and how I could make sure the content-type is the one I set?
Thanks for any help.
You should check the order of the middleware, it's really tricky and can mess things up if they are in the correct order.
You can check the correct order here in the Connect webpage

Sending download request to web client using nodejs

I am implementing some downloader application. Web client will send some data in web server.
It will process the data and will create a file in some specific format and will push that file to client.
I have done the part till creating the file using nodeJS.
Now can someone suggest me how I can push the file to the client. It is like a downloader application, whenever web client sends the data, using some upload button, it will open a Save As window to save the file in client machine.
So can someone throw some light or pointer on some existing code stuff such that I can have a look?
Thanks in advance.
Regards,
-M-
You can see how do the Express Framework implement that:
https://github.com/visionmedia/express/blob/master/lib/response.js#L356
Line 364: Set the Content-Disposition header to tell the client this response is a attachment that can be downloaded.
this.set('Content-Disposition', 'attachment; filename="' + basename(filename) + '"');
Line 365: Send the file as the body of the response:
return this.sendfile(path, fn);
The send module is used in the above function:
https://github.com/visionmedia/send

Resources