Giter Site home page Giter Site logo

fastify-http-proxy's Introduction

@fastify/http-proxy

CI NPM version js-standard-style

Proxy your HTTP requests to another server, with hooks. This fastify plugin forwards all requests received with a given prefix (or none) to an upstream. All Fastify hooks are still applied.

@fastify/http-proxy is built on top of @fastify/reply-from, which enables single route proxying.

This plugin can be used in a variety of circumstances, for example if you have to proxy an internal domain to an external domain (useful to avoid CORS problems) or to implement your own API gateway for a microservices architecture.

Requirements

Fastify 4.x. See @fastify/http-proxy v7.x for Fastify 3.x compatibility.

Install

npm i @fastify/http-proxy fastify

Example

const Fastify = require('fastify');
const server = Fastify();

server.register(require('@fastify/http-proxy'), {
  upstream: 'http://my-api.example.com',
  prefix: '/api', // optional
  http2: false, // optional
});

server.listen({ port: 3000 });

This will proxy any request starting with /api to http://my-api.example.com. For instance http://localhost:3000/api/users will be proxied to http://my-api.example.com/users.

If you want to have different proxies on different prefixes you can register multiple instances of the plugin as shown in the following snippet:

const Fastify = require('fastify');
const server = Fastify();
const proxy = require('@fastify/http-proxy');

// /api/x will be proxied to http://my-api.example.com/x
server.register(proxy, {
  upstream: 'http://my-api.example.com',
  prefix: '/api', // optional
  http2: false, // optional
});

// /rest-api/123/endpoint will be proxied to http://my-rest-api.example.com/123/endpoint
server.register(proxy, {
  upstream: 'http://my-rest-api.example.com',
  prefix: '/rest-api/:id/endpoint', // optional
  rewritePrefix: '/:id/endpoint', // optional
  http2: false, // optional
});

// /auth/user will be proxied to http://single-signon.example.com/signon/user
server.register(proxy, {
  upstream: 'http://single-signon.example.com',
  prefix: '/auth', // optional
  rewritePrefix: '/signon', // optional
  http2: false, // optional
});

// /user will be proxied to http://single-signon.example.com/signon/user
server.register(proxy, {
  upstream: 'http://single-signon.example.com',
  rewritePrefix: '/signon', // optional
  http2: false, // optional
});

server.listen({ port: 3000 });

Notice that in this case it is important to use the prefix option to tell the proxy how to properly route the requests across different upstreams.

Also notice paths in upstream are ignored, so you need to use rewritePrefix to specify the target base path.

For other examples, see example.js.

Request tracking

@fastify/http-proxy can track and pipe the request-id across the upstreams. Using the hyperid module and the @fastify/reply-from built-in options a fairly simple example would look like this:

const Fastify = require('fastify');
const proxy = require('@fastify/http-proxy');
const hyperid = require('hyperid');

const server = Fastify();
const uuid = hyperid();

server.register(proxy, {
  upstream: 'http://localhost:4001',
  replyOptions: {
    rewriteRequestHeaders: (originalReq, headers) => ({
      ...headers,
      'request-id': uuid(),
    }),
  },
});

server.listen({ port: 3000 });

Options

This fastify plugin supports all the options of @fastify/reply-from plus the following.

Note that this plugin is fully encapsulated, and non-JSON payloads will be streamed directly to the destination.

upstream

An URL (including protocol) that represents the target server to use for proxying.

prefix

The prefix to mount this plugin on. All the requests to the current server starting with the given prefix will be proxied to the provided upstream.

Parametric path is supported. To register a parametric path, use the colon before the parameter name.

The prefix will be removed from the URL when forwarding the HTTP request.

rewritePrefix

Rewrite the prefix to the specified string. Default: ''.

preHandler

A preHandler to be applied on all routes. Useful for performing actions before the proxy is executed (e.g. check for authentication).

proxyPayloads

When this option is false, you will be able to access the body but it will also disable direct pass through of the payload. As a result, it is left up to the implementation to properly parse and proxy the payload correctly.

For example, if you are expecting a payload of type application/xml, then you would have to add a parser for it like so:

fastify.addContentTypeParser('application/xml', (req, done) => {
  const parsedBody = parsingCode(req);
  done(null, parsedBody);
});

preValidation

Specify preValidation function to perform the validation of the request before the proxy is executed (e.g. check request payload).

fastify.register(proxy, {
  upstream: `http://your-target-upstream.com`,
  preValidation: async (request, reply) => {
    if (request.body.method === 'invalid_method') {
      return reply.code(400).send({ message: 'payload contains invalid method' });
    }
  },
});

config

An object accessible within the preHandler via reply.context.config. See Config in the Fastify documentation for information on this option. Note: this is merged with other configuration passed to the route.

replyOptions

Object with reply options for @fastify/reply-from.

internalRewriteLocationHeader

By default, @fastify/http-proxy will rewrite the location header when a request redirects to a relative path. In other words, the prefix will be added to the relative path.

If you want to preserve the original path, this option will disable this internal operation. Default: true.

Note that the rewriteHeaders option of @fastify/reply-from will retrieve headers modified (reminder: only location is updated among all headers) in parameter but with this option, the headers are unchanged.

httpMethods

An array that contains the types of the methods. Default: ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT', 'OPTIONS'].

websocket

This module has partial support for forwarding websockets by passing a websocket boolean option.

A few things are missing:

  1. request id logging
  2. support ignoreTrailingSlash
  3. forwarding more than one subprotocols. Note: Only the first subprotocol is being forwarded

Pull requests are welcome to finish this feature.

wsUpstream

Working only if property websocket is true.

An URL (including protocol) that represents the target websockets to use for proxying websockets. Accepted both https:// and wss://.

Note that if property wsUpstream not specified then proxy will try to connect with the upstream property.

wsServerOptions

The options passed to new ws.Server().

