Skip to content

Commit e9055c1

Browse files
fix(openapi): preserve vendor +json Content-Type on object bodies (#1937)
1 parent f1930dd commit e9055c1

3 files changed

Lines changed: 37 additions & 6 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@executor-js/plugin-openapi": patch
3+
---
4+
5+
Preserve vendor +json Content-Type on OpenAPI object request bodies.

‎packages/plugins/openapi/src/sdk/invoke.ts‎

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -838,12 +838,8 @@ const applyRequestBody = (
838838
});
839839

840840
if (isJsonContentType(contentType)) {
841-
// Pre-serialized JSON strings pass through with the declared media
842-
// type preserved (important for `application/vnd.foo+json` etc.).
843-
if (typeof bodyValue === "string") {
844-
return sent(HttpClientRequest.bodyText(request, bodyValue, contentType));
845-
}
846-
return sent(HttpClientRequest.bodyJsonUnsafe(request, bodyValue));
841+
const text = typeof bodyValue === "string" ? bodyValue : JSON.stringify(bodyValue);
842+
return sent(HttpClientRequest.bodyText(request, text, contentType));
847843
}
848844

849845
if (isFormUrlEncoded(contentType)) {

‎packages/plugins/openapi/src/sdk/non-json-body.test.ts‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,36 @@ describe("OpenAPI non-JSON request body dispatch", () => {
447447
}),
448448
);
449449

450+
it.effect("application/vnd.api+json: object body keeps the declared content type", () =>
451+
Effect.gen(function* () {
452+
const { server, captured } = yield* startEchoServer({
453+
name: "createNote",
454+
path: "/notes",
455+
payload: JsonNameObject,
456+
transformSpec: replaceRequestBodyContent("/notes", "post", {
457+
"application/vnd.api+json": {
458+
schema: {
459+
type: "object",
460+
properties: {
461+
name: { type: "string" },
462+
},
463+
},
464+
},
465+
}),
466+
});
467+
468+
const executor = yield* createExecutor(makeTestConfig({ plugins: testPlugins() }));
469+
const conn = yield* addOpenApiTestConnection(executor, server, { slug: "notes-jsonapi" });
470+
471+
yield* executor.execute(conn.address("body.createNote"), {
472+
body: { name: "Acme" },
473+
});
474+
475+
expect(captured.contentType).toBe("application/vnd.api+json");
476+
expect(decodeJsonNameBody(captured.body.toString("utf8"))).toEqual({ name: "Acme" });
477+
}),
478+
);
479+
450480
it.effect("multipart/form-data: only encoder-supported file shapes are advertised", () =>
451481
Effect.gen(function* () {
452482
const { server } = yield* startEchoServer({

0 commit comments

Comments
 (0)