Proxy with express.js

前端 未结 9 1450
别那么骄傲
别那么骄傲 2020-11-28 00:29

To avoid same-domain AJAX issues, I want my node.js web server to forward all requests from URL /api/BLABLA to another server, for example other_domain.co

相关标签:
9条回答
  • 2020-11-28 01:02

    Ok, here's a ready-to-copy-paste answer using the require('request') npm module and an environment variable *instead of an hardcoded proxy):

    coffeescript

    app.use (req, res, next) ->                                                 
      r = false
      method = req.method.toLowerCase().replace(/delete/, 'del')
      switch method
        when 'get', 'post', 'del', 'put'
          r = request[method](
            uri: process.env.PROXY_URL + req.url
            json: req.body)
        else
          return res.send('invalid method')
      req.pipe(r).pipe res
    

    javascript:

    app.use(function(req, res, next) {
      var method, r;
      method = req.method.toLowerCase().replace(/delete/,"del");
      switch (method) {
        case "get":
        case "post":
        case "del":
        case "put":
          r = request[method]({
            uri: process.env.PROXY_URL + req.url,
            json: req.body
          });
          break;
        default:
          return res.send("invalid method");
      }
      return req.pipe(r).pipe(res);
    });
    
    0 讨论(0)
  • 2020-11-28 01:11

    I used the following setup to direct everything on /rest to my backend server (on port 8080), and all other requests to the frontend server (a webpack server on port 3001). It supports all HTTP-methods, doesn't lose any request meta-info and supports websockets (which I need for hot reloading)

    var express  = require('express');
    var app      = express();
    var httpProxy = require('http-proxy');
    var apiProxy = httpProxy.createProxyServer();
    var backend = 'http://localhost:8080',
        frontend = 'http://localhost:3001';
    
    app.all("/rest/*", function(req, res) {
      apiProxy.web(req, res, {target: backend});
    });
    
    app.all("/*", function(req, res) {
        apiProxy.web(req, res, {target: frontend});
    });
    
    var server = require('http').createServer(app);
    server.on('upgrade', function (req, socket, head) {
      apiProxy.ws(req, socket, head, {target: frontend});
    });
    server.listen(3000);
    
    0 讨论(0)
  • 2020-11-28 01:12

    request has been deprecated as of February 2020, I'll leave the answer below for historical reasons, but please consider moving to an alternative listed in this issue.

    Archive

    I did something similar but I used request instead:

    var request = require('request');
    app.get('/', function(req,res) {
      //modify the url in any way you want
      var newurl = 'http://google.com/';
      request(newurl).pipe(res);
    });
    

    I hope this helps, took me a while to realize that I could do this :)

    0 讨论(0)
  • 2020-11-28 01:16

    I don't have have an express sample, but one with plain http-proxy package. A very strip down version of the proxy I used for my blog.

    In short, all nodejs http proxy packages work at the http protocol level, not tcp(socket) level. This is also true for express and all express middleware. None of them can do transparent proxy, nor NAT, which means keeping incoming traffic source IP in the packet sent to backend web server.

    However, web server can pickup original IP from http x-forwarded headers and add it into the log.

    The xfwd: true in proxyOption enable x-forward header feature for http-proxy.

    const url = require('url');
    const proxy = require('http-proxy');
    
    proxyConfig = {
        httpPort: 8888,
        proxyOptions: {
            target: {
                host: 'example.com',
                port: 80
            },
            xfwd: true // <--- This is what you are looking for.
        }
    };
    
    function startProxy() {
    
        proxy
            .createServer(proxyConfig.proxyOptions)
            .listen(proxyConfig.httpPort, '0.0.0.0');
    
    }
    
    startProxy();
    

    Reference for X-Forwarded Header: https://en.wikipedia.org/wiki/X-Forwarded-For

    Full version of my proxy: https://github.com/J-Siu/ghost-https-nodejs-proxy

    0 讨论(0)
  • 2020-11-28 01:17

    First install express and http-proxy-middleware

    npm install express http-proxy-middleware --save
    

    Then in your server.js

    const express = require('express');
    const proxy = require('http-proxy-middleware');
    
    const app = express();
    app.use(express.static('client'));
    
    // Add middleware for http proxying 
    const apiProxy = proxy('/api', { target: 'http://localhost:8080' });
    app.use('/api', apiProxy);
    
    // Render your site
    const renderIndex = (req, res) => {
      res.sendFile(path.resolve(__dirname, 'client/index.html'));
    }
    app.get('/*', renderIndex);
    
    app.listen(3000, () => {
      console.log('Listening on: http://localhost:3000');
    });
    

    In this example we serve the site on port 3000, but when a request end with /api we redirect it to localhost:8080.

    http://localhost:3000/api/login redirect to http://localhost:8080/api/login

    0 讨论(0)
  • 2020-11-28 01:20

    You want to use http.request to create a similar request to the remote API and return its response.

    Something like this:

    const http = require('http');
    // or use import http from 'http';
    
    
    /* your app config here */
    
    app.post('/api/BLABLA', (oreq, ores) => {
      const options = {
        // host to forward to
        host: 'www.google.com',
        // port to forward to
        port: 80,
        // path to forward to
        path: '/api/BLABLA',
        // request method
        method: 'POST',
        // headers to send
        headers: oreq.headers,
      };
    
      const creq = http
        .request(options, pres => {
          // set encoding
          pres.setEncoding('utf8');
    
          // set http status code based on proxied response
          ores.writeHead(pres.statusCode);
    
          // wait for data
          pres.on('data', chunk => {
            ores.write(chunk);
          });
    
          pres.on('close', () => {
            // closed, let's end client request as well
            ores.end();
          });
    
          pres.on('end', () => {
            // finished, let's finish client request as well
            ores.end();
          });
        })
        .on('error', e => {
          // we got an error
          console.log(e.message);
          try {
            // attempt to set error message and http status
            ores.writeHead(500);
            ores.write(e.message);
          } catch (e) {
            // ignore
          }
          ores.end();
        });
    
      creq.end();
    });
    

    Notice: I haven't really tried the above, so it might contain parse errors hopefully this will give you a hint as to how to get it to work.

    0 讨论(0)
提交回复
热议问题