You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
5.5 KiB

import { ServerRequest } from '../external/http.ts'
import { HTTPProtocol, HTTPRequest, RemoteHost } from './type/HTTPRequest.ts'
import { Response } from './Response.ts'
import { HTTPResponse } from './type/HTTPResponse.ts'
import Utility from '../service/utility/Utility.ts'
import { Injectable } from '../../../di/src/decorator/Injection.ts'
import SessionInterface from './session/SessionInterface.ts'
import ActivatedRoute from './routing/ActivatedRoute.ts'
/**
* Base class for Daton-managed HTTP requests.
* @implements HTTPRequest
*/
@Injectable()
export class Request implements HTTPRequest {
/**
* The associated response object.
* @type HTTPResponse
*/
public readonly response: HTTPResponse
/**
* The base raw Deno request.
* @type ServerRequest
*/
private readonly _deno_req: ServerRequest
/**
* The parsed body.
*/
private _body: any
/**
* The parsed query params.
* @type object
*/
private _query: { [key: string]: any } = {}
/**
* The associated session.
* @type SessionInterface
*/
private _session!: SessionInterface
/**
* The matched, mounted route.
* @type ActivatedRoute
*/
private _activated_route!: ActivatedRoute
/**
* The incoming URL.
* @type string
*/
public readonly url: string
/**
* The incoming request method.
* @type string
*/
public readonly method: string
/**
* The incoming HTTP protocol.
* @type HTTPProtocol
*/
public readonly protocol: HTTPProtocol
/**
* The underlying Deno connection.
* @type Deno.Conn
*/
public readonly connection: Deno.Conn
/**
* True if the request used HTTPS.
* @type boolean
*/
public readonly secure: boolean = false
/**
* The incoming headers.
*/
public get headers() {
return this._deno_req.headers
}
/**
* Get the underlying Deno request.
* @type ServerRequest
*/
get to_native(): ServerRequest {
return this._deno_req
}
/**
* Get the cookies for the response.
* @type CookieJar
*/
get cookies() {
return this.response.cookies
}
/**
* Get the associated session.
* @type SessionInterface
*/
get session(): SessionInterface {
return this._session
}
/**
* Set the associated session.
* @param {SessionInterface} session
*/
set session(session: SessionInterface) {
if ( !this._session )
this._session = session
}
/**
* Get the activated route mounted to this request.
* @type ActivatedRoute
*/
get route(): ActivatedRoute {
return this._activated_route
}
/**
* Mount the given route to the request.
* @param {ActivatedRoute} route
*/
set route(route: ActivatedRoute) {
if ( !this._activated_route )
this._activated_route = route
}
constructor(
protected utility: Utility,
/**
* The raw Deno request.
*/
from: ServerRequest
) {
this._deno_req = from
this.url = this._deno_req.url
this.method = this._deno_req.method.toLowerCase()
this.protocol = {
string: this._deno_req.proto,
major: this._deno_req.protoMajor,
minor: this._deno_req.protoMinor,
}
this.connection = this._deno_req.conn
this.response = new Response(this)
}
/**
* Prepare the request for the Daton framework.
* @return Promise<void>
*/
public async prepare() {
this._body = await Deno.readAll(this._deno_req.body)
const url_params = new URLSearchParams(this.url.substr(1))
const param_obj = Object.fromEntries(url_params)
const params: any = {}
for ( const key in param_obj ) {
if ( !param_obj.hasOwnProperty(key) ) continue
if ( param_obj[key] === '' ) params[key] = true
else params[key] = this.utility.infer(param_obj[key])
}
this._query = params
}
/**
* Send the given response.
* @param res
*/
respond(res: any) {
return this._deno_req.respond(res)
}
// public body: RequestBody = {}
// public original_body: RequestBody = {}
/**
* Get the remote host information.
* @type RemoteHost
*/
get remote() {
return this.connection.remoteAddr as RemoteHost
}
/**
* Get the raw body from the request.
* @type string
*/
get body() {
return this._body
}
/**
* Get the query params.
* @type object
*/
get query() {
return this._query
}
/**
* Get the incoming host name.
* @type string
*/
get hostname() {
return this.headers.get('host')?.split(':')[0]
}
/**
* Get the incoming path of the route.
* @type string
*/
get path() {
return this.url.split('?')[0].split('#')[0]
}
/**
* True if the request is an XHR incoming.
* @type boolean
*/
get xhr() {
return this.headers.get('x-requested-with')?.toLowerCase() === 'xmlhttprequest'
}
/*
body
fresh/stale - cache
remote ips (proxy)
params
route?
signedCookies
*/
/*
accepts content type
accepts charsets
accepts encodings
accepts languages
get header
is content type
get param with default value
get input with default value
range header parser
*/
}