Skip to content

Instantly share code, notes, and snippets.

@yusukebe
Last active March 26, 2024 13:47
Show Gist options
  • Save yusukebe/180bfcf261d142df4e233e90e65cb63b to your computer and use it in GitHub Desktop.
Save yusukebe/180bfcf261d142df4e233e90e65cb63b to your computer and use it in GitHub Desktop.
type MethodOverrideOptions = {
// Default is 'form' and the value is `_method`
form?: string
header?: string
query?: string
}
const DEFAULT_METHOD_FORM_NAME = '_method'
const methodOverride = (options?: MethodOverrideOptions): MiddlewareHandler =>
async function methodOverride(c, next) {
// Method override by form
if (!options || options.form || !(options.form || options.header || options.query)) {
const methodFormName = options?.form || DEFAULT_METHOD_FORM_NAME
const contentType = c.req.header('content-type')
if (!(contentType === 'multipart/form-data' || contentType === 'application/x-www-form-urlencoded')) {
return await next()
}
const clonedRequest = c.req.raw.clone()
const newRequest = clonedRequest.clone()
const form = await clonedRequest.formData()
const method = form.get(methodFormName)
if (method) {
const newForm = await newRequest.formData()
newForm.delete(methodFormName)
const newHeaders = new Headers(clonedRequest.headers)
newHeaders.delete('content-type')
newHeaders.delete('content-length')
const request = new Request(c.req.url, {
body: newForm,
headers: newHeaders,
method
})
return app.fetch(request, c.env, c.executionCtx)
}
}
// Method override by header
else if (options.header) {
const headerName = options.header
const method = c.req.header(headerName)
if (method) {
const newHeaders = new Headers(c.req.raw.headers)
newHeaders.delete(headerName)
const request = new Request(c.req.raw, {
headers: newHeaders,
method
})
return app.fetch(request, c.env, c.executionCtx)
}
}
// Method override by query
else if (options.query) {
const queryName = options.query
const method = c.req.query(queryName)
if (method) {
const url = new URL(c.req.url)
url.searchParams.delete(queryName)
const request = new Request(url.toString(), {
body: c.req.raw.body,
headers: c.req.raw.headers,
method
})
return app.fetch(request, c.env, c.executionCtx)
}
}
await next()
}
@usualoma
Copy link

Thanks for the explanation about the content-type, I understand. Thanks!

@yusukebe
Copy link
Author

@usualoma

Created the PR! honojs/hono#2420

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment