serve-handler icon indicating copy to clipboard operation
serve-handler copied to clipboard

Implement proxy config option

Open nathancahill opened this issue 6 years ago • 15 comments

Uses well-established http-proxy to provide an option similar to rewrite that proxies requests to a different backend. Resolves #30. The new option would look like this:

{
  "proxy": [
    { "source": "/api/foo", "destination": "http://foo.example" },
    { "source": "/api/bar", "destination": "http://bar.example" }
  ]
}

Additionally, other http-proxy options can be specified in the config, like ignorePath which removes the original url when the request is proxied:

{
  "proxy": [
    { "source": "/api/foo", "destination": "http://foo.example", "ignorePath": true }
  ]
}

Wanted to put this in a PR to get it in front of the Zeit team before going further. If the idea is good, I'll finish the remaining todos:

  • [ ] Add tests
  • [ ] Document proxy config option
  • [ ] Merge PR for proxy option in @zeit/schema repo

nathancahill avatar Jan 30 '19 01:01 nathancahill

Codecov Report

Merging #75 into master will decrease coverage by 4.03%. The diff coverage is 37.5%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #75      +/-   ##
==========================================
- Coverage   99.42%   95.38%   -4.04%     
==========================================
  Files           2        2              
  Lines         345      368      +23     
==========================================
+ Hits          343      351       +8     
- Misses          2       17      +15
Impacted Files Coverage Δ
src/index.js 95.32% <37.5%> (-4.09%) :arrow_down:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update ce35fcd...6629d8b. Read the comment docs.

codecov[bot] avatar Jan 30 '19 01:01 codecov[bot]

@leo Friendly bump to this. If there's not interest I'd be interested in maintaining a fork of the package to support this feature.

nathancahill avatar Feb 09 '19 20:02 nathancahill

Bump, I'd love to see this move forward as well and would be willing to help.

skipjack avatar Apr 01 '19 16:04 skipjack

+1 imho this is essential. i'm going to have to switch to another library due to lack of proxy support, which is too bad because serve is otherwise great.

gatherben avatar Jul 25 '19 13:07 gatherben

@gatherben Meanwhile you can use my fork with this feature if you'd like. Is published as serve-proxied on npm. Hope to see it merged some day.

nathancahill avatar Jul 27 '19 00:07 nathancahill

Why this PR has not been merged yet? It's a great and useful feature.

JounQin avatar Sep 05 '19 10:09 JounQin

@nathancahill OK, I think you should add related tests and documentation as the description of PR template.

JounQin avatar Sep 05 '19 10:09 JounQin

@JounQin I'm not investing more time until I hear back from the maintainers that they are interested (in which case this PR can be finished) or not interested (in which case the feature will be available in serve-proxied on npm).

nathancahill avatar Sep 05 '19 19:09 nathancahill

@nathancahill I tried your serve-proxied, but it seems not working to me.

// serve.json
{
  "proxy": [
    {
      "source": "/api/",
      "destination": "http://localhost:8080/",
      "secure": false,
      "changeOrigin": true
    }
  ]
}

CMD: cp -f serve.json dist/static && serve dist/static -l 4200

image

// response
{"error":{"code":"not_found","message":"The requested path could not be found"}}

Is there anything wrong?

JounQin avatar Sep 06 '19 03:09 JounQin

@JounQin make sure the service running on :8080 is expecting the URL to be prefixed with /api/v1 and not just /v1

nathancahill avatar Sep 16 '19 22:09 nathancahill

@nathancahill Yeah, of course, it works with webpack-dev-server so I believe the service is running correctly.

Whatever, I've finished up by writing a custom serve.js which wrapped serve-handler and http-proxy manually which seems simple enough to me.


const path = require('path');
const http = require('http');

const httpProxy = require('http-proxy');
const handler = require('serve-handler');

const proxy = httpProxy.createProxyServer();

const PROXIES = require('../.proxyrc.json');

const PROXY_SOURCES = Object.keys(PROXIES);

const server = http.createServer((request, response) => {
  const proxySource = PROXY_SOURCES.find(source => request.url.match(source));

  if (proxySource) {
    const proxyConfig = PROXIES[proxySource];
    return proxy.web(request, response, proxyConfig, error => {
      response.destroy(error);
      console.dir({
        source: request.url,
        target: proxyConfig.target,
        message: error.message,
      });
    });
  }

  return handler(request, response, {
    public: path.resolve('dist/static'),
    rewrites: [
      {
        source: '/**',
        destination: '/index.html',
      },
    ],
  });
});

server.listen(4200, () => console.log('Running at http://localhost:4200'));

JounQin avatar Sep 16 '19 23:09 JounQin

Added support for routing segments like in the redirects and rewrites options. So now it's possible to do this:

{
  "proxy": [
    { "source": "/api/:object", "destination": "http://example.com/:object" }
  ]
}

Published on npm as serve-proxied@11.1.0

nathancahill avatar Sep 23 '19 21:09 nathancahill

@leo Did you guys ever have any time to review these pending PRs?

JounQin avatar Feb 04 '20 02:02 JounQin

use http-proxy:

const handler = require("serve-handler");
const http = require("http");
const path = require("path");
const proxy = require("http-proxy").createProxyServer();
const apiAddr = "http://192.168.1.2:31501/"; // proxy host

const server = http.createServer((request, response) => {
  if (request.url.indexOf("/es") > -1) { // request api
    console.log("proxying req url: " + request.url);
    return proxy.web(request, response, { target: apiAddr }, (err) => {
      console.error(err);
    });
  }
  // You pass two more arguments for config and middleware
  // More details here: https://github.com/vercel/serve-handler#options
  return handler(request, response, {
    public: path.resolve("./dist/es-web-portal"),
  });
});

server.listen(3000, () => {
  console.log("Running at http://localhost:3000");
});

yy7054wyq5 avatar Jul 08 '20 03:07 yy7054wyq5

Added support for routing segments like in the redirects and rewrites options. So now it's possible to do this:

{
  "proxy": [
    { "source": "/api/:object", "destination": "http://example.com/:object" }
  ]
}

Published on npm as serve-proxied@11.1.0

Hello,

I have used your fork but I need to list all possible path as follow "proxy": [ { "source": "/app1/", "destination": "http://localhost:8080/app1/" }, { "source": "/app1/:object", "destination": "http://localhost:8080/app1/:object" } { "source": "/app1/js/:object", "destination": "http://localhost:8080/app1/js/:object" } ] Is there a way to put a wildcard ? Thanks.

srichez avatar Mar 02 '21 18:03 srichez