Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Edit POST parameters prior to forwarding to a proxy target and sending response back to client

I have a node/express proxy setup using http-proxy-middleware to route requests to a java-tomcat web service (proxy target).

I need to inject POST form data into the request rawbody with a context-type of "application/x-www-form-urlencoded" prior to forwarding the request to the proxy target. The proxy response will need to have the same post parameters removed prior to sending the response to the client.

I have used a number of different proxies include http-proxy, http-proxy-middleware, node-proxy, and express-proxy but none of these modules appear to have a solution available that allows for POST parameter manipulation

This question was originally posted on https://github.com/chimurai/http-proxy-middleware/issues/61#issuecomment-205494577

'use strict';

var express = require('express');
var router = express.Router();
//var request = require("request");

var proxy_filter = function (path, req) {
    return path.match('^/report') && ( req.method === 'GET' ||    req.method === 'POST' );
};

var proxy_options = {
    target: 'http://localhost:8080',
    logLevel: 'debug',
    //logProvider:
    onError(err, req, res) {
        res.writeHead(500, {
            'Content-Type': 'text/plain'
        });
        res.end('Something went wrong. And we are reporting a custom error message.' + err);
    },
    onProxyRes(proxyRes, req, res) {
        //proxyRes.headers['x-added'] = 'foobar';     // add new header to response
        //delete proxyRes.headers['x-removed'];       // remove header from response
    },
    onProxyReq(proxyReq, req, res) {
        if ( req.method == "POST" && req.body ) {
            proxyReq.write( encodeURIComponent( JSON.stringify(   req.body ) ) );
            proxyReq.end();
        }
    }
};

// Proxy configuration
var proxy = require( 'http-proxy-middleware' )( proxy_filter, proxy_options );

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: 'Node.js Express Proxy Test' });
});

router.all('/report/*', function( req, res, next ) {

    //req.body.jdbc_sas = 'jdbc:postgresql://pg_dev:5432/sasdb';
    //req.body.jdbc_agency = 'jdbc:postgresql://pg_dev:5432/agency0329';
    //console.log('proxy body:',req.body);

    proxy( req, res, next );
} );

module.exports = router;

Any suggestions are greatly appreciated.

Respectfully,

Warren.

like image 342
flackenstein Avatar asked Apr 05 '16 02:04

flackenstein


1 Answers

Ok Here's the final solution.

The following example allows you to inject POST parameters prior to forwarding to the proxy target. You don't have scrub any parameters from the proxy target response - as far as I can tell - because it maintains a copy of the original POST request.

On a side note this also allows the http-proxy-middleware to work with body-parser.

Example Node Express Route File:

'use strict';

var express = require('express');
var router = express.Router();

var proxy_filter = function (path, req) {
    return path.match('^/docs') && ( req.method === 'GET' || req.method === 'POST' );
};

var proxy_options = {
    target: 'http://localhost:8080',
    pathRewrite: {
        '^/docs' : '/java/rep/server1' // Host path & target path conversion
    },
    onError(err, req, res) {
        res.writeHead(500, {
            'Content-Type': 'text/plain'
        });
        res.end('Something went wrong. And we are reporting a custom error message.' + err);
    },
    onProxyReq(proxyReq, req, res) {
        if ( req.method == "POST" && req.body ) {
            // Add req.body logic here if needed....

           // ....

            // Remove body-parser body object from the request
            if ( req.body ) delete req.body;

            // Make any needed POST parameter changes
            let body = new Object();

            body.filename = 'reports/statistics/summary_2016.pdf';
            body.routeid = 's003b012d002';
            body.authid = 'bac02c1d-258a-4177-9da6-862580154960';

            // URI encode JSON object
            body = Object.keys( body ).map(function( key ) {
                return encodeURIComponent( key ) + '=' + encodeURIComponent( body[ key ])
            }).join('&');

            // Update header
            proxyReq.setHeader( 'content-type', 'application/x-www-form-urlencoded' );
            proxyReq.setHeader( 'content-length', body.length );

            // Write out body changes to the proxyReq stream
            proxyReq.write( body );
            proxyReq.end();
        }
    }
};

// Proxy configuration
var proxy = require( 'http-proxy-middleware' )( proxy_filter, proxy_options );

/* GET home page. */
router.get('/', function(req, res, next) {
    res.render('index', { title: 'Node.js Express Proxy Test' });
});

router.all('/document', proxy );

module.exports = router;
like image 126
flackenstein Avatar answered Nov 08 '22 08:11

flackenstein