package http

⌘K
Ctrl+K
or
/

    Index

    Constants (0)

    This section is empty.

    Procedures (94)

    Types

    Body_Callback ¶

    Body_Callback :: proc(user_data: rawptr, body: string, err: bufio.Scanner_Error)
    Related Procedures With Parameters

    Body_Error ¶

    Body_Error :: bufio.Scanner_Error

    Connection ¶

    Connection :: struct {
    	server:         ^Server,
    	socket:         net.TCP_Socket,
    	state:          Connection_State,
    	scanner:        Scanner,
    	temp_allocator: mem_virtual.Arena,
    	loop:           Loop,
    }
     

    TODO/PERF: pool the connections, saves having to allocate scanner buf and temp_allocator every time.

    Connection_State ¶

    Connection_State :: enum int {
    	Pending,    // Pending a client to attach.
    	New,        // Got client, waiting to service first request.
    	Active,     // Servicing request.
    	Idle,       // Waiting for next request.
    	Will_Close, // Closing after the current response is sent.
    	Closing,    // Going to close, cleaning up.
    	Closed,     // Fully closed.
    }
    Cookie :: struct {
    	name:         string,
    	value:        string,
    	domain:       runtime.Maybe($T=string),
    	expires_gmt:  runtime.Maybe($T=Time),
    	max_age_secs: runtime.Maybe($T=int),
    	path:         runtime.Maybe($T=string),
    	http_only:    bool,
    	partitioned:  bool,
    	secure:       bool,
    	same_site:    Cookie_Same_Site,
    }
    Related Procedures With Parameters
    Related Procedures With Returns
    Cookie_Same_Site :: enum int {
    	Unspecified, 
    	None, 
    	Strict, 
    	Lax, 
    }

    Handle_Proc ¶

    Handle_Proc :: proc(req: ^Request, res: ^Response)
    Related Procedures With Parameters

    Handler ¶

    Handler :: struct {
    	user_data: rawptr,
    	next:      runtime.Maybe($T=^Handler),
    	handle:    Handler_Proc,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Handler_Proc ¶

    Handler_Proc :: proc(handler: ^Handler, req: ^Request, res: ^Response)
    Related Procedures With Parameters

    Method ¶

    Method :: enum int {
    	Get, 
    	Post, 
    	Delete, 
    	Patch, 
    	Put, 
    	Head, 
    	Connect, 
    	Options, 
    	Trace, 
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Mime_Type ¶

    Mime_Type :: enum int {
    	Plain, 
    	Css, 
    	Csv, 
    	Gif, 
    	Html, 
    	Ico, 
    	Jpeg, 
    	Js, 
    	Json, 
    	Png, 
    	Svg, 
    	Url_Encoded, 
    	Xml, 
    	Zip, 
    	Wasm, 
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Query_Entry ¶

    Query_Entry :: struct {
    	key:   string,
    	value: string,
    }
    Related Procedures With Returns

    Rate_Limit_Data ¶

    Rate_Limit_Data :: struct {
    	opts:       ^Rate_Limit_Opts,
    	next_sweep: time.Time,
    	hits:       map[net.Address]int,
    	mu:         sync.Mutex,
    }
    Related Procedures With Parameters

    Rate_Limit_On_Limit ¶

    Rate_Limit_On_Limit :: struct {
    	user_data: rawptr,
    	on_limit:  proc(req: ^Request, res: ^Response, user_data: rawptr),
    }
    Related Procedures With Returns

    Rate_Limit_Opts ¶

    Rate_Limit_Opts :: struct {
    	window:   time.Duration,
    	max:      int,
    	// Optional handler to call when a request is being rate-limited, allows you to customize the response.
    	on_limit: runtime.Maybe($T=Rate_Limit_On_Limit),
    }
    Related Procedures With Parameters

    Request ¶

    Request :: struct {
    	// If in a handler, this is always there and never None.
    	// TODO: we should not expose this as a maybe to package users.
    	line:       runtime.Maybe($T=Requestline),
    	// Is true if the request is actually a HEAD request,
    	// line.method will be .Get if Server_Opts.redirect_head_to_get is set.
    	is_head:    bool,
    	headers:    Headers,
    	url:        URL,
    	client:     net.Endpoint,
    	// Route params/captures.
    	url_params: []string,
    	// Internal usage only.
    	_scanner:   ^Scanner,
    	_body_ok:   runtime.Maybe($T=bool),
    }
    Related Procedures With Parameters

    Requestline ¶

    Requestline :: struct {
    	method:  Method,
    	target:  union {
    		string, 
    		URL, 
    	},
    	version: Version,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Requestline_Error ¶

    Requestline_Error :: enum int {
    	None, 
    	Method_Not_Implemented, 
    	Not_Enough_Fields, 
    	Invalid_Version_Format, 
    }
    Related Procedures With Returns

    Response ¶

    Response :: struct {
    	// Add your headers and cookies here directly.
    	headers:          Headers,
    	cookies:          [dynamic]Cookie,
    	// If the response has been sent.
    	sent:             bool,
    	// NOTE: use `http.response_status` if the response body might have been set already.
    	status:           Status,
    	// Only for internal usage.
    	_conn:            ^Connection,
    	// TODO/PERF: with some internal refactoring, we should be able to write directly to the
    	// connection (maybe a small buffer in this struct).
    	_buf:             bytes.Buffer,
    	_heading_written: bool,
    }
    Related Procedures With Parameters

    Response_Writer ¶

    Response_Writer :: struct {
    	r:     ^Response,
    	// The writer you can write to.
    	w:     io.Stream,
    	// A dynamic wrapper over the `buffer` given in `response_writer_init`, doesn't allocate.
    	buf:   [dynamic]u8,
    	// If destroy or close has been called.
    	ended: bool,
    }
    Related Procedures With Parameters

    Route ¶

    Route :: struct {
    	handler: Handler,
    	pattern: string,
    }

    Router ¶

    Router :: struct {
    	allocator: runtime.Allocator,
    	routes:    map[Method][dynamic]Route,
    	all:       [dynamic]Route,
    }
    Related Procedures With Parameters

    Server ¶

    Server :: struct {
    	opts:           Server_Opts,
    	tcp_sock:       net.TCP_Socket,
    	conn_allocator: runtime.Allocator,
    	handler:        Handler,
    	main_thread:    int,
    	threads:        []^thread.Thread,
    	// Once the server starts closing/shutdown this is set to true, all threads will check it
    	// and start their thread local shutdown procedure.
    	// 
    	// NOTE: This is only ever set from false to true, and checked repeatedly,
    	// so it doesn't have to be atomic, this is purely to keep the thread sanitizer happy.
    	closing:        Atomic($T=bool),
    	// Threads will decrement the wait group when they have fully closed/shutdown.
    	// The main thread waits on this to clean up global data and return.
    	threads_closed: sync.Wait_Group,
    	// Updated every second with an updated date, this speeds up the server considerably
    	// because it would otherwise need to call time.now() and format the date on each response.
    	date:           Server_Date,
    }
    Related Procedures With Parameters

    Server_Opts ¶

    Server_Opts :: struct {
    	// Whether the server should accept every request that sends a "Expect: 100-continue" header automatically.
    	// Defaults to true.
    	auto_expect_continue: bool,
    	// When this is true, any HEAD request is automatically redirected to the handler as a GET request.
    	// Then, when the response is sent, the body is removed from the response.
    	// Defaults to true.
    	redirect_head_to_get: bool,
    	// Limit the maximum number of bytes to read for the request line (first line of request containing the URI).
    	// The HTTP spec does not specify any limits but in practice it is safer.
    	// RFC 7230 3.1.1 says:
    	// Various ad hoc limitations on request-line length are found in
    	// practice.  It is RECOMMENDED that all HTTP senders and recipients
    	// support, at a minimum, request-line lengths of 8000 octets.
    	// defaults to 8000.
    	limit_request_line:   int,
    	// Limit the length of the headers.
    	// The HTTP spec does not specify any limits but in practice it is safer.
    	// defaults to 8000.
    	limit_headers:        int,
    	// The thread count to use, defaults to your core count - 1.
    	thread_count:         int,
    }
    Related Procedures With Parameters

    Server_State ¶

    Server_State :: enum int {
    	Uninitialized, 
    	Idle, 
    	Listening, 
    	Serving, 
    	Running, 
    	Closing, 
    	Cleaning, 
    	Closed, 
    }

    Server_Thread ¶

    Server_Thread :: struct {
    	conns: map[net.TCP_Socket]^Connection,
    	state: Server_State,
    	io:    nbio._IO,
    }

    Status ¶

    Status :: enum int {
    	Continue                        = 100, 
    	Switching_Protocols             = 101, 
    	Processing                      = 102, 
    	Early_Hints                     = 103, 
    	OK                              = 200, 
    	Created                         = 201, 
    	Accepted                        = 202, 
    	Non_Authoritative_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, // Deprecated.
    	Unused                          = 306, // Deprecated.
    	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_Content           = 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, 
    	Not_Extended                    = 510, 
    	Network_Authentication_Required = 511, 
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    URL ¶

    URL :: struct {
    	raw:    string,
    	// All other fields are views/slices into this string.
    	scheme: string,
    	host:   string,
    	path:   string,
    	query:  string,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Version ¶

    Version :: struct {
    	major: u8,
    	minor: u8,
    }
    Related Procedures With Parameters
    Related Procedures With Returns

    Constants

    This section is empty.

    Variables

    Default_Endpoint ¶

    Default_Endpoint: net.Endpoint = …

    Default_Server_Opts ¶

    Default_Server_Opts: Server_Opts = …

    td ¶

    @(thread_local)
    td: Server_Thread

    Procedures

    body ¶

    body :: proc(req: ^Request, max_length: int = -1, user_data: rawptr, cb: Body_Callback) {…}
     

    Retrieves the request's body.

    If the request has the chunked Transfer-Encoding header set, the chunks are all read and returned. Otherwise, the Content-Length header is used to determine what to read and return it.

    max_length can be used to set a maximum amount of bytes we try to read, once it goes over this, an error is returned.

    Do not call this more than once.

    Tip If an error is returned, easily respond with an appropriate error code like this, http.respond(res, http.body_error_status(err)).

    body_error_status ¶

    body_error_status :: proc(e: bufio.Scanner_Error) -> Status {…}
     

    Returns an appropriate status code for the given body error.

    body_set_bytes ¶

    body_set_bytes :: proc(r: ^Response, byts: []u8, loc := #caller_location) {…}
     

    Prefer the procedure group body_set.

    body_set_str ¶

    body_set_str :: proc(r: ^Response, str: string, loc := #caller_location) {…}
     

    Prefer the procedure group body_set.

    body_url_encoded ¶

    body_url_encoded :: proc(plain: string, allocator := context.temp_allocator) -> (res: map[string]string, ok: bool) {…}
     

    Parses a URL encoded body, aka bodies with the 'Content-Type: application/x-www-form-urlencoded'.

    Key&value pairs are percent decoded and put in a map.

    cookie_date_parse :: proc(value: string) -> (t: time.Time, ok: bool) {…}
     

    Implementation of the algorithm described in RFC 6265 section 5.1.1.

    cookie_parse :: proc(value: string, allocator := context.allocator) -> (cookie: Cookie, ok: bool) {…}
     

    TODO: check specific whitespace requirements in RFC.

    Allocations are done to check case-insensitive attributes but they are deleted right after. So, all the returned strings (inside cookie) are slices into the given value string.

    cookie_string :: proc(c: Cookie, allocator := context.allocator) -> string {…}
     

    Builds the Set-Cookie header string representation of the given cookie.

    cookie_write :: proc(w: io.Stream, c: Cookie) -> io.Error {…}
     

    Builds the Set-Cookie header string representation of the given cookie.

    date_parse ¶

    date_parse :: proc(value: string) -> (t: time.Time, ok: bool) {…}

    date_string ¶

    date_string :: proc(t: time.Time, allocator := context.allocator) -> string {…}
     

    Formats a time in the HTTP header format (no timezone conversion is done, GMT expected): <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT

    date_write ¶

    date_write :: proc(w: io.Stream, t: time.Time) -> io.Error {…}
     

    Formats a time in the HTTP header format (no timezone conversion is done, GMT expected): <day-name>, <day> <month> <year> <hour>:<minute>:<second> GMT

    handler ¶

    handler :: proc(handle: Handle_Proc) -> Handler {…}

    header_allowed_trailer ¶

    header_allowed_trailer :: proc(key: string) -> bool {…}
     

    Returns if this is a valid trailer header.

    RFC 7230 4.1.2: A sender MUST NOT generate a trailer that contains a field necessary for message framing (e.g., Transfer-Encoding and Content-Length), routing (e.g., Host), request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]), authentication (e.g., see [RFC7235] and [RFC6265]), response control data (e.g., see Section 7.1 of [RFC7231]), or determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer).

    header_parse ¶

    header_parse :: proc(headers: ^Headers, line: string, allocator := context.temp_allocator) -> (key: string, ok: bool) {…}
     

    Parses the header and adds it to the headers if valid. The given string is copied.

    headers_count ¶

    headers_count :: proc(h: Headers) -> int {…}

    headers_delete ¶

    headers_delete :: proc(h: ^Headers, k: string) -> (deleted_key: string, deleted_value: string) {…}

    headers_delete_unsafe ¶

    headers_delete_unsafe :: proc(h: ^Headers, k: string) {…}
     

    Unsafely delete a header, given key is assumed to be a lowercase string.

    headers_get ¶

    headers_get :: proc(h: Headers, k: string) -> (string, bool) #optional_ok {…}

    headers_get_unsafe ¶

    headers_get_unsafe :: proc(h: Headers, k: string) -> (string, bool) #optional_ok {…}
     

    Unsafely get header, given key is assumed to be a lowercase string.

    headers_has ¶

    headers_has :: proc(h: Headers, k: string) -> bool {…}

    headers_has_unsafe ¶

    headers_has_unsafe :: proc(h: Headers, k: string) -> bool {…}
     

    Unsafely check for a header, given key is assumed to be a lowercase string.

    headers_init ¶

    headers_init :: proc(h: ^Headers, allocator := context.temp_allocator) {…}

    headers_set ¶

    headers_set :: proc(h: ^Headers, k: string, v: string, loc := #caller_location) -> string {…}
     

    Sets a header, given key is first sanitized, final (sanitized) key is returned.

    headers_set_close ¶

    headers_set_close :: proc(h: ^Headers) {…}

    headers_set_content_type_mime ¶

    headers_set_content_type_mime :: proc(h: ^Headers, ct: Mime_Type) {…}

    headers_set_content_type_string ¶

    headers_set_content_type_string :: proc(h: ^Headers, ct: string) {…}

    headers_set_unsafe ¶

    headers_set_unsafe :: proc(h: ^Headers, k: string, v: string, loc := #caller_location) {…}
     

    Unsafely set header, given key is assumed to be a lowercase string and to be without newlines.

    headers_validate ¶

    headers_validate :: proc(headers: ^Headers) -> bool {…}
     

    Validates the headers, use headers_validate_for_server if these are request headers that should be validated from the server side.

    headers_validate_for_server ¶

    headers_validate_for_server :: proc(headers: ^Headers) -> bool {…}
     

    Validates the headers of a request, from the pov of the server.

    listen ¶

    listen :: proc(s: ^Server, endpoint: net.Endpoint = Default_Endpoint, opts: Server_Opts = Default_Server_Opts) -> (err: net.Network_Error) {…}

    listen_and_serve ¶

    listen_and_serve :: proc(s: ^Server, h: Handler, endpoint: net.Endpoint = Default_Endpoint, opts: Server_Opts = Default_Server_Opts) -> (err: net.Network_Error) {…}

    method_parse ¶

    method_parse :: proc(m: string) -> (method: Method, ok: bool) {…}

    method_string ¶

    method_string :: proc(m: Method) -> string {…}

    middleware_proc ¶

    middleware_proc :: proc(next: runtime.Maybe($T=^Handler), handle: Handler_Proc) -> Handler {…}

    mime_from_extension ¶

    mime_from_extension :: proc(s: string) -> Mime_Type {…}

    mime_to_content_type ¶

    mime_to_content_type :: proc(m: Mime_Type) -> string {…}

    query_get ¶

    query_get :: proc(url: URL, key: string) -> (val: string, ok: bool) #optional_ok {…}

    query_get_bool ¶

    query_get_bool :: proc(url: URL, key: string) -> (result, set: bool) #optional_ok {…}

    query_get_int ¶

    query_get_int :: proc(url: URL, key: string, base: int = 0) -> (result: int, ok: bool, set: bool) {…}

    query_get_percent_decoded ¶

    query_get_percent_decoded :: proc(url: URL, key: string, allocator := context.temp_allocator) -> (val: string, ok: bool) {…}

    query_get_uint ¶

    query_get_uint :: proc(url: URL, key: string, base: int = 0) -> (result: uint, ok: bool, set: bool) {…}

    query_iter ¶

    query_iter :: proc(query: ^string) -> (entry: Query_Entry, ok: bool) {…}

    rate_limit ¶

    rate_limit :: proc(data: ^Rate_Limit_Data, next: ^Handler, opts: ^Rate_Limit_Opts, allocator := context.allocator) -> Handler {…}
     

    Basic rate limit based on IP address.

    rate_limit_destroy ¶

    rate_limit_destroy :: proc(data: ^Rate_Limit_Data) {…}

    rate_limit_message ¶

    rate_limit_message :: proc(message: ^string) -> Rate_Limit_On_Limit {…}
     

    Convenience method to create a Rate_Limit_On_Limit that writes the given message.

    request_cookie_get :: proc(r: ^Request, key: string) -> (value: string, ok: bool) {…}
     

    Retrieves the cookie with the given key out of the requests Cookie header.

    If the same key is in the header multiple times the last one is returned.

    request_cookies ¶

    request_cookies :: proc(r: ^Request, allocator := context.temp_allocator) -> (res: map[string]string) {…}
     

    Allocates a map with the given allocator and puts all cookie pairs from the requests Cookie header into it.

    If the same key is in the header multiple times the last one is returned.

    request_cookies_iter ¶

    request_cookies_iter :: proc(cookies: ^string) -> (key: string, value: string, ok: bool) {…}
     

    Iterates the cookies from right to left.

    request_init ¶

    request_init :: proc(r: ^Request, allocator := context.temp_allocator) {…}

    request_path ¶

    request_path :: proc(target: URL, allocator := context.allocator) -> (rq_path: string) {…}

    request_path_write ¶

    request_path_write :: proc(w: io.Stream, target: URL) -> io.Error {…}

    requestline_parse ¶

    requestline_parse :: proc(s: string, allocator := context.temp_allocator) -> (line: Requestline, err: Requestline_Error) {…}
     

    A request-line begins with a method token, followed by a single space (SP), the request-target, another single space (SP), the protocol version, and ends with CRLF.

    This allocates a clone of the target, because this is intended to be used with a scanner, which has a buffer that changes every read.

    requestline_write ¶

    requestline_write :: proc(w: io.Stream, rline: Requestline) -> io.Error {…}

    respond_dir ¶

    respond_dir :: proc(r: ^Response, base, target, request: string, loc := #caller_location) {…}
     

    Sets the response to one that, based on the request path, returns a file. base: The base of the request path that should be removed when retrieving the file. target: The path to the directory to serve. request: The request path.

    Path traversal is detected and cleaned up. The Content-Type is set based on the file extension, see the MimeType enum for known file extensions.

    respond_file ¶

    respond_file :: proc(r: ^Response, path: string, content_type: runtime.Maybe($T=Mime_Type) = nil, loc := #caller_location) {…}
     

    Sends the content of the file at the given path as the response.

    This procedure uses non blocking IO and only allocates the size of the file in the body's buffer, no other allocations or temporary buffers, this is to make it as fast as possible.

    The content type is taken from the path, optionally overwritten using the parameter.

    If the file doesn't exist, a 404 response is sent. If any other error occurs, a 500 is sent and the error is logged.

    respond_file_content ¶

    respond_file_content :: proc(r: ^Response, path: string, content: []u8, status: Status = .OK, loc := #caller_location) {…}
     

    Responds with the given content, determining content type from the given path.

    This is very useful when you want to #load(path) at compile time and respond with that.

    respond_html ¶

    respond_html :: proc(r: ^Response, html: string, status: Status = .OK, loc := #caller_location) {…}
     

    Sets the response to one that sends the given HTML.

    respond_json ¶

    respond_json :: proc(r: ^Response, v: any, status: Status = .OK, opt: encoding_json.Marshal_Options = {}, loc := #caller_location) -> (err: encoding_json.Marshal_Error) {…}
     

    Sets the response to one that returns the JSON representation of the given value.

    respond_plain ¶

    respond_plain :: proc(r: ^Response, text: string, status: Status = .OK, loc := #caller_location) {…}
     

    Sets the response to one that sends the given plain text.

    respond_with_none ¶

    respond_with_none :: proc(r: ^Response, loc := #caller_location) {…}
     

    Prefer the procedure group respond.

    respond_with_status ¶

    respond_with_status :: proc(r: ^Response, status: Status, loc := #caller_location) {…}
     

    Prefer the procedure group respond.

    response_init ¶

    response_init :: proc(r: ^Response, allocator := context.allocator) {…}

    response_status ¶

    response_status :: proc(r: ^Response, status: Status) {…}
     

    Sets the status code with the safety of being able to do this after writing (part of) the body.

    response_writer_init ¶

    response_writer_init :: proc(rw: ^Response_Writer, r: ^Response, buffer: []u8) -> io.Stream {…}
     

    Initialize a writer you can use to write responses. Use the body_set procedure group if you have a string or byte slice.

    The buffer can be used to avoid very small writes, like the ones when you use the json package (each write in the json package is only a few bytes). You are allowed to pass nil which will disable buffering.

    NOTE: You need to call io.destroy to signal the end of the body, OR io.close to send the response.

    route_all ¶

    route_all :: proc(router: ^Router, pattern: string, handler: Handler) {…}
     

    Adds a catch-all fallback route (all methods, ran if no other routes match).

    route_connect ¶

    route_connect :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    route_delete ¶

    route_delete :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    route_get ¶

    route_get :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    route_head ¶

    route_head :: proc(router: ^Router, pattern: string, handler: Handler) {…}
     

    NOTE: this does not get called when Server_Opts.redirect_head_to_get is set to true.

    route_options ¶

    route_options :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    route_patch ¶

    route_patch :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    route_post ¶

    route_post :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    route_put ¶

    route_put :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    route_trace ¶

    route_trace :: proc(router: ^Router, pattern: string, handler: Handler) {…}

    router_destroy ¶

    router_destroy :: proc(router: ^Router) {…}

    router_handler ¶

    router_handler :: proc(router: ^Router) -> Handler {…}
     

    Returns a handler that matches against the given routes.

    router_init ¶

    router_init :: proc(router: ^Router, allocator := context.allocator) {…}

    serve ¶

    serve :: proc(s: ^Server, h: Handler) -> (err: net.Network_Error) {…}

    server_shutdown ¶

    server_shutdown :: proc(s: ^Server) {…}
     

    Starts a graceful shutdown.

    Some error logs will be generated but all active connections are finished before closing them and all connections and threads are freed.

    1. Stops 'server_start' from accepting new connections. 2. Close and free non-active connections. 3. Repeat 2 every SHUTDOWN_INTERVAL until no more connections are open. 4. Close the main socket. 5. Signal 'server_start' it can return.

    server_shutdown_on_interrupt ¶

    server_shutdown_on_interrupt :: proc(s: ^Server) {…}
     

    Registers a signal handler to shutdown the server gracefully on interrupt signal. Can only be called once in the lifetime of the program because of a hacky interaction with libc.

    status_from_string ¶

    status_from_string :: proc(s: string) -> (Status, bool) {…}

    status_is_client_error ¶

    status_is_client_error :: proc(s: Status) -> bool {…}

    status_is_informational ¶

    status_is_informational :: proc(s: Status) -> bool {…}

    status_is_redirect ¶

    status_is_redirect :: proc(s: Status) -> bool {…}

    status_is_server_error ¶

    status_is_server_error :: proc(s: Status) -> bool {…}

    status_is_success ¶

    status_is_success :: proc(s: Status) -> bool {…}

    status_string ¶

    status_string :: proc(s: Status) -> string {…}

    status_valid ¶

    status_valid :: proc(s: Status) -> bool {…}

    test_dynamic_unwritten ¶

    test_dynamic_unwritten :: proc(t: ^testing.T) {…}

    url_parse ¶

    url_parse :: proc(raw: string) -> (url: URL) {…}

    version_parse ¶

    version_parse :: proc(s: string) -> (version: Version, ok: bool) {…}
     

    Parses an HTTP version string according to RFC 7230, section 2.6.

    version_string ¶

    version_string :: proc(v: Version, allocator := context.allocator) -> string {…}

    version_write ¶

    version_write :: proc(w: io.Stream, v: Version) -> io.Error {…}

    Procedure Groups

    body_set ¶

    body_set :: proc{
    	body_set_str,
    	body_set_bytes,
    }
    
     

    Sets the response body. After calling this you can no longer add headers to the response. If, after calling, you want to change the status code, use the response_status procedure.

    For bodies where you do not know the size or want an io.Writer, use the response_writer_init procedure to create a writer.

    respond ¶

    respond :: proc{
    	respond_with_none,
    	respond_with_status,
    }
    
     

    Sends the response back to the client, handlers should call this.

    Source Files

    Generation Information

    Generated with odin version dev-2024-10 (vendor "odin") Linux_amd64 @ 2024-10-30 12:34:52.771422134 +0000 UTC