wsClientOptions

The options passed to the WebSocket constructor for outgoing websockets.

It also supports an additional rewriteRequestHeaders(headers, request) function that can be used to write the headers before opening the WebSocket connection. This function should return an object with the given headers. The default implementation forwards the cookie header.

Benchmarks

The following benchmarks where generated on a dedicated server with an Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz and 64GB of RAM:

Framework req/sec
express-http-proxy 2557
http-proxy 9519
@fastify/http-proxy 15919

The results were gathered on the second run of autocannon -c 100 -d 5 URL.

TODO

  • Perform validations for incoming data
  • Finish implementing websocket

License

MIT

fastify-http-proxy's People

Contributors

cemremengu avatar climba03003 avatar delvedor avatar dependabot-preview[bot] avatar dependabot[bot] avatar dokki avatar eomm avatar fdawgs avatar github-actions[bot] avatar greenkeeper[bot] avatar jsumners avatar lmammino avatar lynxtaa avatar mcollina avatar nettema avatar poppinlp avatar rafaelgss avatar salmanm avatar simenb avatar stefanmirck avatar stevenmatchett avatar thejones avatar trott avatar txchen avatar uzlopak avatar valeneiko avatar vorillaz avatar xa3lis avatar yoursunny avatar zekth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fastify-http-proxy's Issues

Setting reponse timeout handler throws an error if request is sent in through FastifyInstance.inject

🐛 Bug Report

It seems that fastify-http-proxy does not allow to set a response timeout handler if the original request is sent in to fastify throug FastifyInstance.inject

To Reproduce

Assume I have the following configuration:

const proxy = require('fastify-http-proxy')
const fastify = ...
fastify.register(proxy, {
  upstream: upstreamUrl,
  prefix: '/myPrefix',
  http2: false,
  async preHandler(request, reply) {
    reply.res.setTimeout(5000, () => {
      reply.status(502).send('Gateway timeout')
    })
  }
})

I have a test case that would test if the timeout is working:

it('should respond with HTTP 502 if the proxied system does not respond in the specified timeout', async () => {
  // mock server
  nock('http://localhost:9000')
      .get('/')
      .delay(6000)
      .reply(200, { dummy: 'dummy' })
  // call
  const response = await fastify
      .inject({ method: 'GET', url: '/myPrefix' })
      .should.be.fulfilled()
  // test
  should(response.statusCode).be.equal(502)
})

Expected behavior

The test case should be successful, but it fails with the following error:

This test fails with the followig error:

TypeError: this.socket.setTimeout is not a function
    at Response.setTimeout (_http_outgoing.js:222:17)
    at Object.preHandler (<project root>/src/my-route.ts:34:27)
    at hookIterator (<project root>/node_modules/fastify/lib/hooks.js:124:10)
    at next (<project root>/node_modules/fastify/lib/hooks.js:70:20)
    at hookRunner (<project root>/node_modules/fastify/lib/hooks.js:84:3)
    at preValidationCallback (<project root>/node_modules/fastify/lib/handleRequest.js:92:5)
    at handler (<project root>/node_modules/fastify/lib/handleRequest.js:69:5)
    at handleRequest (<project root>/node_modules/fastify/lib/handleRequest.js:18:5)
    at onRunMiddlewares (<project root>/node_modules/fastify/lib/middleware.js:22:5)
    at Holder.done (<project root>/node_modules/middie/middie.js:90:9)
    at xXssProtection (<project root>/node_modules/x-xss-protection/dist/index.js:47:13)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at crossdomain (<project root>/node_modules/helmet-crossdomain/dist/index.js:27:9)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at nosniff (<project root>/node_modules/dont-sniff-mimetype/dist/index.js:5:9)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at ienoopen (<project root>/node_modules/ienoopen/dist/index.js:5:9)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at hsts (<project root>/node_modules/hsts/index.js:52:5)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at hidePoweredBy (<project root>/node_modules/hide-powered-by/dist/index.js:7:13)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at frameguard (<project root>/node_modules/frameguard/dist/index.js:55:9)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at dnsPrefetchControl (<project root>/node_modules/dns-prefetch-control/dist/index.js:14:9)
    at Holder.done (<project root>/node_modules/middie/middie.js:112:11)
    at Object.run (<project root>/node_modules/middie/middie.js:59:12)
    at middlewareCallback (<project root>/node_modules/fastify/lib/route.js:384:27)
    at next (<project root>/node_modules/fastify/lib/hooks.js:66:7)
    at handleResolve (<project root>/node_modules/fastify/lib/hooks.js:77:5)

Your Environment

  • node version: 12.13.1
  • fastify version: >=2.11.0
  • os: Mac

Option types not in sync with fastify-reply-from

🐛 Bug Report

Typescript interface FastifyHttpProxyOptions does not extend FastifyReplyFromOptions from module fastify-reply-from, so it's not possible to specify e.g. the http option in fastify-http-proxy.

To Reproduce

    fastify.register(proxy, {
        upstream: upstreamUrl,
        prefix,
        http2: false,
        http: {
          requestOptions: {
            timeout: 20000
          }
        }
    })

Expected behavior

It is expected to be compiled without errors, but I get the following error:

Object literal may only specify known properties, but 'http' does not exist in type '{ upstream: string; prefix?: string | undefined; rewritePrefix?: string | undefined; http2?: boolean | undefined; proxyPayloads?: boolean | undefined; preHandler?: ((request: FastifyRequest<IncomingMessage | Http2ServerRequest, DefaultQuery, DefaultParams, DefaultHeaders, any>, reply: FastifyReply<...>, next: (err?:...'. Did you mean to write 'http2'?

Your Environment

  • node version: 14
  • fastify version: >=2.0.0
  • os: Mac

Selectively apply middleware to some specific routes

I am using this library to create a simple api gateway for my microservices . I am using preHandler to check which route needs the middleware but I am quiet lost after this point . My objective is to register the middleware in certain routes in my services only . How do I achieve that ?

How I can supply upstream with path?

I want to proxy a request from /test (and only /test) to a remote service: http://remote.com/test like this:

GET http://proxy/test/users -> GET http://remote/test/users

This doesn't work:

server.register(
  require('fastify-http-proxy'),
  { upstream: 'http://proxy/test', prefix: '/test' }
)

// GET http://proxy/test/users -> GET http://remote/users 404 Not Found

Can't add route on root while using this plugin

🐛 Bug Report

If I try to register a handler on root, and use this plugin; Fastify throws AssertionError [ERR_ASSERTION]: Method 'GET' already declared for route '/'.

To Reproduce

Steps to reproduce the behavior:

const fastify = require('fastify')()
const proxy = require('fastify-http-proxy')

;(async () => {
  fastify.get('/', (_, reply) => reply.send('hello'))
  fastify.register(proxy, { upstream: 'http://localhost:8081', path: '/llama', rewritePrefix: '/llama' })
  await fastify.listen(8080, '0.0.0.0')
})()

The same as above with dependencies and such ready - https://github.com/pearofducks/fastify-proxy-repro

Expected behavior

Able to have a route on root, and add a proxy.

Your Environment

  • node version: v15.2.0
  • os: Mac - 11.0.1
  "dependencies": {
    "fastify": "^3.8.0",
    "fastify-http-proxy": "^4.0.4"
  }

Unique request ids and request tracking

🚀 Feature Proposal

There is TODO note at the very end of the README.md about creating unique request ids and implementing request tracking. I am highly interested in this feature and if some of the maintainers could drop an architecture overview I am more than happy to create a PR.

information :

Hello,

As we registerer the proxy to fastify, can I do some logic ( addHook ) in the fastify instance before providing it to fastify-http-proxy ?

On description of onRequest and Hook in fastify documentation I see that I could do it on that method, Is it doable instead of doing it in the preHandler of the proxy ?
Same for helmet, cors, can I set it on this fastify instance ?

For example for the JWT, I use the JWT-encrypt to add additional informations (extra Authorization) in the token ( encrypted ). As all the backend is using http/2 it's not really necessary to have the data encrypted in the bearer token.

Something like :

-- public --> proxy ( set CORS, helmet, authentication/jwt,...) --> backend

Thanks by advance.

API whitelisting behind gateway

This is not a real security breach I guess, but some companies rely on api-gateways to whitelist their APIs that are exposed to the world.

For example, I would like to expose only those APIs that have /external prefix

'use strict'

const Fastify = require('fastify')

const target = Fastify({
  logger: false
})

const server = Fastify({
  logger: false
})

target.get('/internal/api/token', (request, reply) => {
  reply.send('Security token: 123')
})

target.get('/external/api/v1', (request, reply) => {
  reply.send('hello world')
})

const proxy = require('fastify-http-proxy')

server.register(proxy, {
  upstream: 'http://localhost:3001',
  prefix: '/external',
  rewritePrefix: '/external',
})


target.listen(3001, (err) => {
  if (err) {
    throw err
  }

  server.listen(3000, (err) => {
    if (err) {
      throw err
    }
  })
})

then execute this snippet(does not work with cURL for some reason):

URL: 'http://127.0.0.1:3000/external/../internal/api/token

var request = require('request');
request.get('http://127.0.0.1:3000/external/../internal/api/token', function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

will result:

$ node req.js 
Security token: 123

suggestion

change

fastify.addContentTypeParser('application/json', bodyParser);

to

if (!fastify.hasContentTypeParser('application/json')) {
    fastify.addContentTypeParser('application/json', bodyParser);
  }

Based on prefix, proxy to different paths within same host

Am I able to register a proxy like this?

  fastify.register(proxy, {
    upstream: 'https://hostname.com/api/v1',
    prefix: '/api',
    http2: false
  });

  fastify.register(proxy, {
    upstream: 'https://hostname.com/api/v1',
    prefix: '/api/v1',
    http2: false
  });

From what I can tell, it looks like both prefixes redirect to just the hostname excluding the api/v1 path.

So if I call https://beforeproxy.com/api/this-endpoint proxies to https://hostname.com/this-endpoint.

How to read the response data?

Hi! I have a doubt. How to I read the response data? It is possible? Thank's

...
replyOptions: {
      onResponse (req, reply, res) {
        console.log('== onResponse - data ==', res.response.data) // example
        reply.send(res)
      },
    },
...

Use new fastify-reply-from 1.1.0

The newest fastify-http-proxy version on NPM still uses fastify-reply-from 0.6.x. From the commits it looks safe to update fastify-http-proxy to use the newer 1.x versions.

Would it be possible to update on your end? We're currently using the master branch in our package.json 😄

Add ignorePrefixes options

🚀 Feature Proposal

Add ignorePrefixes option, which takes an array. All requests made to those routes would not get handled by fastify-http-proxy.

Motivation

I'd like to proxy my Vue.js development server to the root prefix (/). I also want to have /api/ routes on the same server.

Example

await server.register(FastifyHttpProxy, {
  upstream: 'http://localhost:8080',
});
await server.register(registerOAuth, { prefix: '/api/oauth', logLevel: 'info' });
await server.register(registerWebsiteApi, { prefix: '/api/website', logLevel: 'info' });

Disclosure

I'm new to Fastify, so this might already be possible without modifying fastify-http-proxy. If it's the case I'd ask for an example of how to do this (maybe it's a good idea to place it in README.md). Thanks!

Question - Using replyOptions

I have a general question on how to call, if possible, the onResponse method from reply-from when using http-proxy. I am successful in calling rewriteHeaders but have not had luck with the onResponse call.

I am testing with an app generated with fastify-cli.

This is what I have.

  fastify.register(proxy, {
    upstream: 'myUrl',
    prefix: '/apiProxy',
    async beforeHandler(request, reply) {
      console.log('beforeHandler from proxy called'); // works as expected
    },
    replyOptions: {
      rewriteHeaders: headers => Object.assign({ 'x-from-proxy': 'yes-indeed' }, headers), // works as expected
      onResponse: (res) => {
        console.log('here'); // Should this work? Nothing is logged at this point.
      },
    },
  });

I have tried a few iterations but wanted to know if this is a supported and (most likely) a syntax error.

I did post this in Gitter as well but my timing seems to be a bit off of when others are online (not trying to spam two places).

Any help is appreciated.

Proxy S3 storage file through fastify-http-proxy

I am thinking of writing a thin proxy layer using this library to proxy files stored in AWS S3 . I want to know will there be any major latency besides the usual to stream through fastify-http-proxy ?

upstream with base path doesn't work

Following example in README.md is not work. /auth/abc always proxy to http://single-signon.example.com/abc.

server.register(proxy, {
  upstream: 'http://single-signon.example.com/auth',
  prefix: '/auth', // optional
  http2: false // optional
})

UPDATED:
According to https://github.com/fastify/fastify-reply-from#base

Set the base URL for all the forwarded requests. Will be required if http2 is set to true Note that every path will be discarded.

But we do have usecase that require pass prefix to the proxy server.

Proxy server returns a 308 when placed behind a rewriteUrl fastify server

🐛 Bug Report

I have a server that rewrite a request site-1.localhost to localhost/site-1. Then I registerred the proxy plugin as

      fastify.register(fastifyProxy, {
        upstream,
        prefix: 'site-1', // optional
        http2: false, // optional
      })

A request of site-1.localhost is responded with a 308 redirect to localhost/site-1/site-1

To Reproduce

Start fastify server:

  const fastify = fastify({
    logger: {
      level: isProduction ? 'error' : 'info',
    },
    ...settings.fastify,
    rewriteUrl: function (req) {
       const subsite = getSubsite(req.headers.host) // get site-1 from site-1.localhost
       return subsite + req.url
    },
  })

Register proxy:

      fastify.register(fastifyProxy, {
        upstream,
        prefix: 'site-1', // optional
        http2: false, // optional
      })

Expected behavior

Respond with proxyed page but got 308.

Your Environment

  • node version: 10, 12, 13
  • fastify version: >=3
  • os: Linux

An in-range update of @types/node is breaking the build 🚨


☝️ Important announcement: Greenkeeper will be saying goodbye 👋 and passing the torch to Snyk on June 3rd, 2020! Find out how to migrate to Snyk and more at greenkeeper.io


The devDependency @types/node was updated from 13.7.7 to 13.9.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@types/node is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build failed (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

vs nginx

How much slower is this than nginx?
Should I use it instead of nginx to do micro service?

An in-range update of @typescript-eslint/parser is breaking the build 🚨

The devDependency @typescript-eslint/parser was updated from 1.9.0 to 1.10.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@typescript-eslint/parser is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Handling/ignoring undici errors

🚀 Feature Proposal

Version 5.0 uses fastify-reply-from 5.0, which now uses Undici as default HTTP client.

In our projects, this has led to interesting new errors where calls will fail due to Undici errors, e.g

code: "UND_ERR_CONTENT_LENGTH_MISMATCH"
error: "Internal Server Error"
message: "Request body length does not match content-length header"
statusCode: 500

We did not see these under 4.0, and our clients are not having problem with anything not using Undici.

It would be nice if http-proxy could allow Undici errors to be ignored or otherwise handled.

Motivation

To give greater control to developers over what Undici errors can cause the proxy to fail, if any.

Transform HTML body before to send back to the proxied website

I am trying to proxy any website, do some changes on the returned HTML string from the proxied website and then return it to the Browser. This is how far I've got:

const Fastify = require('fastify');
const server = Fastify();
const { ungzip } = require('node-gzip');
const cheerio = require('cheerio');

export default class Proxy {
    _initProxy(host: string) {
        server.register(require('fastify-http-proxy'), { upstream: host });
        server.addHook('onSend', (request: any, reply: any, payload: any, done: () => void) => {
            const chunks = [];
            payload.on('data', (chunk) => {
                chunks.push(chunk);
            });
            payload.on('end', async () => {
                const buffer = Buffer.concat(chunks);
                if (payload.headers['content-encoding'] === 'gzip') {
                    try {
                        const decompressed = await ungzip(buffer);
                        let $ = null;
                        $ = await cheerio.load(decompressed.toString());
                        const scriptTag = '<script src="my-custom.js"></script>';
                        $('body').append(scriptTag);
                    } catch (e) {
                        console.log(e);
                    }
                }
            })
            done();
        })
        server.listen(5051);
    }
}

You can see that I am adding my-custom.js script inside the BODY tag once I have unzipped and parsed the returned payload. It is working fine, however, the last bit I can't find yet is: How to return the transformed HTML string to the browser?

I have an API responsible for starting the Proxy server:

   _initApi(): void {
        server.get('/', opts, async (request, reply) => {
            return { res: '200 - OK' }
        });

        server.get('/start-proxy', opts, async (request, reply) => {
            this.proxy._initProxy('http://example.org')
            return { res: '200 - PROXY STARTED' }
        });

        server.listen(5050, (err) => {
            if (err) {
                server.log.error(err)
                process.exit(1)
            }
            server.log.info(`server listening on ${server.server.address()}`)
        });
    } 

Get HTML body of proxied website.

I am trying to get the HTML body of my proxied website using fastify-http-proxy middleware:

const Fastify = require('fastify')
const server = Fastify()

export default class Proxy {
    _initproxy(host: string) {
        server.register(require('fastify-http-proxy'), { upstream: host });
        server.addHook('onSend', (request: any, reply: any, payload: any, done: () => void) => {
            console.log('Display website HTML body here');
            done()
        })
        server.listen(5051);
    }
}

I have thoughtfully read the documentation but seems like something is missing in the code.

An in-range update of express-http-proxy is breaking the build 🚨

The devDependency express-http-proxy was updated from 1.4.0 to 1.5.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

express-http-proxy is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Commits

The new version differs by 15 commits.

  • bf63dbf 1.5.0
  • fe8d02e Updating README for 1.5.0 release.
  • 8b716ca [#374] fixes bug in filter signature (#389)
  • ea936f3 kill only in test file
  • abf684c Remove httpbin.org as a test dependency here. (#388)
  • c68f1b9 Add js language to markdown for syntax highlighting (#385)
  • ad94d32 381 (#386)
  • 338c6d8 Insert missing parenthesis (#378)
  • c8cdb67 [#357] Correct documentation.
  • 3c4d8f9 [#366] Improve debug logging in reqOpt decorator. (#367)
  • 8bac3fe [#361] Fix skipToNextHandler, add expressHttpProxy value to user res for additional processing. (#373)
  • 762b16f [#363] Tests for host as ip address. (#371)
  • f7c55cf updating mocha version (#372)
  • b78046b Rebuild package-lock.json with updated npm. (#370)
  • ca944fa remove jshint and jscs dependencies

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Modify headers

I am investigating using this module to create a service proxy. In this proxy I will need to be able to inspect and modify or add headers to the request. My testing reveals that I can add headers, but I do not seem to be able to modify headers.

    preHandler(req, res, next) {
      const apiKey = req.headers['x-api-key']
      if (!apiKey) {
        return res.code(400).send({invalid: 'request'})
      }
      const bar = req.headers['x-bar']
      if (bar) {
        req.headers['bar'] = 'bar;modified'
      }

      req.headers['x-foo'] = 'foo'
      next()
    }

If you add that preHandler to the example.js included in this repository and attempt to send a request with a x-bar header then the "upstream" service does not see the modified header. It sees the original unaltered header.

Are there plans to support header manipulation in this manner?

Websocket server errors are not captured

🐛 Bug Report

Check out example below

To Reproduce

const fastify = require('fastify')
const proxy = require('fastify-http-proxy')

const s1 = fastify()
const s2 = fastify()

s2.register(proxy, {
	upstream: 'http://example.com',
	prefix: '/api',
	http2: false,
	websocket: true,
})

s1.listen(3000)
	.then(() => s2.listen(3000))
	.catch(err => {
		console.log('Captured', err) // nothing
	})

Expected behavior

Expected s2 port conflict error to be captured in catch-block

Your Environment

  • node version: 10, 12, 13
  • fastify version: >=2.0.0
  • os: Mac, Windows, Linux
  • any other relevant information

TODO: Generate unique request ids and implement request tracking

To support request tracking will the below code is sufficient:

function reply (request, reply) {
    request.req.headers[<requestIdHeaderName>] = request.id;
    var dest = request.req.url.replace(this.basePath, '')
    reply.from(dest)
}

Please let me know. I'll submit pull request.

HTTP2 Proxy always falls

Hello, i fastify user, and now i needed proxy server, i install fastify proxy and set basic settings.
This my server -


const proxy = require('fastify-http-proxy')
const fastify = require('fastify')({
    logger: false,
    http2: true,
    https: {
        key: fs.readFileSync(path.join(serverDirectory, '/certificate/', 'key.pem')),
        cert: fs.readFileSync(path.join(serverDirectory, '/certificate/', 'domain.crt')),
        ca: [
            fs.readFileSync(path.join(serverDirectory, '/certificate/', 'USERTrustRSAAddTrustCA.crt')),
            fs.readFileSync(path.join(serverDirectory, '/certificate/', 'AddTrustExternalCARoot.crt')),
            fs.readFileSync(path.join(serverDirectory, '/certificate/', 'SectigoRSADomainValidationSecureServerCA.crt')),
        ]
    }
})

fastify.register(proxy, {
    upstream: 'https://localhost:3000',
    prefix: '/back', // optional
    http2: true // optional
})

I use SSL from domain, after request i use sort for several servers...
One problem, fastyfy proxy always falls!!!

Error

[nodemon] starting `node ./server/index.js`
internal/http2/compat.js:567
      throw new ERR_HTTP2_INVALID_STREAM();
      ^

Error [ERR_HTTP2_INVALID_STREAM]: The stream has been destroyed
    at Http2ServerResponse.writeHead (internal/http2/compat.js:567:13)
    at onSendEnd (D:\js\proxy\node_modules\fastify\lib\reply.js:308:7)
    at onSendHook (D:\js\proxy\node_modules\fastify\lib\reply.js:261:5)
    at handleError (D:\js\proxy\node_modules\fastify\lib\reply.js:418:5)
    at onErrorHook (D:\js\proxy\node_modules\fastify\lib\reply.js:373:5)
    at _Reply.Reply.send (D:\js\proxy\node_modules\fastify\lib\reply.js:98:5)
    at defaultErrorHandler (D:\js\proxy\node_modules\fastify\lib\context.js:34:9)
    at handleError (D:\js\proxy\node_modules\fastify\lib\reply.js:401:18)
    at onErrorHook (D:\js\proxy\node_modules\fastify\lib\reply.js:373:5)
    at _Reply.Reply.send (D:\js\proxy\node_modules\fastify\lib\reply.js:98:5)
[nodemon] app crashed - waiting for file changes before starting...

In version 1.* this same problem

  "dependencies": {
    "fastify": "^2.2.0",
    "fastify-http-proxy": "^2.1.0"
  }

An in-range update of @typescript-eslint/parser is breaking the build 🚨

The devDependency @typescript-eslint/parser was updated from 2.19.0 to 2.19.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

@typescript-eslint/parser is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build could not complete due to an error (Details).

Release Notes for v2.19.1

2.19.1 (2020-02-10)

Bug Fixes

  • eslint-plugin: [unbound-method] blacklist a few unbound natives (#1562) (4670aab)
  • typescript-estree: ts returning wrong file with project references (#1575) (4c12dac)
Commits

The new version differs by 5 commits.

  • 1c8f0df chore: publish v2.19.1
  • 4c12dac fix(typescript-estree): ts returning wrong file with project references (#1575)
  • e9cf734 docs(eslint-plugin): fix typo in readme
  • 10d86b1 docs(eslint-plugin): [no-dupe-class-members] fix typo (#1566)
  • 4670aab fix(eslint-plugin): [unbound-method] blacklist a few unbound natives (#1562)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

using undici pipelining + pool might not be a good idea?

Different clients could block each other. Should probably have one connection/pool per remote client? DDoS risk otherwise? Or maybe even one connection per request and just re-use them, like node core agent class does? At least for requests that contain a body. Though receiving headers could also be head of line blocking.

i.e. if you have a pipeline that is serving both fast and slow clients, the slow clients would block the fast ones.

Proxy request to url defined after prefix

Is there any possibility to extract absolute url from request url to use it for proxy request?

For example:
Given service which should proxy request to different servers with request and/or response modification (let it be adding identifier)

When
we receive request like:
/proxy/https://google.com/search?q=fastify-http-proxy

Then
service removes prefix to get link and modify it if necessary (in our case: adding modifier to request url):
https://google.com/search?q=fastify-http-proxy&identifier=blah-blah

Then
service makes request to result url with request parameters (headers) and returns result to user

Problems with HTTP/2 Invalid Stream

Version: 11.11.0
OS: Windows 10 Home (64-bit)

I am using Fastify HTTP Proxy to get the CDN (S3 + Cloudfront) files and avoid CORS or CSP problems, but sometimes the request fail and generate a error ERR_HTTP2_INVALID_STREAM that crash de Node.js Application, so i started observe that and always the request that crash the app was from the proxy.

This error decreases a lot, but even so it still occurs, and in addition another error began to appear the HTTP2_ENHANCE_YOUR_CALM that after the error all requests from the proxy result in a Internal Server Error (Code: 500) and the only way to resolve that is restarting the app.

To try resolve this error, i used GZIP compression from the Cloudfront Server to not compress the files from the CDN by the Fastify Compress, this helped a lot, a way to bypass the Invalid Stream Error is using a UncaughtException what is not secure to use, handling the error the requests throw the error but the app works, the files load and not crash, but i really not want continue doing that.

The normal routes from the Fastify works fine, the only problem is that error that can occur any time, not guaranteeing the stability of the application. So how can i fix that?

Note: I am starting work with JS and Node.js recently, so i may have done something wrong, you can check the code that i am using on my profile, the name is ACS. Thanks!

Error [ERR_HTTP2_INVALID_STREAM]: The stream has been destroyed
    at Http2ServerResponse.write (internal/http2/compat.js:606:19)
    at IncomingMessage.ondata (_stream_readable.js:693:20)
    at IncomingMessage.emit (events.js:197:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at IncomingMessage.Readable.push (_stream_readable.js:224:10)
    at HTTPParser.parserOnBody (_http_common.js:126:22)
    at TLSSocket.socketOnData (_http_client.js:447:20)
    at TLSSocket.emit (events.js:197:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at TLSSocket.Readable.push (_stream_readable.js:224:10)
    at TLSWrap.onStreamRead [as onread] (internal/stream_base_commons.js:145:17)
Error [ERR_HTTP2_INVALID_STREAM]: The stream has been destroyed
    at Http2ServerResponse.write (internal/http2/compat.js:606:19)
    at Duplexify.ondata (C:\Users\Wolfer\Documents\App\node_modules\readable-stream\lib\_stream_readable.js:619:20)
    at Duplexify.emit (events.js:197:13)
    at addChunk (C:\Users\Wolfer\Documents\App\node_modules\readable-stream\lib\_stream_readable.js:291:12)
    at readableAddChunk (C:\Users\Wolfer\Documents\App\node_modules\readable-stream\lib\_stream_readable.js:278:11)
    at Duplexify.Readable.push (C:\Users\Wolfer\Documents\App\node_modules\readable-stream\lib\_stream_readable.js:245:10)
    at Duplexify._forward (C:\Users\Wolfer\Documents\App\node_modules\duplexify\index.js:170:26)
    at Gzip.onreadable (C:\Users\Wolfer\Documents\App\node_modules\duplexify\index.js:134:10)
    at Gzip.emit (events.js:197:13)
    at emitReadable_ (_stream_readable.js:539:12)
    at processTicksAndRejections (internal/process/next_tick.js:76:17)

An in-range update of got is breaking the build 🚨

The devDependency got was updated from 10.5.0 to 10.5.1.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

got is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • continuous-integration/travis-ci/push: The Travis CI build failed (Details).

Release Notes for v10.5.1

v10.5.0...v10.5.1

Commits

The new version differs by 2 commits.

  • 78fb85b 10.5.1
  • 453a3a3 Wait until body file descriptor is open (#1054)

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Proxy socket.io

🚀 Feature Proposal

I came across the necessity to proxy a Socket.io connection. Knowing that the socket support is partial, I tried to use this module as-is, but without success.

Motivation

Not sure if Socket.io support can be a goal (because of the almost universal support of raw WebSockets in any environment).

Example

Firstly I tried to emulate the module code: declaring my WebSocket instance and using the stream created by ws. This code does not throw, but the first received message is lost (saw while debugging the Socket.io server).

import make from 'fastify-plugin'
import websocket from 'fastify-websocket'
import WebSocket from 'ws'
import { pipeline } from 'stream'

async function plugin(fastify) {
  fastify.register(websocket)

  fastify.route({
    method: 'GET',
    url: '/socket.io',
    handler(request, reply) {
      reply.code(404).send()
    },
    wsHandler(connection, request) {
      const ws = new WebSocket(process.env.SERVER + request.url, {
        perMessageDeflate: {
          threshold: 1024,
        },
        rejectUnauthorized: false,
      })

      const stream = WebSocket.createWebSocketStream(ws)

      fastify.log.info('starting websocket tunnel')
      pipeline(connection, stream, connection, function (err) {
        if (err) {
          fastify.log.info({ err }, 'websocket tunnel terminated with error')
          return
        }
        fastify.log.info('websocket tunnel terminated')
      })
    },
  })
}

export default make(plugin)

Instead, by proxying all events socket-to-socket, everything works.

import make from 'fastify-plugin'
import websocket from 'fastify-websocket'
import WebSocket from 'ws'

function closeWebSocket(socket, code, reason) {
  if (socket.readyState === WebSocket.OPEN) {
    socket.close(code, reason)
  }
}

function proxy(a, b) {
  function close(code, reason) {
    closeWebSocket(a, code, reason)
    closeWebSocket(b, code, reason)
  }

  a.on('message', data => b.send(data))
  a.on('ping', data => b.ping(data))
  a.on('pong', data => b.pong(data))
  // cannot proxy error code because of ws
  a.on('close', (code, reason) => close(4600, reason))
  a.on('error', error => close(4610, error.message))
  a.on('unexpected-response', (req, res) =>
    close(4620, 'websocket upgrade failed'),
  )

  b.on('message', data => a.send(data))
  b.on('ping', data => a.ping(data))
  b.on('pong', data => a.pong(data))
  // cannot proxy error code because of ws
  b.on('close', (code, reason) => close(4600, reason))
  b.on('error', error => close(4610, error.message))
  b.on('unexpected-response', (req, res) =>
    close(4620, 'websocket upgrade failed'),
  )
}

async function plugin(fastify) {
  fastify.register(websocket)

  fastify.route({
    method: 'GET',
    url: '/socket.io',
    handler(request, reply) {
      reply.code(404).send()
    },
    wsHandler(connection, request) {
      proxy(
        connection.socket,
        new WebSocket(process.env.SERVER + request.url, {
          perMessageDeflate: {
            threshold: 1024,
          },
          rejectUnauthorized: false,
        }),
      )
    },
  })
}

export default make(plugin)

Update basePath to prefix for fastify v2

basePath is deprecated in Fastify ^2 and should be replaced with prefix.

(node:78101) Warning: basePath is deprecated. Use prefix instead. See: https://www.fastify.io/docs/latest/Server/#prefix

An in-range update of fastify-reply-from is breaking the build 🚨

Version 0.4.6 of fastify-reply-from was just published.

Branch Build failing 🚨
Dependency fastify-reply-from
Current Version 0.4.5
Type dependency

This version is covered by your current version range and after updating it in your project the build failed.

fastify-reply-from is a direct dependency of this project, and it is very likely causing it to break. If other packages depend on yours, this update is probably also breaking those in turn.

Status Details
  • continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details

Release Notes v0.4.6
  • Updated dependencies
  • Do not warn if a lot of concurrent requests are waiting for a connection with HTTP2
Commits

The new version differs by 3 commits.

  • 077cf0e Bumped v0.4.6.
  • 9a5d673 Updated dependencies
  • 16ebbb7 Enable unlimited queuing without a warning.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Example does not work

$ mkdir proxy-test && cd proxy-test
$ echo "{}" > package.json
$ npm i --save fastify fastify-http-proxy
# add https://github.com/fastify/fastify-http-proxy/blob/6a213c6c9e95d3f37559bdb9e18d360ccf0dd20b/example.js as `index.js`
$ node index.js

Result:

origin started http://localhost:61146
(node:30350) UnhandledPromiseRejectionWarning: Error: plugin must be a function
    at Boot.use (/private/tmp/02/proxy-test/node_modules/avvio/boot.js:187:11)
    at Object.server.(anonymous function) [as register] (/private/tmp/02/proxy-test/node_modules/avvio/boot.js:31:14)
    at startProxy (/private/tmp/02/proxy-test/index.js:30:10)
    at run (/private/tmp/02/proxy-test/index.js:45:23)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
(node:30350) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:30350) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

Issues with types not matching fastify itself

🐛 Bug Report

From what I can tell, the upstream types for the request/reply interfaces in fastify have changed, which means that the types in fastify-http-proxy are no longer correct. I've tried to work out how to fix these myself, but I don't understand fastify well enough to make sure I'm not going to break anything. I tried removing RawServerBase from the generic but the type check still fails with the too wide issue. Happy to be pointed in the right direction to fix it properly!

To Reproduce

Steps to reproduce the behavior:

Do an npm run typescript in this project

Expected behavior

Tests to pass

Actual behaviour

% npm run typescript

> [email protected] typescript /Users/chris/development/fastify-http-proxy
> tsd


  test/index.test-d.ts:21:4
  ✖  21:4   Parameter type IncomingMessage | Http2ServerRequest is declared too wide for argument type IncomingMessage.
  ✖  25:4   Parameter type IncomingMessage | Http2ServerRequest is declared too wide for argument type IncomingMessage.

  index.d.ts:18:28
  ✖  18:28  Type RawServerBase does not satisfy the constraint RouteGenericInterface.
  Type Server has no properties in common with type RouteGenericInterface.
  ✖  23:28  Type RawServerBase does not satisfy the constraint RouteGenericInterface.
  Type Server has no properties in common with type RouteGenericInterface.

  4 errors

Your Environment

  • node version: 12
  • fastify version: >=2.0.0
  • os: Mac

fastify-http-proxy does not respect 302 redirects

🐛 Bug Report

Hey, thanks for this amazing project. I have some trouble when the upstream servers are triggering some redirects. It seems that the proxy is prefixing the

To Reproduce

Steps to reproduce the behavior:

const Fastify = require('fastify')
const proxy = require('fastify-http-proxy')

const server = Fastify()
const upstream = Fastify()


// Declare a route
const Fastify = require('fastify');
const proxy = require('fastify-http-proxy');

const server = Fastify();
const upstream = Fastify();

// Declare a route
upstream.get('/', async (request, reply) => {
  return reply.redirect(302, 'https://google.com');
});

upstream.get('/foo', async (request, reply) => {
  return reply.send({hello: 'world'});
});

upstream.listen(3001);

server.register(proxy, {
  upstream: 'http://localhost:3001',
  prefix: '/bar'
});

server.listen(3000);

Expected behavior

Visiting http://localhost:3000/bar/foo the proxy works as expected, visiting http://localhost:3000/bar a new redirect was triggered to /barhttps://google.com

Your Environment

  • node version: 14
  • fastify version: 3.9.2
  • os: Mac

Improve typing of `replyOptions`

🚀 Feature Proposal

Give a more precise type to replyOptions (

replyOptions?: Object;
). At the moment the type is Object, aka untyped.

Motivation

It'd appear that replyOptions conforms to the FastifyReplyFromHooks type (https://github.com/fastify/fastify-reply-from/blob/0b34fe66ac0c8814dc912020014538bd846d9f76/index.d.ts#L32), so perhaps this package should import and use this type?

There might have been a good reason why the person who wrote the code left replyOptions loosely typed though. Perhaps it doesn't quite conform to FastifyReplyFromHooks. I hope a maintainer can shed some light on this!

PS: thanks for the amazing work on this library <3

Can't access body in preHandler

When using preHandler in proxy, body is not parsed but instead is overwritten with the request object.

To Reproduce

To reproduce the behavior create a simple reverse proxy and make a POST or PUT request with a body. (JSON)

fastify.register(require("fastify-http-proxy"), {
  upstream: "http://localhost:8080", 
  prefix: "/api/proxy",
  async preHandler(request, reply) {
    console.log(request.body) // This line logs whole fastify request object instead of body
    return
  }
})

Expected behavior

As is preHandler hook on routes, the body should be accessible from proxy's preHandler.

Digging through code I did found a custom body-parser, which I believe disables parsing.

// Code from index.js
fastify.addContentTypeParser('application/json', bodyParser)
fastify.addContentTypeParser('*', bodyParser)

function bodyParser (req, done) {
    done(null, req)
  }

After disabling (commenting out) contentTypeParser the preHandler is working as expected (the body is parsed and accessible).

Is that the expected behavior and if so are there any workarounds?

Your Environment

  • node version: 12.16.1
  • fastify version: 2.12.1
  • os: Linux

Action required: Greenkeeper could not be activated 🚨

🚨 You need to enable Continuous Integration on all branches of this repository. 🚨

To enable Greenkeeper, you need to make sure that a commit status is reported on all branches. This is required by Greenkeeper because it uses your CI build statuses to figure out when to notify you about breaking changes.

Since we didn’t receive a CI status on the greenkeeper/initial branch, it’s possible that you don’t have CI set up yet. We recommend using Travis CI, but Greenkeeper will work with every other CI service as well.

If you have already set up a CI for this repository, you might need to check how it’s configured. Make sure it is set to run on all new branches. If you don’t want it to run on absolutely every branch, you can whitelist branches starting with greenkeeper/.

Once you have installed and configured CI on this repository correctly, you’ll need to re-trigger Greenkeeper’s initial pull request. To do this, please delete the greenkeeper/initial branch in this repository, and then remove and re-add this repository to the Greenkeeper App’s white list on Github. You'll find this list on your repo or organization’s settings page, under Installed GitHub Apps.

TypeScript Integration

Hello
It's a great plugin. Thanks for your work.

I think we should add TypeScript support.
This is not a hard task. But it can improve our developer experience.

I created PR which adds types definition (#55).

Thanks!

Proxying with nested prefix

What are you trying to achieve or the steps to reproduce?

I'm trying to create a proxy on nested prefix, e.g. /api/test.
Here's the simple example that reproduces the behavior:

// index.js
const fastify = require('fastify');
const proxy = require('fastify-http-proxy');

// setup proxy
const proxiedServer = require('./proxiedServer');

// setup app
const app = fastify();

app.get('/', (req, res) => res.send('Hello world!'));

app.register(proxy, {
  upstream: 'http://localhost:8081',
  prefix: '/api/test',
});

app.listen(8080, '0.0.0.0', (err, address) => {
  if (err) {
    console.error(err);
    return;
  }
  console.info(`Listening at ${address}`);
});
// proxiedServer.js
const fastify = require('fastify');
const app = fastify();

app.get('/', (req, res) => res.send('Hello proxied GET world!'));
app.post('/', (req, res) => res.send('Hello proxied POST world!'));

app.listen(8081, (err, address) => {
  if (err) {
    console.error(err);
    return;
  }
  console.info(`Listening at ${address}`);
});

Online test version can be found here on glitch

What was the result you received?

Trying to GET or POST to /api/test returns 404.

What did you expect?

Get correct proxied responses.

Context

  • node version: 8, 10
  • fastify version: 1.7.0
  • fastify-http-proxy version: 0.4.0
  • os: Linux, Mac
  • any other relevant information:

If you change /api/test to /test - it starts working fine.

I've also tried using plugin approach and wrapping proxy in the following block:

app.register((inst, opts, next) => {
  inst.register(proxy, {
    upstream: 'http://localhost:8081',
    prefix: '/test',
  });
  next();
}, {prefix: '/api'});

This still results in 404.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.