///
///
///
import InternalRequestContext from "../../types/internal/classes/RequestContext";
import { HttpContext } from "../../types/implementation/contexts/http";
import { Content, JSONParsed, ParsedBody, RatelimitInfos } from "../../types/global";
import Base from "./Base";
import { ZodResponse } from "../../types/internal";
import { z } from "zod";
import { Writable } from "stream";
import YieldedResponse from "../YieldedResponse";
import Server from "../Server";
export default class HttpRequestContext = {}> extends Base {
protected rawContext: HttpContext;
protected abort: AbortSignal;
constructor(context: InternalRequestContext, server: Server, rawContext: HttpContext, abort: AbortSignal);
/**
* The Type of this Request
* @since 5.7.0
*/ readonly type: 'http' | 'ws';
/**
* HTTP Status Codes Enum
* @since 9.0.0
*/ $status: Readonly<{
CONTINUE: 100;
SWITCHING_PROTOCOLS: 101;
PROCESSING: 102;
EARLY_HINTS: 103;
OK: 200;
CREATED: 201;
ACCEPTED: 202;
NON_AUTHORATIVE_INFORMATION: 203;
NO_CONTENT: 204;
RESET_CONTENT: 205;
PARTIAL_CONTENT: 206;
MULTI_STATUS: 207;
ALREADY_REPORTED: 208;
IM_USED: 226;
MULTIPLE_CHOICES: 300;
MOVED_PERMANENTLY: 301;
FOUND: 302;
SEE_OTHER: 303;
NOT_MODIFIED: 304;
USE_PROXY: 305;
TEMPORARY_REDIRECT: 307;
PERMANENT_REDIRECT: 308;
BAD_REQUEST: 400;
UNAUTHORIZED: 401;
PAYMENT_REQUIRED: 402;
FORBIDDEN: 403;
NOT_FOUND: 404;
METHOD_NOT_ALLOWED: 405;
NOT_ACCEPTABLE: 406;
PROXY_AUTHENTICATION_REQUIRED: 407;
REQUEST_TIMEOUT: 408;
CONFLICT: 409;
GONE: 410;
LENGTH_REQUIRED: 411;
PRECONDITION_FAILED: 412;
PAYLOAD_TOO_LARGE: 413;
URI_TOO_LONG: 414;
UNSUPPORTED_MEDIA_TYPE: 415;
RANGE_NOT_SATISFIABLE: 416;
EXPECTATION_FAILED: 417;
IM_A_TEAPOT: 418;
MISDIRECTED_REQUEST: 421;
UNPROCESSABLE_ENTITY: 422;
LOCKED: 423;
FAILED_DEPENDENCY: 424;
TOO_EARLY: 425;
UPGRADE_REQUIRED: 426;
PRECONDITION_REQUIRED: 428;
TOO_MANY_REQUESTS: 429;
REQUEST_HEADER_FIELDS_TOO_LARGE: 431;
UNAVAILABLE_FOR_LEGAL_REASONS: 451;
INTERNAL_SERVER_ERROR: 500;
NOT_IMPLEMENTED: 501;
BAD_GATEWAY: 502;
SERVICE_UNAVAILABLE: 503;
GATEWAY_TIMEOUT: 504;
HTTP_VERSION_NOT_SUPPORTED: 505;
VARIANT_ALSO_NEGOTIATES: 506;
INSUFFICIENT_STORAGE: 507;
LOOP_DETECTED: 508;
BANDWIDTH_LIMIT_EXCEEDED: 509;
NOT_EXTENDED: 510;
NETWORK_AUTHENTICATION_REQUIRED: 511;
}>;
/**
* HTTP Abort Controller (please use to decrease server load)
* @since 9.0.0
*/ $abort(callback?: () => void): boolean;
/**
* The Request Body as a Blob-like Object
* @example
* ```
* const size = await ctr.$body().size()
*
* return ctr.print(`The size of the body is ${size} bytes`)
* ```
* @since 9.7.0
*/ $body(): {
text(): Promise;
json(): Promise;
arrayBuffer(): Promise;
formData(): Promise>;
blob(): Promise;
size(): Promise;
};
/**
* The Request Body (JSON and Urlencoding Automatically parsed if enabled)
* @since 0.4.0
*/ body(): Promise;
/**
* The HTTP Body Type
* @since 9.0.0
*/ bodyType(): Promise<'raw' | 'json' | 'url-encoded'>;
/**
* The Raw Request Body
* @since 5.5.2
*/ rawBody(encoding: BufferEncoding): Promise;
/**
* The Raw Request Body as Buffer
* @since 8.1.4
*/ rawBodyBytes(): Promise;
/**
* Bind the Body using Zod
*
* This uses `.body` internally so no binary data
* @example
* ```
* const [ data, error ] = await ctr.bindBody((z) => z.object({
* name: z.string().max(24),
* gender: z.union([ z.literal('male'), z.literal('female') ])
* }))
*
* if (!data) return ctr.status(ctr.$status.BAD_REQUEST).print(error.toString())
*
* ctr.print('Everything valid! 👍')
* ctr.printPart(`
* your name is ${data.name}
* and you are a ${data.gender}
* `)
* ```
* @since 8.8.0
*/ bindBody(schema: Schema | ((z: typeof import('zod')) => Schema)): Promise>;
/**
* HTTP WWW-Authentication Checker
*
* This will validate the Authorization Header using the WWW-Authentication Standard,
* you can choose between `basic` and `digest` authentication, in most cases `digest`
* should be used unless you are using an outdated client or want to test easily.
* When not matching any user the method will return `null` and the request should be
* ended with a `Status.UNAUTHORIZED` (401) status code.
* @example
* ```
* const user = ctr.wwwAuth('basic', 'Access this Page.', { // Automatically adds www-authenticate header
* bob: '123!',
* rotvproHD: 'password'
* })
*
* if (!user) return ctr.status(ctr.$status.UNAUTHORIZED).print('Invalid credentials')
*
* ctr.print(`You authenticated with user: ${user}`)
* ```
* @since 8.0.0
*/ wwwAuth>(type: 'basic' | 'digest', reason: string, users: Users): keyof Users | null;
/**
* Yield the Request to the next Route that matches the URL
*
* This will yield the request to the next route that matches the URL, this is useful
* if you want to have multiple routes that match the same URL but have different methods
* or if you want to have a fallback route that matches all URLs. You can also pass data
* to the next route by providing it as an argument.
* @example
* ```
* const server = new Server(...)
*
* server.path('/api', (path) => path
* .http('GET', '/', (http) => http
* .onRequest((ctr) => {
* if (ctr.queries.has('yield')) return ctr.yield('Hello World!')
*
* ctr.headers.set('content-type', 'text/html')
* ctr.print('yield this shit')
* })
* )
* .http('GET', '/', (http) => http
* .onRequest((ctr) => {
* ctr.print(`u yielded, ${ctr.yield().data()}`) // u yielded, Hello World!
* })
* )
* )
* ```
* @since 9.2.0
*/ yield(data?: Data): YieldedResponse;
/**
* Clear the active Ratelimit of the Client
*
* This Clears the currently active Ratelimit (on this endpoint) of the Client, remember:
* you cant call this in a normal endpoint if the max hits are already reached since well...
* they are already reached.
* @since 8.6.0
*/ clearRateLimit(): this;
/**
* Skips counting the request to the Client IPs Rate limit (if there is one)
*
* When a specific IP makes a request to an endpoint under a ratelimit, the maxhits will be
* increased instantly to prevent bypassing the rate limit by spamming requests faster than the host can
* handle. When this function is called, the server removes the set hit again.
* @since 8.6.0
*/ skipRateLimit(): this;
/**
* Get Infos about the current Ratelimit
*
* This will get all information about the currently applied ratelimit
* to the endpoint. If none is active, will return `null`.
* @since 8.6.0
*/ getRateLimit(): RatelimitInfos | null;
/**
* Add a Header the response depended on (vary header)
*
* This will add a header to the response that tells the client that the response
* is dependent on the value of the header, this is useful if you want to cache
* responses that are dependent on the value of a header.
* @example
* ```
* switch (ctr.client.origin) {
* case "localhost": {
* return ctr.vary('origin').print('Hi, ur cool')
* }
*
* default: {
* return ctr.vary('origin').print('You are gay.')
* }
* }
* ```
* @since 9.3.4
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary
*/ vary(header: string): this;
/**
* The Request Status to Send
*
* This will set the status of the request that the client will recieve, by default
* the status will be `200`, the server will not change this value unless calling the
* `.redirect()` method. If you want to add a custom message to the status you can provide
* a second argument that sets that, for RFC documented codes this will automatically be
* set but can be overridden, the mapping is provided by `http.STATUS_CODES`
* @example
* ```
* ctr.status(401).print('Unauthorized')
*
* // or
* ctr.status(666, 'The Devil').print('The Devil')
*
* // or
* ctr.status(ctr.$status.IM_A_TEAPOT).print('Im a Teapot, mate!')
* ```
* @since 0.0.2
*/ status(code: number, message?: string): this;
/**
* Redirect a Client to another URL
*
* This will set the location header and the status to either to 301 or 302 depending
* on whether the server should tell the browser that the page has permanently moved
* or temporarily. Obviously this will only work correctly if the client supports the
* 30x Statuses combined with the location header.
* @example
* ```
* ctr.redirect('https://example.com', 'permanent') // Will redirect to that URL
* ```
* @since 2.8.5
*/ redirect(location: string, type?: 'temporary' | 'permanent'): this;
/**
* Print a Message to the Client (automatically Formatted)
*
* This Message will be the one actually sent to the client, nothing
* can be "added" to the content using this function, it can only be replaced using `.print()`
* To add content to the response body, use `.printPart()` instead.
* @example
* ```
* ctr.print({
* message: 'this is json!'
* })
*
* // content will be `{"message":"this is json!"}`
*
* /// or
*
* ctr.print({
* message: 'this is json!'
* }, true)
* // content will be `{\n "message": "this is json!"\n}`
*
* /// or
*
* ctr.print('this is text!')
* // content will be `this is text!`
* ```
* @since 0.0.2
*/ print(content: Content, prettify?: boolean): this;
/**
* Print a Message to the client (without resetting the previous message state)
*
* This will turn your response into a chunked response, this means that you cannot
* add headers or cookies after this function has been called. This function is useful
* if you want to add content to the response body without resetting the previous content.
* And when you manually want to print massive amounts of data to the client without having
* to store it in memory.
* @example
* ```
* const file = fs.createReadStream('./10GB.bin')
*
* ctr.printChunked((print) => new Promise((end) => {
* file.on('data', (chunk) => {
* file.pause()
* print(chunk)
* .then(() => file.resume())
* })
*
* file.on('end', () => {
* end()
* })
*
* ctr.$abort(() => {
* file.destroy()
* end()
* })
* }))
* ```
* @since 8.2.0
*/ printChunked Promise) => Promise) | null>(callback: Callback): Callback extends null ? Writable : this;
/**
* Print the Content of a File to the Client
*
* This will print a file to the client using transfer encoding chunked and
* if `addTypes` is enabled automatically add some content types based on the
* file extension. This function wont respect any other http response body set by
* `.print()` or any other normal print as this overwrites the custom ctx execution
* function.
* @example
* ```
* ctr.printFile('./profile.png', {
* addTypes: true // Automatically add Content types
* })
* ```
* @since 0.6.3
*/ printFile(file: string, options?: {
/**
* The Name of the File (if not set, the basename of the file will be used)
*
* Only applied if the `content-disposition` header is not set and options.download is true
* @default path.basename(file)
* @since 9.1.4
*/ name?: string;
/**
* Whether to download the file or display it in the browser
* @default ctr.context.response.headers.get('content-type') === 'application/octet-stream'
* @since 9.1.4
*/ download?: boolean;
/**
* Whether some Content Type Headers will be added automatically
* @default true
* @since 2.2.0
*/ addTypes?: boolean;
/**
* Whether to compress this File
* @default true
* @since 7.9.0
*/ compress?: boolean;
}): this;
}