Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: honojs/hono
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.0.2
Choose a base ref
...
head repository: honojs/hono
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.0.3
Choose a head ref
  • 5 commits
  • 20 files changed
  • 2 contributors

Commits on Feb 14, 2024

  1. fix(jsx-renderer): support async component (#2211)

    * fix(jsx-renderer): support async component
    
    * denoify
    
    * use `jsx(component, ...)`
    
    * denoify
    
    Co-authored-by: Taku Amano <taku@taaas.jp>
    yusukebe and usualoma authored Feb 14, 2024
    Copy the full SHA
    48c6ce9 View commit details

Commits on Feb 15, 2024

  1. fix(context): Inherit current status if not specified (#2218)

    * fix(context): Inherit current status if not specified
    
    * chore: denoify
    usualoma authored Feb 15, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    06cb43a View commit details
  2. fix(hono-base): custom not found with middleware like compress (#2220)

    * fix(hono-base): custom not found with middleware like compress
    
    * denoify
    yusukebe authored Feb 15, 2024
    Copy the full SHA
    89f8e07 View commit details

Commits on Feb 16, 2024

  1. refactor: jsx streaming (#2216)

    * refactor(jsx): tweaks loop in order to avoid error for blank content
    
    * feat(jsx): add data-hono-target attribute to streaming content
    
    * chore: denoify
    
    * test: fix runtime_tests/deno-jsx/jsx.test.tsx
    usualoma authored Feb 16, 2024
    Copy the full SHA
    473a6f0 View commit details
  2. v4.0.3

    yusukebe committed Feb 16, 2024
    Copy the full SHA
    553d555 View commit details
2 changes: 1 addition & 1 deletion deno_dist/context.ts
Original file line number Diff line number Diff line change
@@ -359,7 +359,7 @@ export class Context<
const headers = setHeaders(new Headers(arg.headers), this.#preparedHeaders)
return new Response(data, {
headers,
status: arg.status,
status: arg.status ?? this.#status,
})
}

7 changes: 3 additions & 4 deletions deno_dist/hono-base.ts
Original file line number Diff line number Diff line change
@@ -332,10 +332,9 @@ class Hono<
if (matchResult[0].length === 1) {
let res: ReturnType<H>
try {
res = matchResult[0][0][0][0](c, async () => {})
if (!res) {
return this.notFoundHandler(c)
}
res = matchResult[0][0][0][0](c, async () => {
c.res = await this.notFoundHandler(c)
})
} catch (err) {
return this.handleError(err, c)
}
6 changes: 3 additions & 3 deletions deno_dist/jsx/components.ts
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ export const ErrorBoundary: FC<
}
return buffer
? ''
: `<template>${fallbackResString}</template><script>
: `<template data-hono-target="E:${index}">${fallbackResString}</template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('E:${index}')
@@ -100,7 +100,7 @@ d.replaceWith(c.content)
const content = htmlArray.join('')
let html = buffer
? ''
: `<template>${content}</template><script>
: `<template data-hono-target="E:${index}">${content}</template><script>
((d,c) => {
c=d.currentScript.previousSibling
d=d.getElementById('E:${index}')
@@ -161,7 +161,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
d=d.getElementById('E:${index}')
if(!d)return
n=d.nextSibling
do{n=n.nextSibling}while(n.nodeType!=8||n.nodeValue!='E:${index}')
while(n.nodeType!=8||n.nodeValue!='E:${index}'){n=n.nextSibling}
n.remove()
d.remove()
})(document)
2 changes: 1 addition & 1 deletion deno_dist/jsx/streaming.ts
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ export const Suspense: FC<PropsWithChildren<{ fallback: any }>> = async ({
}
let html = buffer
? ''
: `<template>${content}</template><script>
: `<template data-hono-target="H:${index}">${content}</template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${index}')
17 changes: 11 additions & 6 deletions deno_dist/middleware/jsx-renderer/index.ts
Original file line number Diff line number Diff line change
@@ -32,20 +32,23 @@ const createRenderer =
? ''
: '<!DOCTYPE html>'

/* eslint-disable @typescript-eslint/no-explicit-any */
const currentLayout = component
? component({
children,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...{ Layout, ...(props as any) },
})
? jsx(
component,
{
...{ Layout, ...(props as any) },
},
children as any
)
: children

const body = html`${raw(docType)}${jsx(
RequestContext.Provider,
{ value: c },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
currentLayout as any
)}`
/* eslint-enable @typescript-eslint/no-explicit-any */

if (options?.stream) {
return c.body(renderToReadableStream(body), {
@@ -78,7 +81,9 @@ export const jsxRenderer = (
}

export const useRequestContext = <
// eslint-disable-next-line @typescript-eslint/no-explicit-any
E extends Env = any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
P extends string = any,
I extends Input = {}
>(): Context<E, P, I> => {
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hono",
"version": "4.0.2",
"version": "4.0.3",
"description": "Ultrafast web framework for the Edges",
"main": "dist/cjs/index.js",
"type": "module",
2 changes: 1 addition & 1 deletion runtime_tests/deno-jsx/jsx.test.tsx
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ Deno.test('JSX: Suspense', async () => {

assertEquals(chunks, [
'<template id="H:0"></template><p>Loading...</p><!--/$-->',
`<template><h1>Hello</h1></template><script>
`<template data-hono-target="H:0"><h1>Hello</h1></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:0')
14 changes: 14 additions & 0 deletions src/context.test.ts
Original file line number Diff line number Diff line change
@@ -128,6 +128,20 @@ describe('Context', () => {
expect(c.res.status).toBe(201)
})

it('Inherit current status if not specified', async () => {
c.status(201)
const res = c.newResponse('this is body', {
headers: {
'x-custom3': 'Message3',
'x-custom2': 'Message2-Override',
},
})
expect(res.headers.get('x-Custom2')).toBe('Message2-Override')
expect(res.headers.get('x-Custom3')).toBe('Message3')
expect(res.status).toBe(201)
expect(await res.text()).toBe('this is body')
})

it('Should append the previous headers to new Response', () => {
c.res.headers.set('x-Custom1', 'Message1')
const res2 = new Response('foo2', {
2 changes: 1 addition & 1 deletion src/context.ts
Original file line number Diff line number Diff line change
@@ -359,7 +359,7 @@ export class Context<
const headers = setHeaders(new Headers(arg.headers), this.#preparedHeaders)
return new Response(data, {
headers,
status: arg.status,
status: arg.status ?? this.#status,
})
}

2 changes: 1 addition & 1 deletion src/helper/css/index.test.tsx
Original file line number Diff line number Diff line change
@@ -240,7 +240,7 @@ describe('CSS Helper', () => {
const res = await app.request('http://localhost/stream')
expect(res).not.toBeNull()
expect(await res.text()).toBe(
`<style id="hono-css"></style><template id="H:0"></template><p>Loading...</p><!--/$--><script>document.querySelector('#hono-css').textContent+=".css-2458908649{background-color:blue}"</script><template><h1 class="css-2458908649">Hello!</h1></template><script>
`<style id="hono-css"></style><template id="H:0"></template><p>Loading...</p><!--/$--><script>document.querySelector('#hono-css').textContent+=".css-2458908649{background-color:blue}"</script><template data-hono-target="H:0"><h1 class="css-2458908649">Hello!</h1></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:0')
7 changes: 3 additions & 4 deletions src/hono-base.ts
Original file line number Diff line number Diff line change
@@ -332,10 +332,9 @@ class Hono<
if (matchResult[0].length === 1) {
let res: ReturnType<H>
try {
res = matchResult[0][0][0][0](c, async () => {})
if (!res) {
return this.notFoundHandler(c)
}
res = matchResult[0][0][0][0](c, async () => {
c.res = await this.notFoundHandler(c)
})
} catch (err) {
return this.handleError(err, c)
}
20 changes: 20 additions & 0 deletions src/hono.test.ts
Original file line number Diff line number Diff line change
@@ -1258,6 +1258,26 @@ describe('Not Found', () => {
expect(await res.text()).toBe('404 Not Found')
})
})

describe('Custom 404 Not Found with a middleware like Compress Middleware', () => {
const app = new Hono()

// Custom Middleware which creates a new Response object after `next()`.
app.use('*', async (c, next) => {
await next()
c.res = new Response(await c.res.text(), c.res)
})

app.notFound((c) => {
return c.text('Custom NotFound', 404)
})

it('Custom 404 Not Found', async () => {
const res = await app.request('http://localhost/')
expect(res.status).toBe(404)
expect(await res.text()).toBe('Custom NotFound')
})
})
})

describe('Redirect', () => {
6 changes: 3 additions & 3 deletions src/jsx/components.test.tsx
Original file line number Diff line number Diff line change
@@ -191,15 +191,15 @@ describe('ErrorBoundary', () => {

expect(chunks).toEqual([
`<template id="E:${errorBoundaryCounter}"></template><!--E:${errorBoundaryCounter}-->`,
`<template><template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$--></template><script>
`<template data-hono-target="E:${errorBoundaryCounter}"><template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$--></template><script>
((d,c) => {
c=d.currentScript.previousSibling
d=d.getElementById('E:${errorBoundaryCounter}')
if(!d)return
d.parentElement.insertBefore(c.content,d.nextSibling)
})(document)
</script>`,
`<template><div>Hello</div></template><script>
`<template data-hono-target="H:${suspenseCounter}"><div>Hello</div></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
@@ -212,7 +212,7 @@ d.replaceWith(c.content)
d=d.getElementById('E:${errorBoundaryCounter}')
if(!d)return
n=d.nextSibling
do{n=n.nextSibling}while(n.nodeType!=8||n.nodeValue!='E:${errorBoundaryCounter}')
while(n.nodeType!=8||n.nodeValue!='E:${errorBoundaryCounter}'){n=n.nextSibling}
n.remove()
d.remove()
})(document)
6 changes: 3 additions & 3 deletions src/jsx/components.ts
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ export const ErrorBoundary: FC<
}
return buffer
? ''
: `<template>${fallbackResString}</template><script>
: `<template data-hono-target="E:${index}">${fallbackResString}</template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('E:${index}')
@@ -100,7 +100,7 @@ d.replaceWith(c.content)
const content = htmlArray.join('')
let html = buffer
? ''
: `<template>${content}</template><script>
: `<template data-hono-target="E:${index}">${content}</template><script>
((d,c) => {
c=d.currentScript.previousSibling
d=d.getElementById('E:${index}')
@@ -161,7 +161,7 @@ d.parentElement.insertBefore(c.content,d.nextSibling)
d=d.getElementById('E:${index}')
if(!d)return
n=d.nextSibling
do{n=n.nextSibling}while(n.nodeType!=8||n.nodeValue!='E:${index}')
while(n.nodeType!=8||n.nodeValue!='E:${index}'){n=n.nextSibling}
n.remove()
d.remove()
})(document)
2 changes: 1 addition & 1 deletion src/jsx/index.test.tsx
Original file line number Diff line number Diff line change
@@ -653,7 +653,7 @@ describe('Context', () => {

expect(chunks).toEqual([
'<template id="H:0"></template><span>red</span><!--/$-->',
`<template><span>dark</span><span>black</span></template><script>
`<template data-hono-target="H:0"><span>dark</span><span>black</span></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:0')
18 changes: 9 additions & 9 deletions src/jsx/streaming.test.tsx
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@ describe('Streaming', () => {

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$-->`,
`<template><h1>Hello</h1></template><script>
`<template data-hono-target="H:${suspenseCounter}"><h1>Hello</h1></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
@@ -92,7 +92,7 @@ d.replaceWith(c.content)

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$-->`,
`<template><p>thrown a promise then resolved</p></template><script>
`<template data-hono-target="H:${suspenseCounter}"><p>thrown a promise then resolved</p></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
@@ -208,7 +208,7 @@ d.replaceWith(c.content)

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$-->`,
`<template><p></p></template><script>
`<template data-hono-target="H:${suspenseCounter}"><p></p></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
@@ -242,7 +242,7 @@ d.replaceWith(c.content)

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$-->`,
`<template><p></p></template><script>
`<template data-hono-target="H:${suspenseCounter}"><p></p></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
@@ -316,7 +316,7 @@ d.replaceWith(c.content)

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$-->`,
`<template><h1>Hello</h1><h2>World</h2></template><script>
`<template data-hono-target="H:${suspenseCounter}"><h1>Hello</h1><h2>World</h2></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
@@ -362,7 +362,7 @@ d.replaceWith(c.content)

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template>Loading<span>...</span><!--/$-->`,
`<template><h1>Hello</h1></template><script>
`<template data-hono-target="H:${suspenseCounter}"><h1>Hello</h1></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
@@ -418,7 +418,7 @@ d.replaceWith(c.content)

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$-->`,
`<template><h1>Hello</h1><template id=\"H:${
`<template data-hono-target="H:${suspenseCounter}"><h1>Hello</h1><template id=\"H:${
suspenseCounter + 1
}\"></template><p>Loading sub content...</p><!--/$--></template><script>
((d,c,n) => {
@@ -429,7 +429,7 @@ do{n=d.nextSibling;n.remove()}while(n.nodeType!=8||n.nodeValue!='/$')
d.replaceWith(c.content)
})(document)
</script>`,
`<template><h2>World</h2></template><script>
`<template data-hono-target="H:${suspenseCounter + 1}"><h2>World</h2></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter + 1}')
@@ -605,7 +605,7 @@ d.replaceWith(c.content)

expect(chunks).toEqual([
`<template id="H:${suspenseCounter}"></template><p>Loading...</p><!--/$-->`,
`<template><h1>Hello from use()</h1></template><script>
`<template data-hono-target="H:${suspenseCounter}"><h1>Hello from use()</h1></template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${suspenseCounter}')
2 changes: 1 addition & 1 deletion src/jsx/streaming.ts
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ export const Suspense: FC<PropsWithChildren<{ fallback: any }>> = async ({
}
let html = buffer
? ''
: `<template>${content}</template><script>
: `<template data-hono-target="H:${index}">${content}</template><script>
((d,c,n) => {
c=d.currentScript.previousSibling
d=d.getElementById('H:${index}')
33 changes: 33 additions & 0 deletions src/middleware/compress/index.test.ts
Original file line number Diff line number Diff line change
@@ -9,6 +9,9 @@ describe('Parse Compress Middleware', () => {
ctx.header('Content-Length', '5')
return ctx.text('hello')
})
app.notFound((c) => {
return c.text('Custom NotFound', 404)
})

it('gzip', async () => {
const req = new Request('http://localhost/hello', {
@@ -56,4 +59,34 @@ describe('Parse Compress Middleware', () => {
expect(res.headers.get('Content-Encoding')).toBeNull()
expect(res.headers.get('Content-Length')).toBe('5')
})

it('Should handle Custom 404 Not Found', async () => {
const req = new Request('http://localhost/not-found', {
method: 'GET',
headers: new Headers({ 'Accept-Encoding': 'gzip' }),
})
const res = await app.request(req)
expect(res).not.toBeNull()
expect(res.status).toBe(404)
expect(res.headers.get('Content-Encoding')).toEqual('gzip')

// decompress response body
const decompressionStream = new DecompressionStream('gzip')
const decompressedStream = res.body!.pipeThrough(decompressionStream)

const textDecoder = new TextDecoder()
const reader = decompressedStream.getReader()
let text = ''

for (;;) {
const { done, value } = await reader.read()
if (done) {
break
}
text += textDecoder.decode(value, { stream: true })
}

text += textDecoder.decode()
expect(text).toBe('Custom NotFound')
})
})
Loading