Skip to content

Commit

Permalink
v0.12.1 - see CHANGELOG for details (#37)
Browse files Browse the repository at this point in the history
  • Loading branch information
Thesephi authored Nov 5, 2024
1 parent f03686a commit bb1d0db
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 35 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -96,13 +96,13 @@ curl localhost:1993/v1/hello/world # prints: hello, world
<summary>View Example</summary>

```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 {
Expand Down Expand Up @@ -133,13 +133,13 @@ curl -H"Content-Type: application/json" localhost:1993/v1/tell/alice -d'{"messag
<summary>View Example</summary>

```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 {
Expand Down Expand Up @@ -170,8 +170,8 @@ curl localhost:1993/v1/books/thriller\?page=2
<summary>View Example</summary>

```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 {
Expand Down
2 changes: 1 addition & 1 deletion jsr.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@dklab/oak-routing-ctrl",
"version": "0.12.0",
"version": "0.12.1",
"exports": {
".": "./mod.ts",
"./mod": "./mod.ts"
Expand Down
8 changes: 5 additions & 3 deletions src/ControllerMethodArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
63 changes: 40 additions & 23 deletions src/ControllerMethodArgs_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});

Expand Down

0 comments on commit bb1d0db

Please sign in to comment.