import type {
Input,
InputToDataByType,
ParamKeys,
ParamKeyToRecord,
RemoveQuestion,
UndefinedIfHavingQuestion,
ValidationTypes,
} from './types.ts'
import { parseBody } from './utils/body.ts'
import type { BodyData } from './utils/body.ts'
import type { Cookie } from './utils/cookie.ts'
import { parse } from './utils/cookie.ts'
import type { UnionToIntersection } from './utils/types.ts'
import { getQueryStringFromURL, getQueryParam, getQueryParams } from './utils/url.ts'
export class HonoRequest
{
raw: Request
private paramData: Record | undefined
private validatedData: { [K in keyof ValidationTypes]?: {} }
private queryIndex: number
constructor(
request: Request,
paramData?: Record | undefined,
queryIndex: number = -1
) {
this.raw = request
this.paramData = paramData
this.queryIndex = queryIndex
this.validatedData = {}
}
param(key: RemoveQuestion>): UndefinedIfHavingQuestion>
param(): UnionToIntersection>>
param(key?: string): unknown {
if (this.paramData) {
if (key) {
const param = this.paramData[key]
return param ? (/\%/.test(param) ? decodeURIComponent(param) : param) : undefined
} else {
const decoded: Record = {}
for (const [key, value] of Object.entries(this.paramData)) {
if (value && typeof value === 'string') {
decoded[key] = /\%/.test(value) ? decodeURIComponent(value) : value
}
}
return decoded
}
}
return null
}
query(key: string): string
query(): Record
query(key?: string) {
const queryString = getQueryStringFromURL(this.url, this.queryIndex)
return getQueryParam(queryString, key)
}
queries(key: string): string[]
queries(): Record
queries(key?: string) {
const queryString = getQueryStringFromURL(this.url, this.queryIndex)
return getQueryParams(queryString, key)
}
header(name: string): string
header(): Record
header(name?: string) {
const headerData: Record = {}
this.raw.headers.forEach((value, key) => {
headerData[key] = value
})
if (name) {
return headerData[name.toLowerCase()]
} else {
return headerData
}
}
cookie(key: string): string | undefined
cookie(): Cookie
cookie(key?: string) {
const cookie = this.raw.headers.get('Cookie')
if (!cookie) return
const obj = parse(cookie)
if (key) {
const value = obj[key]
return value
} else {
return obj
}
}
async parseBody(): Promise {
return await parseBody(this.raw)
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async json(): Promise {
return this.raw.json() as T
}
async text() {
return this.raw.text()
}
async arrayBuffer() {
return this.raw.arrayBuffer()
}
async blob() {
return this.raw.blob()
}
async formData() {
return this.raw.formData()
}
addValidatedData(type: keyof ValidationTypes, data: {}) {
this.validatedData[type] = data
}
valid<
T extends keyof ValidationTypes = I extends Record
? R extends keyof ValidationTypes
? R
: never
: never
>(type: T): InputToDataByType
valid(): never
valid(type?: keyof ValidationTypes) {
if (type) {
return this.validatedData[type] as unknown
}
}
get url() {
return this.raw.url
}
get method() {
return this.raw.method
}
get headers() {
return this.raw.headers
}
get redirect() {
return this.raw.redirect
}
get body() {
return this.raw.body
}
get bodyUsed() {
return this.raw.bodyUsed
}
get cache() {
return this.raw.cache
}
get credentials() {
return this.raw.credentials
}
get integrity() {
return this.raw.integrity
}
get keepalive() {
return this.raw.keepalive
}
get mode() {
return this.raw.mode
}
get referrer() {
return this.raw.referrer
}
get refererPolicy() {
return this.raw.referrerPolicy
}
get signal() {
return this.raw.signal
}
}