Skip to content

Commit

Permalink
fix: 216 withContent returning 500 (#217)
Browse files Browse the repository at this point in the history
Fix to return a 400 instead of a 500 when using the `withContent` middleware and sending no content of invalid JSON in the request body.
  • Loading branch information
smcstewart authored Mar 12, 2024
1 parent 415b2c1 commit 1c4f67b
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 2 deletions.
60 changes: 60 additions & 0 deletions src/withContent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'isomorphic-fetch'
import { describe, expect, it, vi } from 'vitest'
import { Router } from './Router'
import { withContent } from './withContent'
import { StatusError } from './StatusError'

describe('withContent (middleware)', () => {
it('can access the awaited Response body as request.content', async () => {
Expand All @@ -19,4 +20,63 @@ describe('withContent (middleware)', () => {

expect(handler).toHaveReturnedWith({ foo: 'bar' })
})

it('throws an "Unexpected end of JSON input" error when no content is sent in the body', async () => {
const router = Router()
const handler = vi.fn(({ content }) => content)
const request = new Request('https://foo.bar', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
})

await expect(
router.post('/', withContent, handler).handle(request)
).rejects.toThrowError(/Unexpected end of JSON input/)

expect(handler).not.toHaveBeenCalled()
expect(handler).not.toHaveReturned()
})

it('returns a 400 when no content is sent in the body', async () => {
const router = Router()
const handler = vi.fn(({ content }) => content)
const request = new Request('https://foo.bar', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
})

try {
await router.post('/', withContent, handler).handle(request)
} catch (e) {
expect(e).toBeInstanceOf(StatusError)
expect(e).toContain({ status: 400 })
}
expect(handler).not.toHaveBeenCalled()
expect(handler).not.toHaveReturned()
})

it('returns a 400 when invalid JSON content is sent in the body', async () => {
const router = Router()
const handler = vi.fn(({ content }) => content)
const request = new Request('https://foo.bar', {
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: 'foo is invalid JSON',
})

try {
await router.post('/', withContent, handler).handle(request)
} catch (e) {
expect(e).toBeInstanceOf(StatusError)
expect(e).toContain({ status: 400 })
}
expect(handler).not.toHaveBeenCalled()
expect(handler).not.toHaveReturned()
})
})
10 changes: 8 additions & 2 deletions src/withContent.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { IRequest, IRequestStrict } from './Router'
import { StatusError } from './StatusError'

export type HasContent<ContentType> = {
content: ContentType,
content: ContentType
} & IRequestStrict

// withContent - embeds any request body as request.content
export const withContent = async (request: IRequest): Promise<void> => {
if (request.headers.get('content-type')?.includes('json'))
request.content = await request.json()
try {
request.content = await request.json()
} catch (e: unknown) {
const se = e as SyntaxError
throw new StatusError(400, se.message)
}
}

0 comments on commit 1c4f67b

Please sign in to comment.