diff --git a/CHANGELOG.md b/CHANGELOG.md
index faebc00..07d7716 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,11 @@
+## [0.12.1] - 2024-11-05
+
+### Changed
+
+- laxed parsing rule for requests with header 'content-type: application/json'
+ now covers all 3 methods: GET, DELETE, and HEAD
+- doc updated in README
+
## [0.12.0] - 2024-11-05
### Changed
diff --git a/README.md b/README.md
index 8f97bc4..1ded138 100644
--- a/README.md
+++ b/README.md
@@ -57,13 +57,13 @@ deno add @oak/oak @dklab/oak-routing-ctrl
```ts
// main.ts
-import { Application } from "@oak/oak/application";
+import { Application } from "jsr:@oak/oak/application";
import {
Controller,
ControllerMethodArgs,
Get,
useOakServer,
-} from "@dklab/oak-routing-ctrl";
+} from "jsr:@dklab/oak-routing-ctrl";
const app = new Application();
@@ -96,13 +96,13 @@ curl localhost:1993/v1/hello/world # prints: hello, world
View Example
```ts
-import { Application } from "@oak/oak/application";
+import { Application } from "jsr:@oak/oak/application";
import {
Controller,
ControllerMethodArgs,
Post,
useOakServer,
-} from "@dklab/oak-routing-ctrl";
+} from "jsr:@dklab/oak-routing-ctrl";
@Controller("/v1")
class MyController {
@@ -133,13 +133,13 @@ curl -H"Content-Type: application/json" localhost:1993/v1/tell/alice -d'{"messag
View Example
```ts
-import { Application } from "@oak/oak/application";
+import { Application } from "jsr:@oak/oak/application";
import {
Controller,
ControllerMethodArgs,
Get,
useOakServer,
-} from "@dklab/oak-routing-ctrl";
+} from "jsr:@dklab/oak-routing-ctrl";
@Controller("/v1")
class MyController {
@@ -170,8 +170,8 @@ curl localhost:1993/v1/books/thriller\?page=2
View Example
```ts
-import { Application } from "@oak/oak/application";
-import { Controller, Get, useOakServer } from "@dklab/oak-routing-ctrl";
+import { Application } from "jsr:@oak/oak/application";
+import { Controller, Get, useOakServer } from "jsr:@dklab/oak-routing-ctrl";
@Controller()
class MyController {
diff --git a/jsr.json b/jsr.json
index 196c8ca..48b77b9 100644
--- a/jsr.json
+++ b/jsr.json
@@ -1,6 +1,6 @@
{
"name": "@dklab/oak-routing-ctrl",
- "version": "0.12.0",
+ "version": "0.12.1",
"exports": {
".": "./mod.ts",
"./mod": "./mod.ts"
diff --git a/src/ControllerMethodArgs.ts b/src/ControllerMethodArgs.ts
index c1a33af..8276c78 100644
--- a/src/ControllerMethodArgs.ts
+++ b/src/ControllerMethodArgs.ts
@@ -129,14 +129,16 @@ function getEnhancedHandler(
parsedReqBody = await _internal.parseOakReqBody(ctx);
} catch (e) {
if (
- ctx.request.method === "GET" &&
+ ["GET", "DELETE", "HEAD"].includes(ctx.request.method) &&
ctx.request.headers.get("Content-Type") === "application/json" &&
(e as Error).message?.includes("Unexpected end of JSON input")
) {
// we ignore this parsing error because the client was sending
- // a weird combination of method & content-type header
+ // a weird combination of method & content-type header, but here to
+ // the "Japanese engineering mindset":
+ // https://www.500eboard.co/forums/threads/engineers-japanese-vs-german.14695/
} else {
- // for other case, we trigger the error back to userland
+ // for other scenarios, we trigger the error back to userland
return ctx.throw(
400,
`Unable to parse request body: ${(e as Error).message}`,
diff --git a/src/ControllerMethodArgs_test.ts b/src/ControllerMethodArgs_test.ts
index 0278205..f550b88 100644
--- a/src/ControllerMethodArgs_test.ts
+++ b/src/ControllerMethodArgs_test.ts
@@ -636,30 +636,47 @@ Deno.test("getEnhancedHandler with a faulty ctx.request.body", async () => {
spyParseOakRequestBody.restore();
});
-Deno.test("getEnhancedHandler with a faulty request method and content-type combination", async () => {
+Deno.test("getEnhancedHandler with a non-conventional request method and content-type combination", async (t) => {
+ const methodsToTest = ["GET", "HEAD", "DELETE"];
const spyParseOakRequestBody = spy(_internal, "parseOakReqBody");
- function testHandler() {
- return "weird.method.content-type.combination.handled";
- }
- // deno-lint-ignore ban-types
- const enhancedHandler: Function = _internal.getEnhancedHandler(testHandler);
- const ctx = createMockContext({
- method: "GET",
- headers: [["Content-Type", "application/json"]],
- });
- Object.defineProperty(ctx.request, "body", {
- get: () => createMockRequestBody("json", "Unexpected end of JSON input"),
- });
- const spyCtxThrow = spy();
- Object.defineProperty(ctx, "throw", {
- value: (errorStatus: unknown, message?: string, props?: unknown) => {
- spyCtxThrow(errorStatus, message, props);
- },
- });
- const retVal = await enhancedHandler(ctx);
- assertSpyCalls(spyCtxThrow, 0);
- assertSpyCalls(spyParseOakRequestBody, 1);
- assertEquals(retVal, "weird.method.content-type.combination.handled");
+ await Promise.all(methodsToTest.map((method) =>
+ t.step({
+ name: `testing content-type: application/json and ${method} request`,
+ fn: async () => {
+ function testHandler() {
+ return `method ${method} and Content-Type: application/json handled`;
+ }
+ // deno-lint-ignore ban-types
+ const enhancedHandler: Function = _internal.getEnhancedHandler(
+ testHandler,
+ );
+ const ctx = createMockContext({
+ method, // GET | HEAD | DELETE
+ headers: [["Content-Type", "application/json"]],
+ });
+ Object.defineProperty(ctx.request, "body", {
+ get: () =>
+ createMockRequestBody("json", "Unexpected end of JSON input"),
+ });
+ const spyCtxThrow = spy();
+ Object.defineProperty(ctx, "throw", {
+ value: (errorStatus: unknown, message?: string, props?: unknown) => {
+ spyCtxThrow(errorStatus, message, props);
+ },
+ });
+ const retVal = await enhancedHandler(ctx);
+ assertSpyCalls(spyCtxThrow, 0);
+ assertEquals(
+ retVal,
+ `method ${method} and Content-Type: application/json handled`,
+ );
+ },
+ sanitizeOps: false,
+ sanitizeResources: false,
+ sanitizeExit: false,
+ })
+ ));
+ assertSpyCalls(spyParseOakRequestBody, methodsToTest.length);
spyParseOakRequestBody.restore();
});