mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-09 23:21:30 -07:00
Initial commit
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
import type { HonoApp } from '@repo/hono-helpers'
|
||||
import type { SharedHonoEnv, SharedHonoVariables } from '@repo/hono-helpers/src/types'
|
||||
|
||||
export type Env = SharedHonoEnv & {
|
||||
// add additional Bindings here
|
||||
}
|
||||
|
||||
/** Variables can be extended */
|
||||
export type Variables = SharedHonoVariables
|
||||
|
||||
export interface App extends HonoApp {
|
||||
Bindings: Env
|
||||
Variables: Variables
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
import { env } from 'cloudflare:workers'
|
||||
import { Hono } from 'hono'
|
||||
import { useWorkersLogger } from 'workers-tagged-logger'
|
||||
|
||||
import { getRequestLogData, logger, withNotFound, withOnError } from '@repo/hono-helpers'
|
||||
|
||||
import type { App } from './context'
|
||||
|
||||
const app = new Hono<App>()
|
||||
.use(
|
||||
'*',
|
||||
// middleware
|
||||
(c, next) =>
|
||||
useWorkersLogger(c.env.NAME, {
|
||||
environment: c.env.ENVIRONMENT,
|
||||
release: c.env.SENTRY_RELEASE,
|
||||
})(c, next)
|
||||
)
|
||||
|
||||
.onError(withOnError())
|
||||
.notFound(withNotFound())
|
||||
|
||||
.all('*', async (c) => {
|
||||
const url = new URL(c.req.url)
|
||||
|
||||
// we can also access env variables via
|
||||
// import { env } from 'cloudflare:workers'
|
||||
logger.info(`release: ${env.SENTRY_RELEASE}`)
|
||||
|
||||
let body: string | undefined
|
||||
if (['PUT', 'POST'].includes(c.req.method) && c.req.raw.body !== null) {
|
||||
body = await c.req.text()
|
||||
}
|
||||
|
||||
const headers = new Headers(c.req.raw.headers)
|
||||
|
||||
const data = {
|
||||
method: c.req.method,
|
||||
url: c.req.url,
|
||||
path: url.pathname,
|
||||
host: url.host,
|
||||
hostname: url.hostname,
|
||||
headers: Object.fromEntries(headers.entries()),
|
||||
body: body ?? null,
|
||||
}
|
||||
|
||||
logger
|
||||
.withTags({
|
||||
type: 'echoback_request',
|
||||
echoback_host: url.hostname,
|
||||
})
|
||||
.info(`echoback request: ${url.toString()}`, {
|
||||
data: JSON.stringify(data),
|
||||
request: getRequestLogData(c, Date.now()),
|
||||
})
|
||||
return c.json(data)
|
||||
})
|
||||
|
||||
export default app
|
||||
@@ -0,0 +1,143 @@
|
||||
import { exports } from 'cloudflare:workers'
|
||||
import { describe, expect, it, test } from 'vitest'
|
||||
|
||||
import '../../example-worker-echoback.app'
|
||||
|
||||
describe('echoback returns data about the request', () => {
|
||||
test('GET', async () => {
|
||||
const res = await exports.default.fetch('https://example.com/stuff?foo=bar', {
|
||||
headers: {
|
||||
'X-Test': 'true',
|
||||
},
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"body": null,
|
||||
"headers": {
|
||||
"x-test": "true",
|
||||
},
|
||||
"host": "example.com",
|
||||
"hostname": "example.com",
|
||||
"method": "GET",
|
||||
"path": "/stuff",
|
||||
"url": "https://example.com/stuff?foo=bar",
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
test('POST', async () => {
|
||||
const res = await exports.default.fetch('https://example.com/stuff?foo=bar', {
|
||||
method: 'POST',
|
||||
body: 'hello world!',
|
||||
headers: {
|
||||
'X-Test': 'true',
|
||||
},
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"body": "hello world!",
|
||||
"headers": {
|
||||
"content-length": "12",
|
||||
"content-type": "text/plain;charset=UTF-8",
|
||||
"x-test": "true",
|
||||
},
|
||||
"host": "example.com",
|
||||
"hostname": "example.com",
|
||||
"method": "POST",
|
||||
"path": "/stuff",
|
||||
"url": "https://example.com/stuff?foo=bar",
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
test('PUT', async () => {
|
||||
const res = await exports.default.fetch('https://example.com/stuff?foo=bar', {
|
||||
method: 'PUT',
|
||||
body: 'hello world!',
|
||||
headers: {
|
||||
'X-Test': 'true',
|
||||
},
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"body": "hello world!",
|
||||
"headers": {
|
||||
"content-length": "12",
|
||||
"content-type": "text/plain;charset=UTF-8",
|
||||
"x-test": "true",
|
||||
},
|
||||
"host": "example.com",
|
||||
"hostname": "example.com",
|
||||
"method": "PUT",
|
||||
"path": "/stuff",
|
||||
"url": "https://example.com/stuff?foo=bar",
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
test('PATCH', async () => {
|
||||
const res = await exports.default.fetch('https://example.com/stuff?foo=bar', {
|
||||
method: 'PATCH',
|
||||
body: 'hello world!',
|
||||
headers: {
|
||||
'X-Test': 'true',
|
||||
},
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"body": null,
|
||||
"headers": {
|
||||
"content-length": "12",
|
||||
"content-type": "text/plain;charset=UTF-8",
|
||||
"x-test": "true",
|
||||
},
|
||||
"host": "example.com",
|
||||
"hostname": "example.com",
|
||||
"method": "PATCH",
|
||||
"path": "/stuff",
|
||||
"url": "https://example.com/stuff?foo=bar",
|
||||
}
|
||||
`)
|
||||
})
|
||||
|
||||
test('DELETE', async () => {
|
||||
const res = await exports.default.fetch('https://example.com/stuff?foo=bar', {
|
||||
method: 'DELETE',
|
||||
body: 'hello world!',
|
||||
headers: {
|
||||
'X-Test': 'true',
|
||||
},
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toMatchInlineSnapshot(`
|
||||
{
|
||||
"body": null,
|
||||
"headers": {
|
||||
"content-length": "12",
|
||||
"content-type": "text/plain;charset=UTF-8",
|
||||
"x-test": "true",
|
||||
},
|
||||
"host": "example.com",
|
||||
"hostname": "example.com",
|
||||
"method": "DELETE",
|
||||
"path": "/stuff",
|
||||
"url": "https://example.com/stuff?foo=bar",
|
||||
}
|
||||
`)
|
||||
})
|
||||
})
|
||||
|
||||
it(`Doesn't return body for HEAD`, async () => {
|
||||
const res = await exports.default.fetch('https://example.com/stuff?foo=bar', {
|
||||
method: 'HEAD',
|
||||
headers: {
|
||||
'X-Test': 'true',
|
||||
},
|
||||
})
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.text()).toMatchInlineSnapshot(`""`)
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
/** Get hostname from url in lower case */
|
||||
export function getUrlHostname(url: string | URL): string {
|
||||
const hostname = typeof url === 'string' ? new URL(url).hostname : url.hostname
|
||||
return hostname.toLowerCase()
|
||||
}
|
||||
Reference in New Issue
Block a user