简体   繁体   中英

forwarding a response from python flask to client through node js

in a special scenario, my node js backend receives a response from python flask server.

I need to forward this response back to the client (as a response to an action that client preformed).

the response should start a download on the client browser for a file specified in python flask response body.

The line of the return of the response from python flask:

return flask.send_file(download_path, as_attachment=True, attachment_filename=file)

I get this response on my node server callback:

app.get(constants.routes.files.download, function (req, res) {
    fileController.downloadFile(req, (err, response_from_python) => {

        console.log("Response from python flask has arrived")
        res._headers = response_from_python.headers;
        res.set('Content-Disposition', 'attachment; filename=exmp_word.docx');
        return res.json(response_from_python.body)  

    });

This really triggers a download at client browser but the file is corrupted and can't be open with word (it was created with word..). I think it's related to the way that file is encoded in response body (should I use res.json ?).

Also, if I connect from client directly to python-server (without going through node) than the file is downloaded successfully (isn't corrupted) but that isn't the way it should work (Should go through node server in the middle).

How should I do this?

Is there a way to pass the python response object directly to client without copying its body field to node res object and modify the headers?

EDIT:

Thanks to Ivan Velichko I'ts working.

Here is the modified function that does it (I have to build it better but the functionality exist).

app.get(constants.routes.files.download, function (req, res) {


res.set('content-Disposition', 'attachment; filename=noam_susp.docx');
res.set('content-type', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
res.set('Accept-Ranges', 'bytes');
res.set('Cache-Control', 'public, max-age=0');
res.set('ETag', 'W/"2721-161b23de2ee');



var file_hash = req.params.identifier;

var request = http.get(constants.manager_rest_api.base_url +
    constants.manager_rest_api.get_file_endpoint +
    '/' + file_hash + '/download_inner', function(response) {
    response.pipe(res);
});

Looks like your solution makes a request to the python server, then reads the entire file content in memory and only then tries to send it back to the client using for some reasons res.json() . However, most probably you need only forward client's request to the python server and then forward python's response as-is. And you for sure should not download files on your node server. Instead use streams . Something like:

app.get(constants.routes.files.download, function (req, res) {
    fileController.downloadFile(req).pipe(res);
});

To achieve this behaviour your fileController.downloadFile() should return a readable stream which you then can pipe() to the res . And the res by itself is already a writable stream.

UPD: it's important to copy headers from the python's response to the node's response explicitly before piping in it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM