Proxied requests other than GET are hanging with NestJS and http-proxy-middleware

baumgarb

Example code is available on https://github.com/baumgarb/reverse-proxy-demo The README.md explains how you can re-produce the issue if you clone the repo.

I have an API Gateway and a downstream service which returns todos (TodosAPI). A client goes through the API Gateway to access the downstream service.

The API Gateway is leveraging the http-proxy-middleware package to proxy the requests. There are two implementations and the 2nd one is not working:

1. Global middleware in main.ts which kicks in on path /api/v1/...

This approach works perfectly fine and it proxies all requests to the downstream service no matter what http method (GET, PUT, ...).

import * as proxy from 'http-proxy-middleware';

app.use(
  '/api/v1/todos-api',
  proxy({
    target: 'http://localhost:8090/api',
    pathRewrite: {
      '/api/v1/todos-api': ''
    },
    secure: false,
    onProxyReq: (proxyReq, req, res) => {
      console.log(
        `[Global Functional Middlware]: Proxying ${req.method} request originally made to '${req.originalUrl}'...`
      );
    }
  })
);

2. NestMiddleware which is registered in the app module which kicks in on path /api/v2/...

This approach works fine for GET requests, but other http methods like PUT keep "hanging" and no response is ever received on the client. The problem seems to be that the controller in the downstream service is never invoked.

import * as proxy from 'http-proxy-middleware';

export class ReverseProxyMiddleware implements NestMiddleware {
  private proxy = proxy({
    target: 'http://localhost:8090/api',
    pathRewrite: {
      '/api/v2/todos-api': ''
    },
    secure: false,
    onProxyReq: (proxyReq, req, res) => {
      console.log(
        `[NestMiddleware]: Proxying ${req.method} request originally made to '${req.originalUrl}'...`
      );
    }
  });

  use(req: Request, res: Response, next: () => void) {
    this.proxy(req, res, next);
  }
}

And this middleware is registered as follows:

@Module({
  imports: [],
  controllers: [AppController],
  providers: [AppService]
})
export class AppModule implements NestModule {
  configure(consumer: import('@nestjs/common').MiddlewareConsumer) {
    consumer
      .apply(ReverseProxyMiddleware)
      .forRoutes({ path: 'v2/todos-api', method: RequestMethod.ALL });
  }
}
  • Running curl -X PUT -H "Content-Type: application/json" -d "{\"id\": 1, \"userId\": 1, \"title\": \"delectus aut autem - v1\", \"completed\": true}" http://localhost:8080/api/v1/todos-api/1 works perfectly fine
  • Running curl -X PUT -H "Content-Type: application/json" -d "{\"id\": 1, \"userId\": 1, \"title\": \"delectus aut autem - v2\", \"completed\": true}" http://localhost:8080/api/v2/todos-api/1 is having the issue where the controller in the downstream service is never invoked

The NestMiddleware is proxying the request (I can see a log line saying [NestMiddleware]: Proxying PUT request originally made to '/api/v2/todos-api/1'...) and the downstream service receives the request (I can see that from logging). But the downstream service does not invoke the controller / action and eventually never returns.

Has anyone any idea what I'm doing wrong here? Thanks a lot in advance!

baumgarb

I've finally figured out the problem. It seems to be related to the body parser. If I change the API Gateway to turn off the body parser the request is forwarded successfully.

So the solution was to replace

const app = await NestFactory.create(AppModule);

with

const app = await NestFactory.create(AppModule, { bodyParser: false });

I've also created a branch issue-fixed in the Git repo where the fix is implemented.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How to get 'proxied' object from an existing dynamic proxy

Node JS HTTP Proxy hanging up

Fake HTTP Get Requests

Multiple Http.Get hanging randomly

Rewriting path with http-proxy-middleware

Python Requests hanging/freezing

http-proxy-middleware - access to the static files

Akka Http singleRequest stream is hanging after multiple requests

Get proxy response in middleware

how to set proxy by request hostname with http-proxy-middleware and express?

Keycloak says 403 Forbidden for HTTP Methods other than GET

Request is not being proxied through middleware

long poll hanging all other server requests

How to proxy to many different targets using http-proxy-middleware?

Handle WebSocket error with http-proxy-middleware

Autobahn 0.7.3 - Proxied Websocket fails when a client is behind a http Proxy

Diagnosing hanging requests with requests

Python, Django - how to store http requests in the middleware?

Proxy for requests with grunt only works with HTTP (and not HTTPS)

Scrapy - Use proxy middleware but disable proxy for specific requests

Does Python requests really connect to http proxy?

ActionController::InvalidAuthenticityToken when using nginx to proxy https requests to other nginx (http) to proxy to rails (http)

Use a proxy for HTTP requests with WKWebView

Custom response with http-proxy-middleware package

http-proxy-middleware not proxying to index page of other server?

Specifying proxy for http-proxy-middleware

Multiprocessing hanging with requests.get

Postgresql requests proxied by HTTP server

Websockets not working with http-proxy-middleware