Skip to content

Commit c60f53a

Browse files
committed
fix: handle JSON bodies for proxied POST, PUT, DELETE APIs
Fixes an issue where proxied[1] APIs that took JSON content on POST, PUT or DELETE would fail with a timeout. The cause was a combination of when the Podium plugin runs in Fastify's lifecycle[2], that Fastify ships a built-in content parser for JSON[3], and that our proxy depended on the request ReadableStream emitting data in order to work. Our proxy would end up coming in too late, after the request stream had been consumed. The fix is to remove the content type parser for proxied routes, since we in any case aren't interested in the request contents at the layout level. [1]: https://podium-lib.io/docs/guides/proxying [2]: https://fastify.dev/docs/latest/Reference/Lifecycle/ [3]: https://fastify.dev/docs/latest/Reference/ContentTypeParser/
1 parent 5822953 commit c60f53a

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

lib/layout-plugin.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ export default fp(
7878
'/*',
7979
);
8080

81+
// Remove the built-in application/json parser in Fastify from
82+
// the proxy routes instance, otherwise the request stream is
83+
// already consumed at this point when we try to proxy it,
84+
// leading to failing requests (timeouts).
85+
instance.removeAllContentTypeParsers();
86+
8187
// Allow all content types for proxy requests
8288
// https://github.com/fastify/fastify/blob/master/docs/ContentTypeParser.md#catch-all
8389
instance.addContentTypeParser('*', (req, payload, cb) => {

tests/layout-plugin.test.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,43 @@ tap.test(
143143
);
144144

145145
tap.test(
146-
'POST to "proxy" url - should proxy the request to the Podlets target endpoint',
146+
'POST to "proxy" url - should proxy the request to the Podlets target endpoint for application/json',
147+
async (t) => {
148+
const podlet = new PodletServer();
149+
const service = await podlet.listen();
150+
151+
const layout = new Server(service);
152+
const address = await layout.listen();
153+
154+
// Make sure layout has manifest so proxy endpoints are mounted
155+
await request({ address, pathname: '/' });
156+
157+
// Request proxy endpoint
158+
const result = await fetch(
159+
new URL('/podium-resource/component/localApi', address),
160+
{
161+
body: JSON.stringify({
162+
message: 'Message for proxied localApi',
163+
}),
164+
method: 'POST',
165+
headers: {
166+
'content-type': 'application/json',
167+
},
168+
},
169+
);
170+
171+
const body = await result.json();
172+
t.equal(body.payload, '{"message":"Message for proxied localApi"}');
173+
t.equal(body.body, 'POST proxy target');
174+
175+
await layout.close();
176+
await podlet.close();
177+
t.end();
178+
},
179+
);
180+
181+
tap.test(
182+
'POST to "proxy" url - should proxy the request to the Podlets target endpoint for application/x-www-form-urlencoded',
147183
async (t) => {
148184
const podlet = new PodletServer();
149185
const service = await podlet.listen();

0 commit comments

Comments
 (0)