示例代码可在https://github.com/baumgarb/reverse-proxy-demo上找到:README.md解释了如果您克隆存储库,如何重现该问题。
我有一个API网关和一个返回服务的下游服务(TodosAPI)。客户端通过API网关访问下游服务。
API网关正在利用http-proxy-middleware
包来代理请求。有两种实现,第二种不起作用:
1。 main.ts
中的全局中间件,它在路径/ api / v1 / ...上启动
这种方法可以很好地工作,并且无论使用哪种http方法(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,该模块会在/ api / v2 / ...路径上启动
此方法对GET请求有效,但是其他http方法(如PUT)保持“挂起”状态,并且客户端上从未收到任何响应。问题似乎是从不调用下游服务中的控制器。 该中间件注册如下: NestMiddleware正在代理请求(我可以看到一条日志行显示 有人知道我在做什么错吗?提前非常感谢!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);
}
}
@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 });
}
}
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
效果很好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
时遇到问题,即永远不会调用下游服务中的控制器[NestMiddleware]: Proxying PUT request originally made to '/api/v2/todos-api/1'...
),下游服务接收到该请求(我可以从日志记录中看到)。但是下游服务不会调用控制器/动作,并且最终永远不会返回。
答案 0 :(得分:1)
在创建Nest Application时设置bodyParser: false
只是解决了我们正在代理的端点的问题,这将导致其他端点(例如JWT localAuth)失败,因为它们需要解析正文。
解决方案是按照this anwser中的描述创建一个中间件,以针对要代理的端点禁用bodyParser,并为其余代理启用它。
答案 1 :(得分:0)
我终于找到了问题所在。它似乎与主体解析器有关。如果我更改API网关以关闭主体解析器,则请求将成功转发。
因此解决方案是替换
const app = await NestFactory.create(AppModule);
使用
const app = await NestFactory.create(AppModule, { bodyParser: false });
我还在实现修补程序的Git存储库中创建了一个分支issue-fixed
。