Пример кода доступен на 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, продолжают "висеть" и неответ когда-либо получен на клиенте. Кажется, проблема в том, что контроллер в нисходящем сервисе никогда не вызывается.
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 передает прокси-запрос (я вижу строку журнала, говорящую [NestMiddleware]: Proxying PUT request originally made to '/api/v2/todos-api/1'...
) и нисходящий сервис получает запрос (я вижу это по логингу). Но нисходящий сервис не вызывает контроллер / действие и в конечном итоге никогда не возвращается.
Кто-нибудь знает, что я здесь не так делаю? Заранее большое спасибо!