commit:     a545f27fdb504b22ee3799d58f8645ca3fb30eb8
Author:     Nicolas PARLANT <nicolas.parlant <AT> parhuet <DOT> fr>
AuthorDate: Fri Dec  6 00:56:47 2024 +0000
Commit:     Nicolas PARLANT <ppn <AT> parhuet <DOT> fr>
CommitDate: Fri Dec  6 20:45:49 2024 +0000
URL:        https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=a545f27f

dev-lua/lua-http: add doc/man, version 20240908 to 0.4_p20240908

Signed-off-by: Nicolas PARLANT <nicolas.parlant <AT> parhuet.fr>

 dev-lua/lua-http/Manifest                          |    2 +-
 dev-lua/lua-http/files/lua-http.3                  | 2119 ++++++++++++++++++++
 ...240908.ebuild => lua-http-0.4_p20240908.ebuild} |   15 +-
 3 files changed, 2133 insertions(+), 3 deletions(-)

diff --git a/dev-lua/lua-http/Manifest b/dev-lua/lua-http/Manifest
index c32ca2fbe..d83ea6b84 100644
--- a/dev-lua/lua-http/Manifest
+++ b/dev-lua/lua-http/Manifest
@@ -1 +1 @@
-DIST lua-http-20240908.tar.gz 142897 BLAKE2B 
2c68b11ffa8e579ba2be9db08c65f8f28b1eb96079a8d1b71c245ff516a7249cee86317aca3e0635b2e612120aedfa6f4e3bbe9392919835502845567cb2100f
 SHA512 
579db298e901c555bfabd09d375d83ec1be0b45e37c9c55a779620c720a18392fdee3dc971a2ded7b0804f1fcdfc9f69863510a5823b1a0b2637b8195a42cae1
+DIST lua-http-0.4_p20240908.tar.gz 142897 BLAKE2B 
2c68b11ffa8e579ba2be9db08c65f8f28b1eb96079a8d1b71c245ff516a7249cee86317aca3e0635b2e612120aedfa6f4e3bbe9392919835502845567cb2100f
 SHA512 
579db298e901c555bfabd09d375d83ec1be0b45e37c9c55a779620c720a18392fdee3dc971a2ded7b0804f1fcdfc9f69863510a5823b1a0b2637b8195a42cae1

diff --git a/dev-lua/lua-http/files/lua-http.3 
b/dev-lua/lua-http/files/lua-http.3
new file mode 100644
index 000000000..c3cceca86
--- /dev/null
+++ b/dev-lua/lua-http/files/lua-http.3
@@ -0,0 +1,2119 @@
+.\" Automatically generated by Pandoc 3.5
+.\"
+.TH "lua\-http" "" "" ""
+.SH Introduction
+lua\-http is an performant, capable HTTP and WebSocket library for Lua
+5.1, 5.2, 5.3, 5.4 and LuaJIT.
+Some of the features of the library include:
+.IP \[bu] 2
+Support for HTTP versions 1, 1.1 and 2 as specified by \c
+.UR https://tools.ietf.org/html/rfc7230
+RFC 7230
+.UE \c
+\ and \c
+.UR https://tools.ietf.org/html/rfc7540
+RFC 7540
+.UE \c
+.IP \[bu] 2
+Provides both client and server APIs
+.IP \[bu] 2
+Fully asynchronous API that does not block the current thread when
+executing operations that typically block
+.IP \[bu] 2
+Support for WebSockets as specified by \c
+.UR https://tools.ietf.org/html/rfc6455
+RFC 6455
+.UE \c
+\ including ping/pong, binary data transfer and TLS encryption
+.IP \[bu] 2
+Transport Layer Security (TLS) \- lua\-http supports HTTPS and WSS via
+\c
+.UR https://github.com/wahern/luaossl
+luaossl
+.UE \c
+\&.
+.IP \[bu] 2
+Easy integration into other event\-loop or scripts
+.SS Why lua\-http?
+The lua\-http library was written to fill a gap in the Lua ecosystem by
+providing an HTTP and WebSocket library with the following traits:
+.IP \[bu] 2
+Asynchronous and performant
+.IP \[bu] 2
+Can be used without forcing the developer to follow a specific pattern.
+Conversely, the library can be adapted to many common patterns.
+.IP \[bu] 2
+Can be used at a very high level without need to understand the
+transportation of HTTP data (other than connection addresses).
+.IP \[bu] 2
+Provides a rich low level API, if desired, for creating powerful HTTP
+based tools at the protocol level.
+.PP
+As a result of these design goals, the library is simple and unobtrusive
+and can accommodate tens of thousands of connections on commodity
+hardware.
+.PP
+lua\-http is a flexible HTTP and WebSocket library that allows
+developers to concentrate on line\-of\-business features when building
+Internet enabled applications.
+If you are looking for a way to streamline development of an internet
+enabled application, enable HTTP networking in your game, create a new
+Internet Of Things (IoT) system, or write a performant custom web server
+for a specific use case, lua\-http has the tools you need.
+.SS Portability
+lua\-http is pure Lua code with dependencies on the following external
+libraries:
+.IP \[bu] 2
+\c
+.UR http://25thandclement.com/~william/projects/cqueues.html
+cqueues
+.UE \c
+\ \- Posix API library for Lua
+.IP \[bu] 2
+\c
+.UR http://25thandclement.com/~william/projects/luaossl.html
+luaossl
+.UE \c
+\ \- Lua bindings for TLS/SSL
+.IP \[bu] 2
+\c
+.UR https://github.com/brimworks/lua-zlib
+lua\-zlib
+.UE \c
+\ \- Optional Lua bindings for zlib
+.PP
+lua\-http can run on any operating system supported by cqueues and
+openssl, which at the time of writing is GNU/Linux, FreeBSD, NetBSD,
+OpenBSD, OSX and Solaris.
+.SS Common Use Cases
+The following are two simple demonstrations of how the lua\-http library
+can be used:
+.SS Retrieving a Document
+The highest level interface for clients is \f[I]http.request\f[R].
+By constructing a \f[I]request\f[R] object from a URI using
+\f[CR]new_from_uri\f[R] and immediately evaluating it, you can easily
+fetch an HTTP resource.
+.IP
+.EX
+\f[B]local\f[R] http_request = require \[dq]http.request\[dq]
+\f[B]local\f[R] headers, stream = 
assert(http_request.new_from_uri(\[dq]http://example.com\[dq]):go())
+\f[B]local\f[R] body = assert(stream:get_body_as_string())
+\f[B]if\f[R] headers:get \[dq]:status\[dq] \[ti]= \[dq]200\[dq] \f[B]then\f[R]
+    error(body)
+\f[B]end\f[R]
+print(body)
+.EE
+.SS WebSocket Communications
+To request information from a WebSocket server, use the
+\f[CR]websocket\f[R] module to create a new WebSocket client.
+.IP
+.EX
+\f[B]local\f[R] websocket = require \[dq]http.websocket\[dq]
+\f[B]local\f[R] ws = websocket.new_from_uri(\[dq]wss://echo.websocket.org\[dq])
+assert(ws:connect())
+assert(ws:send(\[dq]koo\-eee!\[dq]))
+\f[B]local\f[R] data = assert(ws:receive())
+assert(data == \[dq]koo\-eee!\[dq])
+assert(ws:close())
+.EE
+.SS Asynchronous Operation
+lua\-http has been written to perform asynchronously so that it can be
+used in your application, server or game without blocking your main
+loop.
+Asynchronous operations are achieved by utilizing cqueues, a Lua/C
+library that incorporates Lua yielding and kernel level APIs to reduce
+CPU usage.
+All lua\-http operations including DNS lookup, TLS negotiation and
+read/write operations will not block the main application thread when
+run from inside a cqueue or cqueue enabled \[lq]container\[rq].
+While sometimes it is necessary to block a routine (yield) and wait for
+external data, any blocking API calls take an optional timeout to ensure
+good behaviour of networked applications and avoid unresponsive or
+\[lq]dead\[rq] routines.
+.PP
+Asynchronous operations are one of the most powerful features of
+lua\-http and require no effort on the developers part.
+For instance, an HTTP server can be instantiated within any Lua main
+loop and run alongside application code without adversely affecting the
+main application process.
+If other cqueue enabled components are integrated within a cqueue loop,
+the application is entirely event driven through kernel level polling
+APIs.
+.PP
+cqueues can be used in conjunction with lua\-http to integrate other
+features into your lua application and create powerful, performant, web
+enabled applications.
+Some of the examples in this guide will use cqueues for simple
+demonstrations.
+For more resources about cqueues, please see:
+.IP \[bu] 2
+\c
+.UR http://25thandclement.com/~william/projects/cqueues.html
+The cqueues website
+.UE \c
+\ for more information about the cqueues library.
+.IP \[bu] 2
+cqueues examples can be found with the cqueues source code available
+through \c
+.UR http://www.25thandclement.com/~william/projects/cqueues.html#download
+git or archives
+.UE \c
+\ or accessed online \c
+.UR https://github.com/wahern/cqueues/tree/master/examples
+here
+.UE \c
+\&.
+.IP \[bu] 2
+For more information on integrating cqueues with other event loop
+libraries please see \c
+.UR https://github.com/wahern/cqueues/wiki/Integrations-with-other-main-loops
+integration with other event loops
+.UE \c
+\&.
+.IP \[bu] 2
+For other libraries that use cqueues such as asynchronous APIs for Redis
+and PostgreSQL, please see \c
+.UR https://github.com/wahern/cqueues/wiki/Libraries-that-use-cqueues
+the cqueues wiki entry here
+.UE \c
+\&.
+.SS Conventions
+The following is a list of API conventions and general reference:
+.SS HTTP
+.IP \[bu] 2
+HTTP 1 request and status line fields are passed around inside of
+\f[I]headers\f[R] objects under keys \f[CR]\[dq]:authority\[dq]\f[R],
+\f[CR]\[dq]:method\[dq]\f[R], \f[CR]\[dq]:path\[dq]\f[R],
+\f[CR]\[dq]:scheme\[dq]\f[R] and \f[CR]\[dq]:status\[dq]\f[R] as defined
+in HTTP 2.
+As such, they are all kept in string form (important to remember for the
+\f[CR]:status\f[R] field).
+.IP \[bu] 2
+Header fields should always be used with lower case keys.
+.SS Errors
+.IP \[bu] 2
+Invalid function parameters will throw a lua error (if validated).
+.IP \[bu] 2
+Errors are returned as \f[CR]nil\f[R], error, errno unless noted
+otherwise.
+.IP \[bu] 2
+Some HTTP 2 operations return/throw special http 2 error objects.
+.SS Timeouts
+All operations that may block the current thread take a
+\f[CR]timeout\f[R] argument.
+This argument is always the number of seconds to allow before returning
+\f[CR]nil, err_msg, ETIMEDOUT\f[R] where \f[CR]err_msg\f[R] is a
+localised error message such as
+\f[CR]\[dq]connection timed out\[dq]\f[R].
+.SS Terminology
+Much lua\-http terminology is borrowed from HTTP 2.
+.PP
+\f[I]Connection\f[R] \- An abstraction over an underlying TCP/IP socket.
+lua\-http currently has two connection types: one for HTTP 1, one for
+HTTP 2.
+.PP
+\f[I]Stream\f[R] \- A request/response on a connection object.
+lua\-http has two stream types: one for \f[I]HTTP 1 streams\f[R], and
+one for \f[I]HTTP 2 streams\f[R].
+The common interfaces is described in \f[I]stream\f[R].
+.SH Interfaces
+lua\-http has separate modules for HTTP 1 vs HTTP 2 protocols, yet the
+different versions share many common concepts.
+lua\-http provides a common interface for operations that make sense for
+both protocol versions (as well as any future developments).
+.PP
+The following sections outline the interfaces exposed by the lua\-http
+library.
+.SS connection
+A connection encapsulates a socket and provides protocol specific
+operations.
+A connection may have \f[I]streams\f[R] which encapsulate the
+requests/responses happening over a conenction.
+Alternatively, you can ignore streams entirely and use low level
+protocol specific operations to read and write to the socket.
+.PP
+All \f[I]connection\f[R] types expose the following fields:
+.SS \f[CR]connection.type\f[R] 
+The mode of use for the connection object.
+Valid values are:
+.IP \[bu] 2
+\f[CR]\[dq]client\[dq]\f[R]: Acts as a client; this connection type is
+used by entities who want to make requests
+.IP \[bu] 2
+\f[CR]\[dq]server\[dq]\f[R]: Acts as a server; this conenction type is
+used by entities who want to respond to requests
+.SS \f[CR]connection.version\f[R] 
+The HTTP version number of the connection as a number.
+.SS \f[CR]connection:pollfd()\f[R] 
+.SS \f[CR]connection:events()\f[R] 
+.SS \f[CR]connection:timeout()\f[R] 
+.SS \f[CR]connection:connect(timeout)\f[R] 
+Completes the connection to the remote server using the address
+specified, HTTP version and any options specified in the
+\f[CR]connection.new\f[R] constructor.
+The \f[CR]connect\f[R] function will yield until the connection attempt
+finishes (success or failure) or until \f[CR]timeout\f[R] is exceeded.
+Connecting may include DNS lookups, TLS negotiation and HTTP2 settings
+exchange.
+Returns \f[CR]true\f[R] on success.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]connection:checktls()\f[R] 
+Checks the socket for a valid Transport Layer Security connection.
+Returns the luaossl ssl object if the connection is secured.
+Returns \f[CR]nil\f[R] and an error message if there is no active TLS
+session.
+Please see the \c
+.UR http://25thandclement.com/~william/projects/luaossl.html
+luaossl website
+.UE \c
+\ for more information about the ssl object.
+.SS \f[CR]connection:localname()\f[R] 
+Returns the connection information for the local socket.
+Returns address family, IP address and port for an external socket.
+For Unix domain sockets, the function returns \f[CR]AF_UNIX\f[R] and the
+path.
+If the connection object is not connected, returns \f[CR]AF_UNSPEC\f[R]
+(0).
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]connection:peername()\f[R] 
+Returns the connection information for the socket \f[I]peer\f[R] (as in,
+the next hop).
+Returns address family, IP address and port for an external socket.
+For unix sockets, the function returns \f[CR]AF_UNIX\f[R] and the path.
+If the connection object is not connected, returns \f[CR]AF_UNSPEC\f[R]
+(0).
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.PP
+\f[I]Note: If the client is using a proxy, the values returned
+\f[CI]:peername()\f[I] point to the proxy, not the remote server.\f[R]
+.SS \f[CR]connection:flush(timeout)\f[R] 
+Flushes buffered outgoing data on the socket to the operating system.
+Returns \f[CR]true\f[R] on success.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]connection:shutdown()\f[R] 
+Performs an orderly shutdown of the connection by closing all streams
+and calls \f[CR]:shutdown()\f[R] on the socket.
+The connection cannot be re\-opened.
+.SS \f[CR]connection:close()\f[R] 
+Closes a connection and releases operating systems resources.
+Note that \f[CR]:close()\f[R] performs a
+\f[CR]connection:shutdown()\f[R] prior to releasing resources.
+.SS \f[CR]connection:new_stream()\f[R] 
+Creates and returns a new \f[I]stream\f[R] on the connection.
+.SS \f[CR]connection:get_next_incoming_stream(timeout)\f[R] 
+Returns the next peer initiated \f[I]stream\f[R] on the connection.
+This function can be used to yield and \[lq]listen\[rq] for incoming
+HTTP streams.
+.SS \f[CR]connection:onidle(new_handler)\f[R] 
+Provide a callback to get called when the connection becomes idle
+i.e.\ when there is no request in progress and no pipelined streams
+waiting.
+When called it will receive the \f[CR]connection\f[R] as the first
+argument.
+Returns the previous handler.
+.SS stream
+An HTTP \f[I]stream\f[R] is an abstraction of a request/response within
+a HTTP connection.
+Within a stream there may be a number of \[lq]header\[rq] blocks as well
+as data known as the \[lq]body\[rq].
+.PP
+All stream types expose the following fields and functions:
+.SS \f[CR]stream.connection\f[R] 
+The underlying \f[I]connection\f[R] object.
+.SS \f[CR]stream:checktls()\f[R] 
+Convenience wrapper equivalent to
+\f[CR]stream.connection:checktls()\f[R]
+.SS \f[CR]stream:localname()\f[R] 
+Convenience wrapper equivalent to
+\f[CR]stream.connection:localname()\f[R]
+.SS \f[CR]stream:peername()\f[R] 
+Convenience wrapper equivalent to
+\f[CR]stream.connection:peername()\f[R]
+.SS \f[CR]stream:get_headers(timeout)\f[R] 
+Retrieves the next complete headers object (i.e.\ a block of headers or
+trailers) from the stream.
+.SS \f[CR]stream:write_headers(headers, end_stream, timeout)\f[R] 
+Write the given \f[I]headers\f[R] object to the stream.
+The function takes a flag indicating if this is the last chunk in the
+stream, if \f[CR]true\f[R] the stream will be closed.
+If \f[CR]timeout\f[R] is specified, the stream will wait for the send to
+complete until \f[CR]timeout\f[R] is exceeded.
+.SS \f[CR]stream:write_continue(timeout)\f[R] 
+Sends a 100\-continue header block.
+.SS \f[CR]stream:get_next_chunk(timeout)\f[R] 
+Returns the next chunk of the http body from the socket, potentially
+yielding for up to \f[CR]timeout\f[R] seconds.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:each_chunk()\f[R] 
+Iterator over \f[CR]stream:get_next_chunk()\f[R]
+.SS \f[CR]stream:get_body_as_string(timeout)\f[R] 
+Reads the entire body from the stream and return it as a string.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:get_body_chars(n, timeout)\f[R] 
+Reads \f[CR]n\f[R] characters (bytes) of body from the stream and return
+them as a string.
+If the stream ends before \f[CR]n\f[R] characters are read then returns
+the partial result.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:get_body_until(pattern, plain, include_pattern, timeout)\f[R] 
+Reads in body data from the stream until the \c
+.UR http://www.lua.org/manual/5.4/manual.html#6.4.1
+lua pattern
+.UE \c
+\ \f[CR]pattern\f[R] is found and returns the data as a string.
+\f[CR]plain\f[R] is a boolean that indicates that pattern matching
+facilities should be turned off so that function does a plain \[lq]find
+substring\[rq] operation, with no characters in pattern being considered
+magic.
+\f[CR]include_patterns\f[R] specifies if the pattern itself should be
+included in the returned string.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:save_body_to_file(file, timeout)\f[R] 
+Reads the body from the stream and saves it to the \c
+.UR http://www.lua.org/manual/5.4/manual.html#6.8
+lua file handle
+.UE \c
+\ \f[CR]file\f[R].
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:get_body_as_file(timeout)\f[R] 
+Reads the body from the stream into a temporary file and returns a \c
+.UR http://www.lua.org/manual/5.4/manual.html#6.8
+lua file handle
+.UE \c
+\&.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:unget(str)\f[R] 
+Places \f[CR]str\f[R] back on the incoming data buffer, allowing it to
+be returned again on a subsequent command (\[lq]un\-gets\[rq] the data).
+Returns \f[CR]true\f[R] on success.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:write_chunk(chunk, end_stream, timeout)\f[R] 
+Writes the string \f[CR]chunk\f[R] to the stream.
+If \f[CR]end_stream\f[R] is true, the body will be finalized and the
+stream will be closed.
+\f[CR]write_chunk\f[R] yields indefinitely, or until \f[CR]timeout\f[R]
+is exceeded.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:write_body_from_string(str, timeout)\f[R] 
+Writes the string \f[CR]str\f[R] to the stream and ends the stream.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:write_body_from_file(options|file, timeout)\f[R] 
+.IP \[bu] 2
+\f[CR]options\f[R] is a table containing:
+.RS 2
+.IP \[bu] 2
+\f[CR].file\f[R] (file)
+.IP \[bu] 2
+\f[CR].count\f[R] (positive integer): number of bytes of \f[CR]file\f[R]
+to write
+.PD 0
+.P
+.PD
+defaults to infinity (the whole file will be written)
+.RE
+.PP
+Writes the contents of file \f[CR]file\f[R] to the stream and ends the
+stream.
+\f[CR]file\f[R] will not be automatically seeked, so ensure it is at the
+correct offset before calling.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]stream:shutdown()\f[R] 
+Closes the stream.
+The resources are released and the stream can no longer be used.
+.SH Modules
+.SS http.bit
+An abstraction layer over the various lua bit libraries.
+.PP
+Results are only consistent between underlying implementations when
+parameters and results are in the range of \f[CR]0\f[R] to
+\f[CR]0x7fffffff\f[R].
+.SS \f[CR]band(a, b)\f[R] 
+Bitwise And operation.
+.SS \f[CR]bor(a, b)\f[R] 
+Bitwise Or operation.
+.SS \f[CR]bxor(a, b)\f[R] 
+Bitwise XOr operation.
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] bit = require \[dq]http.bit\[dq]
+print(bit.band(1, 3)) \f[I]\-\-> 1\f[R]
+.EE
+.SS http.client
+Deals with obtaining a connection to an HTTP server.
+.SS \f[CR]negotiate(socket, options, timeout)\f[R] 
+Negotiates the HTTP settings with the remote server.
+If TLS has been specified, this function instantiates the encryption
+tunnel.
+Parameters are as follows:
+.IP \[bu] 2
+\f[CR]socket\f[R] is a cqueues socket object
+.IP \[bu] 2
+\f[CR]options\f[R] is a table containing:
+.RS 2
+.IP \[bu] 2
+\f[CR].tls\f[R] (boolean, optional): Should TLS be used?
+.PD 0
+.P
+.PD
+defaults to \f[CR]false\f[R]
+.IP \[bu] 2
+\f[CR].ctx\f[R] (userdata, optional): the \f[CR]SSL_CTX*\f[R] to use if
+\f[CR].tls\f[R] is \f[CR]true\f[R].
+.PD 0
+.P
+.PD
+If \f[CR].ctx\f[R] is \f[CR]nil\f[R] then a default context will be
+used.
+.IP \[bu] 2
+\f[CR].sendname\f[R] (string|boolean, optional): the \c
+.UR https://en.wikipedia.org/wiki/Server_Name_Indication
+TLS SNI
+.UE \c
+\ host to send.
+.PD 0
+.P
+.PD
+defaults to \f[CR]true\f[R]
+.RS 2
+.IP \[bu] 2
+\f[CR]true\f[R] indicates to copy the \f[CR].host\f[R] field as long as
+it is \f[B]not\f[R] an IP
+.IP \[bu] 2
+\f[CR]false\f[R] disables SNI
+.RE
+.IP \[bu] 2
+\f[CR].version\f[R] (\f[CR]nil\f[R]|1.0|1.1|2): HTTP version to use.
+.RS 2
+.IP \[bu] 2
+\f[CR]nil\f[R]: attempts HTTP 2 and falls back to HTTP 1.1
+.IP \[bu] 2
+\f[CR]1.0\f[R]
+.IP \[bu] 2
+\f[CR]1.1\f[R]
+.IP \[bu] 2
+\f[CR]2\f[R]
+.RE
+.IP \[bu] 2
+\f[CR].h2_settings\f[R] (table, optional): HTTP 2 settings to use.
+See \f[I]http.h2_connection\f[R] for details
+.RE
+.SS \f[CR]connect(options, timeout)\f[R] 
+This function returns a new connection to an HTTP server.
+Once a connection has been opened, a stream can be created to start a
+request/response exchange.
+Please see \f[CR]h1_stream.new_stream\f[R] and
+\f[CR]h2_stream.new_stream\f[R] for more information about creating
+streams.
+.IP \[bu] 2
+\f[CR]options\f[R] is a table containing the options to
+\f[CR]http.client.negotiate\f[R], plus the following:
+.RS 2
+.IP \[bu] 2
+\f[CR]family\f[R] (integer, optional): socket family to use.
+.PD 0
+.P
+.PD
+defaults to \f[CR]AF_INET\f[R]
+.IP \[bu] 2
+\f[CR]host\f[R] (string): host to connect to.
+.PD 0
+.P
+.PD
+may be either a hostname or an IP address
+.IP \[bu] 2
+\f[CR]port\f[R] (string|integer): port to connect to in numeric form
+.PD 0
+.P
+.PD
+e.g.\ \f[CR]\[dq]80\[dq]\f[R] or \f[CR]80\f[R]
+.IP \[bu] 2
+\f[CR]path\f[R] (string): path to connect to (UNIX sockets)
+.IP \[bu] 2
+\f[CR]v6only\f[R] (boolean, optional): if the \f[CR]IPV6_V6ONLY\f[R]
+flag should be set on the underlying socket.
+.IP \[bu] 2
+\f[CR]bind\f[R] (string, optional): the local outgoing address and
+optionally port to bind in the form of
+\f[CR]\[dq]address[:port]\[dq]\f[R], IPv6 addresses may be specified via
+square bracket notation.
+e.g.\ \f[CR]\[dq]127.0.0.1\[dq]\f[R],
+\f[CR]\[dq]127.0.0.1:50000\[dq]\f[R], \f[CR]\[dq][::1]:30000\[dq]\f[R].
+.RE
+.IP \[bu] 2
+\f[CR]timeout\f[R] (optional) is the maximum amount of time (in seconds)
+to allow for connection to be established.
+.PD 0
+.P
+.PD
+This includes time for DNS lookup, connection, TLS negotiation (if TLS
+enabled) and in the case of HTTP 2: settings exchange.
+.SS Example
+Connect to a local HTTP server running on port 8000
+.IP
+.EX
+\f[B]local\f[R] http_client = require \[dq]http.client\[dq]
+\f[B]local\f[R] myconnection = http_client.connect {
+    host = \[dq]localhost\[dq];
+    port = 8000;
+    tls = \f[B]false\f[R];
+}
+.EE
+.SS http.cookie
+A module for working with cookies.
+.SS \f[CR]bake(name, value, expiry_time, domain, path, secure_only, http_only, 
same_site)\f[R] 
+Returns a string suitable for use in a \f[CR]Set\-Cookie\f[R] header
+with the passed parameters.
+.SS \f[CR]parse_cookie(cookie)\f[R] 
+Parses the \f[CR]Cookie\f[R] header contents \f[CR]cookie\f[R].
+.PP
+Returns a table containing \f[CR]name\f[R] and \f[CR]value\f[R] pairs as
+strings.
+.SS \f[CR]parse_cookies(req_headers)\f[R] 
+Parses all \f[CR]Cookie\f[R] headers in the \f[I]http.headers\f[R]
+object \f[CR]req_headers\f[R].
+.PP
+Returns a table containing \f[CR]name\f[R] and \f[CR]value\f[R] pairs as
+strings.
+.SS \f[CR]parse_setcookie(setcookie)\f[R] 
+Parses the \f[CR]Set\-Cookie\f[R] header contents \f[CR]setcookie\f[R].
+.PP
+Returns \f[CR]name\f[R], \f[CR]value\f[R] and \f[CR]params\f[R] where:
+.IP \[bu] 2
+\f[CR]name\f[R] is a string containing the cookie name
+.IP \[bu] 2
+\f[CR]value\f[R] is a string containing the cookie value
+.IP \[bu] 2
+\f[CR]params\f[R] is the a table where the keys are cookie attribute
+names and values are cookie attribute values
+.SS \f[CR]new_store()\f[R] 
+Creates a new cookie store.
+.PP
+Cookies are unique for a tuple of domain, path and name; although
+multiple cookies with the same name may exist in a request due to
+overlapping paths or domains.
+.SS \f[CR]store.psl\f[R] 
+A \c
+.UR https://github.com/daurnimator/lua-psl
+lua\-psl
+.UE \c
+\ object to use for checking against the Public Suffix List.
+Set the field to \f[CR]false\f[R] to skip checking the suffix list.
+.PP
+Defaults to the \c
+.UR 
https://rockdaboot.github.io/libpsl/libpsl-Public-Suffix-List-functions.html#psl-latest
+latest
+.UE \c
+\ PSL on the system.
+If lua\-psl is not installed then it will be \f[CR]nil\f[R].
+.SS \f[CR]store.time()\f[R] 
+A function used by the \f[CR]store\f[R] to get the current time for
+expiries and such.
+.PP
+Defaults to a function based on \c
+.UR https://www.lua.org/manual/5.4/manual.html#pdf-os.time
+\f[CR]os.time\f[R]
+.UE \c
+\&.
+.SS \f[CR]store.max_cookie_length\f[R] 
+The maximum length (in bytes) of cookies in the store; this value is
+also used as default maximum cookie length for \f[CR]:lookup()\f[R].
+Decreasing this value will only prevent new cookies from being added, it
+will not remove old cookies.
+.PP
+Defaults to infinity (no maximum size).
+.SS \f[CR]store.max_cookies\f[R] 
+The maximum number of cookies allowed in the \f[CR]store\f[R].
+Decreasing this value will only prevent new cookies from being added, it
+will not remove old cookies.
+.PP
+Defaults to infinity (any number of cookies is allowed).
+.SS \f[CR]store.max_cookies_per_domain\f[R] 
+The maximum number of cookies allowed in the \f[CR]store\f[R] per
+domain.
+Decreasing this value will only prevent new cookies from being added, it
+will not remove old cookies.
+.PP
+Defaults to infinity (any number of cookies is allowed).
+.SS \f[CR]store:store(req_domain, req_path, req_is_http, req_is_secure, 
req_site_for_cookies, name, value, params)\f[R] 
+Attempts to add a cookie to the \f[CR]store\f[R].
+.IP \[bu] 2
+\f[CR]req_domain\f[R] is the domain that the cookie was obtained from
+.IP \[bu] 2
+\f[CR]req_path\f[R] is the path that the cookie was obtained from
+.IP \[bu] 2
+\f[CR]req_is_http\f[R] is a boolean flag indicating if the cookie was
+obtained from a \[lq]non\-HTTP\[rq] API
+.IP \[bu] 2
+\f[CR]req_is_secure\f[R] is a boolean flag indicating if the cookie was
+obtained from a \[lq]secure\[rq] protocol
+.IP \[bu] 2
+\f[CR]req_site_for_cookies\f[R] is a string containing the host that
+should be considered as the \[lq]site for cookies\[rq] (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+), can be \f[CR]nil\f[R] if unknown.
+.IP \[bu] 2
+\f[CR]name\f[R] is a string containing the cookie name
+.IP \[bu] 2
+\f[CR]value\f[R] is a string containing the cookie value
+.IP \[bu] 2
+\f[CR]params\f[R] is the a table where the keys are cookie attribute
+names and values are cookie attribute values
+.PP
+Returns a boolean indicating if a cookie was stored.
+.SS \f[CR]store:store_from_request(req_headers, resp_headers, req_host, 
req_site_for_cookies)\f[R] 
+Attempt to store any cookies found in the response headers.
+.IP \[bu] 2
+\f[CR]req_headers\f[R] is the \f[I]http.headers\f[R] object for the
+outgoing request
+.IP \[bu] 2
+\f[CR]resp_headers\f[R] is the \f[I]http.headers\f[R] object received in
+response
+.IP \[bu] 2
+\f[CR]req_host\f[R] is the host that your query was directed at (only
+used if \f[CR]req_headers\f[R] is missing a \f[CR]Host\f[R] header)
+.IP \[bu] 2
+\f[CR]req_site_for_cookies\f[R] is a string containing the host that
+should be considered as the \[lq]site for cookies\[rq] (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+), can be \f[CR]nil\f[R] if unknown.
+.SS \f[CR]store:get(domain, path, name)\f[R] 
+Returns the cookie value for the cookie stored for the passed
+\f[CR]domain\f[R], \f[CR]path\f[R] and \f[CR]name\f[R].
+.SS \f[CR]store:remove(domain, path, name)\f[R] 
+Deletes the cookie stored for the passed \f[CR]domain\f[R],
+\f[CR]path\f[R] and \f[CR]name\f[R].
+.PP
+If \f[CR]name\f[R] is \f[CR]nil\f[R] or not passed then all cookies for
+the \f[CR]domain\f[R] and \f[CR]path\f[R] are removed.
+.PP
+If \f[CR]path\f[R] is \f[CR]nil\f[R] or not passed (in addition to
+\f[CR]name\f[R]) then all cookies for the \f[CR]domain\f[R] are removed.
+.SS \f[CR]store:lookup(domain, path, is_http, is_secure, is_safe_method, 
site_for_cookies, is_top_level, max_cookie_length)\f[R] 
+Finds cookies visible to suitable for passing to an entity.
+.IP \[bu] 2
+\f[CR]domain\f[R] is the domain that will be sent the cookie
+.IP \[bu] 2
+\f[CR]path\f[R] is the path that will be sent the cookie
+.IP \[bu] 2
+\f[CR]is_http\f[R] is a boolean flag indicating if the destination is a
+\[lq]non\-HTTP\[rq] API
+.IP \[bu] 2
+\f[CR]is_secure\f[R] is a boolean flag indicating if the destination
+will be communicated with over a \[lq]secure\[rq] protocol
+.IP \[bu] 2
+\f[CR]is_safe_method\f[R] is a boolean flag indicating if the cookie
+will be sent via a safe HTTP method (See also http.util.is_safe_method)
+.IP \[bu] 2
+\f[CR]site_for_cookies\f[R] is a string containing the host that should
+be considered as the \[lq]site for cookies\[rq] (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+), can be \f[CR]nil\f[R] if unknown.
+.IP \[bu] 2
+\f[CR]is_top_level\f[R] is a boolean flag indicating if this request is
+a \[lq]top level\[rq] request (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+)
+.IP \[bu] 2
+\f[CR]max_cookie_length\f[R] is the maximum cookie length to allow (See
+also \f[CR]store.max_cookie_length\f[R])
+.PP
+Returns a string suitable for use in a \f[CR]Cookie\f[R] header.
+.SS \f[CR]store:lookup_for_request(headers, host, site_for_cookies, 
is_top_level, max_cookie_length)\f[R] 
+Finds cookies suitable for adding to a request.
+.IP \[bu] 2
+\f[CR]headers\f[R] is the \f[I]http.headers\f[R] object for the outgoing
+request
+.IP \[bu] 2
+\f[CR]host\f[R] is the host that your query was directed at (only used
+if \f[CR]headers\f[R] is missing a \f[CR]Host\f[R] header)
+.IP \[bu] 2
+\f[CR]site_for_cookies\f[R] is a string containing the host that should
+be considered as the \[lq]site for cookies\[rq] (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+), can be \f[CR]nil\f[R] if unknown.
+.IP \[bu] 2
+\f[CR]is_top_level\f[R] is a boolean flag indicating if this request is
+a \[lq]top level\[rq] request (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+)
+.IP \[bu] 2
+\f[CR]max_cookie_length\f[R] is the maximum cookie length to allow (See
+also \f[CR]store.max_cookie_length\f[R])
+.PP
+Returns a string suitable for use in a \f[CR]Cookie\f[R] header.
+.SS \f[CR]store:clean_due()\f[R] 
+Returns the number of seconds until the next cookie in the
+\f[CR]store\f[R] expires.
+.SS \f[CR]store:clean()\f[R] 
+Remove all expired cookies from the \f[CR]store\f[R].
+.SS \f[CR]store:load_from_file(file)\f[R] 
+Loads cookie data from the file object \f[CR]file\f[R] into
+\f[CR]store\f[R].
+The file should be in the Netscape Cookiejar format.
+Invalid lines in the file are ignored.
+.PP
+Returns \f[CR]true\f[R] on success or passes along
+\f[CR]nil, err, errno\f[R] if a \f[CR]:read\f[R] call fails.
+.SS \f[CR]store:save_to_file(file)\f[R] 
+Writes the cookie data from \f[CR]store\f[R] into the file object
+\f[CR]file\f[R] in the Netscape Cookiejar format.
+\f[CR]file\f[R] is not \f[CR]seek\f[R]\-ed or truncated before writing.
+.PP
+Returns \f[CR]true\f[R] on success or passes along
+\f[CR]nil, err, errno\f[R] if a \f[CR]:write\f[R] call fails.
+.SS http.h1_connection
+The \f[I]h1_connection\f[R] module adheres to the \f[I]connection\f[R]
+interface and provides HTTP 1 and 1.1 specific operations.
+.SS \f[CR]new(socket, conn_type, version)\f[R] 
+Constructor for a new connection.
+Takes a cqueues socket object, a connection type string and a numeric
+HTTP version number.
+Valid values for the connection type are \f[CR]\[dq]client\[dq]\f[R] and
+\f[CR]\[dq]server\[dq]\f[R].
+Valid values for the version number are \f[CR]1\f[R] and \f[CR]1.1\f[R].
+Returns the newly initialized connection object.
+.SS \f[CR]h1_connection.version\f[R] 
+Specifies the HTTP version used for the connection handshake.
+Valid values are:
+.IP \[bu] 2
+\f[CR]1.0\f[R]
+.IP \[bu] 2
+\f[CR]1.1\f[R]
+.PP
+See \f[CR]connection.version\f[R]
+.SS \f[CR]h1_connection:pollfd()\f[R] 
+See \f[CR]connection:pollfd()\f[R]
+.SS \f[CR]h1_connection:events()\f[R] 
+See \f[CR]connection:events()\f[R]
+.SS \f[CR]h1_connection:timeout()\f[R] 
+See \f[CR]connection:timeout()\f[R]
+.SS \f[CR]h1_connection:connect(timeout)\f[R] 
+See \f[CR]connection:connect(timeout)\f[R]
+.SS \f[CR]h1_connection:checktls()\f[R] 
+See \f[CR]connection:checktls()\f[R]
+.SS \f[CR]h1_connection:localname()\f[R] 
+See \f[CR]connection:localname()\f[R]
+.SS \f[CR]h1_connection:peername()\f[R] 
+See \f[CR]connection:peername()\f[R]
+.SS \f[CR]h1_connection:flush(timeout)\f[R] 
+See \f[CR]connection:flush(timeout)\f[R]
+.SS \f[CR]h1_connection:shutdown(dir)\f[R] 
+Shut down is as graceful as possible: pipelined streams are shutdown,
+then the underlying socket is shut down in the appropriate direction(s).
+.PP
+\f[CR]dir\f[R] is a string representing the direction of communication
+to shut down communication in.
+If it contains \f[CR]\[dq]r\[dq]\f[R] it will shut down reading, if it
+contains \f[CR]\[dq]w\[dq]\f[R] it will shut down writing.
+The default is \f[CR]\[dq]rw\[dq]\f[R], i.e.\ to shutdown communication
+in both directions.
+.PP
+See \f[CR]connection:shutdown()\f[R]
+.SS \f[CR]h1_connection:close()\f[R] 
+See \f[CR]connection:close()\f[R]
+.SS \f[CR]h1_connection:new_stream()\f[R] 
+In HTTP 1, only a client may initiate new streams with this function.
+.PP
+See \f[CR]connection:new_stream()\f[R] for more information.
+.SS \f[CR]h1_connection:get_next_incoming_stream(timeout)\f[R] 
+See \f[CR]connection:get_next_incoming_stream(timeout)\f[R]
+.SS \f[CR]h1_connection:onidle(new_handler)\f[R] 
+See \f[CR]connection:onidle(new_handler)\f[R]
+.SS \f[CR]h1_connection:setmaxline(read_length)\f[R] 
+Sets the maximum read buffer size (in bytes) to \f[CR]read_length\f[R].
+i.e.\ sets the maximum length lines (such as headers).
+.PP
+The default comes from the underlying socket, which gets the (changable)
+cqueues default at time of construction.
+The default cqueues default is 4096 bytes.
+.SS \f[CR]h1_connection:clearerr(...)\f[R] 
+Clears errors to allow for further read or write operations on the
+connection.
+Returns the error number of existing errors.
+This function is used to recover from known errors.
+.SS \f[CR]h1_connection:error(...)\f[R] 
+Returns the error number of existing errors.
+.SS \f[CR]h1_connection:take_socket()\f[R] 
+Used to hand the reference of the connection socket to another object.
+Resets the socket to defaults and returns the single existing reference
+of the socket to the calling routine.
+This function can be used for connection upgrades such as upgrading from
+HTTP 1 to a WebSocket.
+.SS \f[CR]h1_connection:read_request_line(timeout)\f[R] 
+Reads a request line from the socket.
+Returns the request method, request target and HTTP version for an
+incoming request.
+\f[CR]:read_request_line()\f[R] yields until a
+\f[CR]\[dq]\[rs]r\[rs]n\[dq]\f[R] terminated chunk is received, or
+\f[CR]timeout\f[R] is exceeded.
+If the incoming chunk is not a valid HTTP request line, \f[CR]nil\f[R]
+is returned.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]h1_connection:read_status_line(timeout)\f[R] 
+Reads a line of input from the socket.
+If the input is a valid status line, the HTTP version (1 or 1.1), status
+code and reason description (if applicable) is returned.
+\f[CR]:read_status_line()\f[R] yields until a
+\f[CR]\[dq]\[rs]r\[rs]n\[dq]\f[R] terminated chunk is received, or
+\f[CR]timeout\f[R] is exceeded.
+If the socket could not be read, returns \f[CR]nil\f[R], an error
+message and an error number.
+.SS \f[CR]h1_connection:read_header(timeout)\f[R] 
+Reads a CRLF terminated HTTP header from the socket and returns the
+header key and value.
+This function will yield until a MIME compliant header item is received
+or until \f[CR]timeout\f[R] is exceeded.
+If the header could not be read, the function returns \f[CR]nil\f[R] an
+error and an error message.
+.SS \f[CR]h1_connection:read_headers_done(timeout)\f[R] 
+Checks for an empty line, which indicates the end of the HTTP headers.
+Returns \f[CR]true\f[R] if an empty line is received.
+Any other value is pushed back on the socket receive buffer (unget) and
+the function returns \f[CR]false\f[R].
+This function will yield waiting for input from the socket or until
+\f[CR]timeout\f[R] is exceeded.
+Returns \f[CR]nil\f[R], an error and an error message if the socket
+cannot be read.
+.SS \f[CR]h1_connection:read_body_by_length(len, timeout)\f[R] 
+Get \f[CR]len\f[R] number of bytes from the socket.
+Use a negative number for \f[I]up to\f[R] that number of bytes.
+This function will yield and wait on the socket if length of the
+buffered body is less than \f[CR]len\f[R].
+Asserts if len is not a number.
+.SS \f[CR]h1_connection:read_body_till_close(timeout)\f[R] 
+Reads the entire request body.
+This function will yield until the body is complete or
+\f[CR]timeout\f[R] is expired.
+If the read fails the function returns \f[CR]nil\f[R], an error message
+and an error number.
+.SS \f[CR]h1_connection:read_body_chunk(timeout)\f[R] 
+Reads the next available line of data from the request and returns the
+chunk and any chunk extensions.
+This function will yield until chunk size is received or
+\f[CR]timeout\f[R] is exceeded.
+If the chunk size is indicated as \f[CR]0\f[R] then \f[CR]false\f[R] and
+any chunk extensions are returned.
+Returns \f[CR]nil\f[R], an error message and an error number if there
+was an error reading reading the chunk header or the socket.
+.SS \f[CR]h1_connection:write_request_line(method, target, httpversion, 
timeout)\f[R] 
+Writes the opening HTTP 1.x request line for a new request to the socket
+buffer.
+Yields until success or \f[CR]timeout\f[R].
+If the write fails, returns \f[CR]nil\f[R], an error message and an
+error number.
+.PP
+\f[I]Note the request line will not be flushed to the remote server
+until\f[R] \f[CR]write_headers_done\f[R] \f[I]is called.\f[R]
+.SS \f[CR]h1_connection:write_status_line(httpversion, status_code, 
reason_phrase, timeout)\f[R] 
+Writes an HTTP status line to the socket buffer.
+Yields until success or \f[CR]timeout\f[R].
+If the write fails, the function returns \f[CR]nil\f[R], an error
+message and an error number.
+.PP
+\f[I]Note the status line will not be flushed to the remote server
+until\f[R] \f[CR]write_headers_done\f[R] \f[I]is called.\f[R]
+.SS \f[CR]h1_connection:write_header(k, v, timeout)\f[R] 
+Writes a header item to the socket buffer as a \f[CR]key:value\f[R]
+string.
+Yields until success or \f[CR]timeout\f[R].
+Returns \f[CR]nil\f[R], an error message and an error if the write
+fails.
+.PP
+\f[I]Note the header item will not be flushed to the remote server
+until\f[R] \f[CR]write_headers_done\f[R] \f[I]is called.\f[R]
+.SS \f[CR]h1_connection:write_headers_done(timeout)\f[R] 
+Terminates a header block by writing a blank line
+(\f[CR]\[dq]\[rs]r\[rs]n\[dq]\f[R]) to the socket.
+This function will flush all outstanding data in the socket output
+buffer.
+Yields until success or \f[CR]timeout\f[R].
+Returns \f[CR]nil\f[R], an error message and an error if the write
+fails.
+.SS \f[CR]h1_connection:write_body_chunk(chunk, chunk_ext, timeout)\f[R] 
+Writes a chunk of data to the socket.
+\f[CR]chunk_ext\f[R] must be \f[CR]nil\f[R] as chunk extensions are not
+supported.
+Will yield until complete or \f[CR]timeout\f[R] is exceeded.
+Returns true on success.
+Returns \f[CR]nil\f[R], an error message and an error number if the
+write fails.
+.SS \f[CR]h1_connection:write_body_last_chunk(chunk_ext, timeout)\f[R] 
+Writes the chunked body terminator \f[CR]\[dq]0\[rs]r\[rs]n\[dq]\f[R] to
+the socket.
+\f[CR]chunk_ext\f[R] must be \f[CR]nil\f[R] as chunk extensions are not
+supported.
+Will yield until complete or \f[CR]timeout\f[R] is exceeded.
+Returns \f[CR]nil\f[R], an error message and an error number if the
+write fails.
+.PP
+\f[I]Note that the connection will not be immediately flushed to the
+remote server; normally this will occur when trailers are written.\f[R]
+.SS \f[CR]h1_connection:write_body_plain(body, timeout)\f[R] 
+Writes the contents of \f[CR]body\f[R] to the socket and flushes the
+socket output buffer immediately.
+Yields until success or \f[CR]timeout\f[R] is exceeded.
+Returns \f[CR]nil\f[R], an error message and an error number if the
+write fails.
+.SS http.h1_reason_phrases
+A table mapping from status codes (as strings) to reason phrases for
+HTTP 1.
+Any unknown status codes return \f[CR]\[dq]Unassigned\[dq]\f[R]
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] reason_phrases = require \[dq]http.h1_reason_phrases\[dq]
+print(reason_phrases[\[dq]200\[dq]]) \f[I]\-\-> \[dq]OK\[dq]\f[R]
+print(reason_phrases[\[dq]342\[dq]]) \f[I]\-\-> \[dq]Unassigned\[dq]\f[R]
+.EE
+.SS http.h1_stream
+The \f[I]h1_stream\f[R] module adheres to the \f[I]stream\f[R] interface
+and provides HTTP 1.x specific operations.
+.PP
+The gzip transfer encoding is supported transparently.
+.SS \f[CR]h1_stream.connection\f[R] 
+See \f[CR]stream.connection\f[R]
+.SS \f[CR]h1_stream.max_header_lines\f[R] 
+The maximum number of header lines to read.
+Default is \f[CR]100\f[R].
+.SS \f[CR]h1_stream:checktls()\f[R] 
+See \f[CR]stream:checktls()\f[R]
+.SS \f[CR]h1_stream:localname()\f[R] 
+See \f[CR]stream:localname()\f[R]
+.SS \f[CR]h1_stream:peername()\f[R] 
+See \f[CR]stream:peername()\f[R]
+.SS \f[CR]h1_stream:get_headers(timeout)\f[R] 
+See \f[CR]stream:get_headers(timeout)\f[R]
+.SS \f[CR]h1_stream:write_headers(headers, end_stream, timeout)\f[R] 
+See \f[CR]stream:write_headers(headers, end_stream, timeout)\f[R]
+.SS \f[CR]h1_stream:write_continue(timeout)\f[R] 
+See \f[CR]stream:write_continue(timeout)\f[R]
+.SS \f[CR]h1_stream:get_next_chunk(timeout)\f[R] 
+See \f[CR]stream:get_next_chunk(timeout)\f[R]
+.SS \f[CR]h1_stream:each_chunk()\f[R] 
+See \f[CR]stream:each_chunk()\f[R]
+.SS \f[CR]h1_stream:get_body_as_string(timeout)\f[R] 
+See \f[CR]stream:get_body_as_string(timeout)\f[R]
+.SS \f[CR]h1_stream:get_body_chars(n, timeout)\f[R] 
+See \f[CR]stream:get_body_chars(n, timeout)\f[R]
+.SS \f[CR]h1_stream:get_body_until(pattern, plain, include_pattern, 
timeout)\f[R] 
+See
+\f[CR]stream:get_body_until(pattern, plain, include_pattern, timeout)\f[R]
+.SS \f[CR]h1_stream:save_body_to_file(file, timeout)\f[R] 
+See \f[CR]stream:save_body_to_file(file, timeout)\f[R]
+.SS \f[CR]h1_stream:get_body_as_file(timeout)\f[R] 
+See \f[CR]stream:get_body_as_file(timeout)\f[R]
+.SS \f[CR]h1_stream:unget(str)\f[R] 
+See \f[CR]stream:unget(str)\f[R]
+.SS \f[CR]h1_stream:write_chunk(chunk, end_stream, timeout)\f[R] 
+See \f[CR]stream:write_chunk(chunk, end_stream, timeout)\f[R]
+.SS \f[CR]h1_stream:write_body_from_string(str, timeout)\f[R] 
+See \f[CR]stream:write_body_from_string(str, timeout)\f[R]
+.SS \f[CR]h1_stream:write_body_from_file(options|file, timeout)\f[R] 
+See \f[CR]stream:write_body_from_file(options|file, timeout)\f[R]
+.SS \f[CR]h1_stream:shutdown()\f[R] 
+See \f[CR]stream:shutdown()\f[R]
+.SS \f[CR]h1_stream:set_state(new)\f[R] 
+Sets the state of the stream to \f[CR]new\f[R].
+\f[CR]new\f[R] must be one of the following valid states:
+.IP \[bu] 2
+\f[CR]\[dq]open\[dq]\f[R]: have sent or received headers; haven\[cq]t
+sent body yet
+.IP \[bu] 2
+\f[CR]\[dq]half closed (local)\[dq]\f[R]: have sent whole body
+.IP \[bu] 2
+\f[CR]\[dq]half closed (remote)\[dq]\f[R]: have received whole body
+.IP \[bu] 2
+\f[CR]\[dq]closed\[dq]\f[R]: complete
+.PP
+Not all state transitions are allowed.
+.SS \f[CR]h1_stream:read_headers(timeout)\f[R] 
+Reads and returns a header block from the underlying connection.
+Does \f[I]not\f[R] take into account buffered header blocks.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.PP
+This function should rarely be used, you\[cq]re probably looking for
+\f[CR]:get_headers()\f[R].
+.SS \f[CR]h1_stream:read_next_chunk(timeout)\f[R] 
+Reads and returns the next chunk as a string from the underlying
+connection.
+Does \f[I]not\f[R] take into account buffered chunks.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.PP
+This function should rarely be used, you\[cq]re probably looking for
+\f[CR]:get_next_chunk()\f[R].
+.SS http.h2_connection
+The \f[I]h2_connection\f[R] module adheres to the \f[I]connection\f[R]
+interface and provides HTTP 2 specific operations.
+An HTTP 2 connection can have multiple streams actively transmitting
+data at once, hence an \f[I]http.h2_connection\f[R] acts much like a
+scheduler.
+.SS \f[CR]new(socket, conn_type, settings)\f[R] 
+Constructor for a new connection.
+Takes a cqueues socket object, a connection type string and an optional
+table of HTTP 2 settings.
+Returns the newly initialized connection object in a non\-connected
+state.
+.SS \f[CR]h2_connection.version\f[R] 
+Contains the HTTP connection version.
+Currently this will always be \f[CR]2\f[R].
+.PP
+See \f[CR]connection.version\f[R]
+.SS \f[CR]h2_connection:pollfd()\f[R] 
+See \f[CR]connection:pollfd()\f[R]
+.SS \f[CR]h2_connection:events()\f[R] 
+See \f[CR]connection:events()\f[R]
+.SS \f[CR]h2_connection:timeout()\f[R] 
+See \f[CR]connection:timeout()\f[R]
+.SS \f[CR]h2_connection:empty()\f[R] 
+.SS \f[CR]h2_connection:step(timeout)\f[R] 
+.SS \f[CR]h2_connection:loop(timeout)\f[R] 
+.SS \f[CR]h2_connection:connect(timeout)\f[R] 
+See \f[CR]connection:connect(timeout)\f[R]
+.SS \f[CR]h2_connection:checktls()\f[R] 
+See \f[CR]connection:checktls()\f[R]
+.SS \f[CR]h2_connection:localname()\f[R] 
+See \f[CR]connection:localname()\f[R]
+.SS \f[CR]h2_connection:peername()\f[R] 
+See \f[CR]connection:peername()\f[R]
+.SS \f[CR]h2_connection:flush(timeout)\f[R] 
+See \f[CR]connection:flush(timeout)\f[R]
+.SS \f[CR]h2_connection:shutdown()\f[R] 
+See \f[CR]connection:shutdown()\f[R]
+.SS \f[CR]h2_connection:close()\f[R] 
+See \f[CR]connection:close()\f[R]
+.SS \f[CR]h2_connection:new_stream(id)\f[R] 
+Create and return a new \f[I]h2_stream\f[R].
+\f[CR]id\f[R] (optional) is the stream id to assign the new stream, if
+not specified for client initiated streams this will be the next free
+odd numbered stream, for server initiated streams this will be the next
+free even numbered stream.
+.PP
+See \f[CR]connection:new_stream()\f[R] for more information.
+.SS \f[CR]h2_connection:get_next_incoming_stream(timeout)\f[R] 
+See \f[CR]connection:get_next_incoming_stream(timeout)\f[R]
+.SS \f[CR]h2_connection:onidle(new_handler)\f[R] 
+See \f[CR]connection:onidle(new_handler)\f[R]
+.SS \f[CR]h2_connection:read_http2_frame(timeout)\f[R] 
+.SS \f[CR]h2_connection:write_http2_frame(typ, flags, streamid, payload, 
timeout, flush)\f[R] 
+.SS \f[CR]h2_connection:ping(timeout)\f[R] 
+.SS \f[CR]h2_connection:write_window_update(inc, timeout)\f[R] 
+.SS \f[CR]h2_connection:write_goaway_frame(last_stream_id, err_code, 
debug_msg, timeout)\f[R] 
+.SS \f[CR]h2_connection:set_peer_settings(peer_settings)\f[R] 
+.SS \f[CR]h2_connection:ack_settings()\f[R] 
+.SS \f[CR]h2_connection:settings(tbl, timeout)\f[R] 
+.SS http.h2_error
+A type of error object that encapsulates HTTP 2 error information.
+An \f[CR]http.h2_error\f[R] object has fields:
+.IP \[bu] 2
+\f[CR]name\f[R]: The error name: a short identifier for this error
+.IP \[bu] 2
+\f[CR]code\f[R]: The error code
+.IP \[bu] 2
+\f[CR]description\f[R]: The description of the error code
+.IP \[bu] 2
+\f[CR]message\f[R]: An error message
+.IP \[bu] 2
+\f[CR]traceback\f[R]: A traceback taken at the point the error was
+thrown
+.IP \[bu] 2
+\f[CR]stream_error\f[R]: A boolean that indicates if this is a stream
+level or protocol level error
+.SS \f[CR]errors\f[R] 
+A table containing errors \c
+.UR https://http2.github.io/http2-spec/#iana-errors
+as defined by the HTTP 2 specification
+.UE \c
+\&.
+It can be indexed by error name (e.g.\ \f[CR]errors.PROTOCOL_ERROR\f[R])
+or numeric code (e.g.\ \f[CR]errors[0x1]\f[R]).
+.SS \f[CR]is(ob)\f[R] 
+Returns a boolean indicating if the object \f[CR]ob\f[R] is an
+\f[CR]http.h2_error\f[R] object
+.SS \f[CR]h2_error:new(ob)\f[R] 
+Creates a new error object from the passed table.
+The table should have the form of an error object i.e.\ with fields
+\f[CR]name\f[R], \f[CR]code\f[R], \f[CR]message\f[R],
+\f[CR]traceback\f[R], etc.
+.PP
+Fields \f[CR]name\f[R], \f[CR]code\f[R] and \f[CR]description\f[R] are
+inherited from the parent \f[CR]h2_error\f[R] object if not specified.
+.PP
+\f[CR]stream_error\f[R] defaults to \f[CR]false\f[R].
+.SS \f[CR]h2_error:new_traceback(message, stream_error, lvl)\f[R] 
+Creates a new error object, recording a traceback from the current
+thread.
+.SS \f[CR]h2_error:error(message, stream_error, lvl)\f[R] 
+Creates and throws a new error.
+.SS \f[CR]h2_error:assert(cond, ...)\f[R] 
+If \f[CR]cond\f[R] is truthy, returns \f[CR]cond, ...\f[R]
+.PP
+If \f[CR]cond\f[R] is falsy (i.e.\ \f[CR]false\f[R] or \f[CR]nil\f[R]),
+throws an error with the first element of \f[CR]...\f[R] as the
+\f[CR]message\f[R].
+.SS http.h2_stream
+An h2_stream represents an HTTP 2 stream.
+The module follows the \f[I]stream\f[R] interface as well as HTTP 2
+specific functions.
+.SS \f[CR]h2_stream.connection\f[R] 
+See \f[CR]stream.connection\f[R]
+.SS \f[CR]h2_stream:checktls()\f[R] 
+See \f[CR]stream:checktls()\f[R]
+.SS \f[CR]h2_stream:localname()\f[R] 
+See \f[CR]stream:localname()\f[R]
+.SS \f[CR]h2_stream:peername()\f[R] 
+See \f[CR]stream:peername()\f[R]
+.SS \f[CR]h2_stream:get_headers(timeout)\f[R] 
+See \f[CR]stream:get_headers(timeout)\f[R]
+.SS \f[CR]h2_stream:write_headers(headers, end_stream, timeout)\f[R] 
+See \f[CR]stream:write_headers(headers, end_stream, timeout)\f[R]
+.SS \f[CR]h2_stream:write_continue(timeout)\f[R] 
+See \f[CR]stream:write_continue(timeout)\f[R]
+.SS \f[CR]h2_stream:get_next_chunk(timeout)\f[R] 
+See \f[CR]stream:get_next_chunk(timeout)\f[R]
+.SS \f[CR]h2_stream:each_chunk()\f[R] 
+See \f[CR]stream:each_chunk()\f[R]
+.SS \f[CR]h2_stream:get_body_as_string(timeout)\f[R] 
+See \f[CR]stream:get_body_as_string(timeout)\f[R]
+.SS \f[CR]h2_stream:get_body_chars(n, timeout)\f[R] 
+See \f[CR]stream:get_body_chars(n, timeout)\f[R]
+.SS \f[CR]h2_stream:get_body_until(pattern, plain, include_pattern, 
timeout)\f[R] 
+See
+\f[CR]stream:get_body_until(pattern, plain, include_pattern, timeout)\f[R]
+.SS \f[CR]h2_stream:save_body_to_file(file, timeout)\f[R] 
+See \f[CR]stream:save_body_to_file(file, timeout)\f[R]
+.SS \f[CR]h2_stream:get_body_as_file(timeout)\f[R] 
+See \f[CR]stream:get_body_as_file(timeout)\f[R]
+.SS \f[CR]h2_stream:unget(str)\f[R] 
+See \f[CR]stream:unget(str)\f[R]
+.SS \f[CR]h2_stream:write_chunk(chunk, end_stream, timeout)\f[R] 
+See \f[CR]stream:write_chunk(chunk, end_stream, timeout)\f[R]
+.SS \f[CR]h2_stream:write_body_from_string(str, timeout)\f[R] 
+See \f[CR]stream:write_body_from_string(str, timeout)\f[R]
+.SS \f[CR]h2_stream:write_body_from_file(options|file, timeout)\f[R] 
+See \f[CR]stream:write_body_from_file(options|file, timeout)\f[R]
+.SS \f[CR]h2_stream:shutdown()\f[R] 
+See \f[CR]stream:shutdown()\f[R]
+.SS \f[CR]h2_stream:pick_id(id)\f[R] 
+.SS \f[CR]h2_stream:set_state(new)\f[R] 
+.SS \f[CR]h2_stream:reprioritise(child, exclusive)\f[R] 
+.SS \f[CR]h2_stream:write_http2_frame(typ, flags, payload, timeout, 
flush)\f[R] 
+Writes a frame with \f[CR]h2_stream\f[R]\[cq]s stream id.
+.PP
+See
+\f[CR]h2_connection:write_http2_frame(typ, flags, streamid, payload, timeout, 
flush)\f[R]
+.SS \f[CR]h2_stream:write_data_frame(payload, end_stream, padded, timeout, 
flush)\f[R] 
+.SS \f[CR]h2_stream:write_headers_frame(payload, end_stream, end_headers, 
padded, exclusive, stream_dep, weight, timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:write_priority_frame(exclusive, stream_dep, weight, 
timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:write_rst_stream_frame(err_code, timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:rst_stream(err, timeout)\f[R] 
+.SS \f[CR]h2_stream:write_settings_frame(ACK, settings, timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:write_push_promise_frame(promised_stream_id, payload, 
end_headers, padded, timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:push_promise(headers, timeout)\f[R] 
+Pushes a new promise to the client.
+.PP
+Returns the new stream as a h2_stream.
+.SS \f[CR]h2_stream:write_ping_frame(ACK, payload, timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:write_goaway_frame(last_streamid, err_code, debug_msg, 
timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:write_window_update_frame(inc, timeout, flush)\f[R] 
+.SS \f[CR]h2_stream:write_window_update(inc, timeout)\f[R] 
+.SS \f[CR]h2_stream:write_continuation_frame(payload, end_headers, timeout, 
flush)\f[R] 
+.SS http.headers
+An ordered list of header fields.
+Each field has a \f[I]name\f[R], a \f[I]value\f[R] and a
+\f[I]never_index\f[R] flag that indicates if the header field is
+potentially sensitive data.
+.PP
+Each headers object has an index by field name to efficiently retrieve
+values by key.
+Keep in mind that there can be multiple values for a given field name.
+(e.g.\ an HTTP server may send two \f[CR]Set\-Cookie\f[R] headers).
+.PP
+As noted in the Conventions section, HTTP 1 request and status line
+fields are passed around inside of headers objects under keys
+\f[CR]\[dq]:authority\[dq]\f[R], \f[CR]\[dq]:method\[dq]\f[R],
+\f[CR]\[dq]:path\[dq]\f[R], \f[CR]\[dq]:scheme\[dq]\f[R] and
+\f[CR]\[dq]:status\[dq]\f[R] as defined in HTTP 2.
+As such, they are all kept in string form (important to remember for the
+\f[CR]\[dq]:status\[dq]\f[R] field).
+.SS \f[CR]new()\f[R] 
+Creates and returns a new headers object.
+.SS \f[CR]headers:len()\f[R] 
+Returns the number of headers.
+.PP
+Also available as \f[CR]#headers\f[R] in Lua 5.2+.
+.SS \f[CR]headers:clone()\f[R] 
+Creates and returns a clone of the headers object.
+.SS \f[CR]headers:append(name, value, never_index)\f[R] 
+Append a header.
+.IP \[bu] 2
+\f[CR]name\f[R] is the header field name.
+Lower case is the convention.
+It will not be validated at this time.
+.IP \[bu] 2
+\f[CR]value\f[R] is the header field value.
+It will not be validated at this time.
+.IP \[bu] 2
+\f[CR]never_index\f[R] is an optional boolean that indicates if the
+\f[CR]value\f[R] should be considered secret.
+Defaults to true for header fields: authorization, proxy\-authorization,
+cookie and set\-cookie.
+.SS \f[CR]headers:each()\f[R] 
+An iterator over all headers that emits
+\f[CR]name, value, never_index\f[R].
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] http_headers = require \[dq]http.headers\[dq]
+\f[B]local\f[R] myheaders = http_headers.new()
+myheaders:append(\[dq]:status\[dq], \[dq]200\[dq])
+myheaders:append(\[dq]set\-cookie\[dq], \[dq]foo=bar\[dq])
+myheaders:append(\[dq]connection\[dq], \[dq]close\[dq])
+myheaders:append(\[dq]set\-cookie\[dq], \[dq]baz=qux\[dq])
+\f[B]for\f[R] name, value, never_index \f[B]in\f[R] myheaders:each() 
\f[B]do\f[R]
+    print(name, value, never_index)
+\f[B]end\f[R]
+\f[I]\-\-[[ prints:\f[R]
+\f[I]\[dq]:status\[dq], \[dq]200\[dq], false\f[R]
+\f[I]\[dq]set\-cookie\[dq], \[dq]foo=bar\[dq], true\f[R]
+\f[I]\[dq]connection\[dq], \[dq]close\[dq], false\f[R]
+\f[I]\[dq]set\-cookie\[dq], \[dq]baz=qux\[dq], true\f[R]
+\f[I]]]\f[R]
+.EE
+.SS \f[CR]headers:has(name)\f[R] 
+Returns a boolean indicating if the headers object has a field with the
+given \f[CR]name\f[R].
+.SS \f[CR]headers:delete(name)\f[R] 
+Removes all occurrences of a field name from the headers object.
+.SS \f[CR]headers:geti(i)\f[R] 
+Return the \f[CR]i\f[R]\-th header as
+\f[CR]name, value, never_index\f[R]
+.SS \f[CR]headers:get_as_sequence(name)\f[R] 
+Returns all headers with the given name in a table.
+The table will contain a field \f[CR].n\f[R] with the number of
+elements.
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] http_headers = require \[dq]http.headers\[dq]
+\f[B]local\f[R] myheaders = http_headers.new()
+myheaders:append(\[dq]:status\[dq], \[dq]200\[dq])
+myheaders:append(\[dq]set\-cookie\[dq], \[dq]foo=bar\[dq])
+myheaders:append(\[dq]connection\[dq], \[dq]close\[dq])
+myheaders:append(\[dq]set\-cookie\[dq], \[dq]baz=qux\[dq])
+\f[B]local\f[R] mysequence = myheaders:get_as_sequence(\[dq]set\-cookie\[dq])
+\f[I]\-\-[[ mysequence will be:\f[R]
+\f[I]{n = 2; \[dq]foo=bar\[dq]; \[dq]baz=qux\[dq]}\f[R]
+\f[I]]]\f[R]
+.EE
+.SS \f[CR]headers:get(name)\f[R] 
+Returns all headers with the given name as multiple return values.
+.SS \f[CR]headers:get_comma_separated(name)\f[R] 
+Returns all headers with the given name as items in a comma separated
+string.
+.SS \f[CR]headers:modifyi(i, value, never_index)\f[R] 
+Change the \f[CR]i\f[R]\-th\[cq]s header to a new \f[CR]value\f[R] and
+\f[CR]never_index\f[R].
+.SS \f[CR]headers:upsert(name, value, never_index)\f[R] 
+If a header with the given \f[CR]name\f[R] already exists, replace it.
+If not, \f[CR]append\f[R] it to the list of headers.
+.PP
+Cannot be used when a header \f[CR]name\f[R] already has multiple
+values.
+.SS \f[CR]headers:sort()\f[R] 
+Sort the list of headers by their field name, ordering those starting
+with \f[CR]:\f[R] first.
+If \f[CR]name\f[R]s are equal then sort by \f[CR]value\f[R], then by
+\f[CR]never_index\f[R].
+.SS \f[CR]headers:dump(file, prefix)\f[R] 
+Print the headers list to the given file, one per line.
+If \f[CR]file\f[R] is not given, then print to \f[CR]stderr\f[R].
+\f[CR]prefix\f[R] is prefixed to each line.
+.SS http.hpack
+.SS \f[CR]new(SETTINGS_HEADER_TABLE_SIZE)\f[R] 
+.SS \f[CR]hpack_context:append_data(val)\f[R] 
+.SS \f[CR]hpack_context:render_data()\f[R] 
+.SS \f[CR]hpack_context:clear_data()\f[R] 
+.SS \f[CR]hpack_context:evict_from_dynamic_table()\f[R] 
+.SS \f[CR]hpack_context:dynamic_table_tostring()\f[R] 
+.SS 
\f[CR]hpack_context:set_max_dynamic_table_size(SETTINGS_HEADER_TABLE_SIZE)\f[R] 
+.SS \f[CR]hpack_context:encode_max_size(val)\f[R] 
+.SS \f[CR]hpack_context:resize_dynamic_table(new_size)\f[R] 
+.SS \f[CR]hpack_context:add_to_dynamic_table(name, value, k)\f[R] 
+.SS \f[CR]hpack_context:dynamic_table_id_to_index(id)\f[R] 
+.SS \f[CR]hpack_context:lookup_pair_index(k)\f[R] 
+.SS \f[CR]hpack_context:lookup_name_index(name)\f[R] 
+.SS \f[CR]hpack_context:lookup_index(index)\f[R] 
+.SS \f[CR]hpack_context:add_header_indexed(name, value, huffman)\f[R] 
+.SS \f[CR]hpack_context:add_header_never_indexed(name, value, huffman)\f[R] 
+.SS \f[CR]hpack_context:encode_headers(headers)\f[R] 
+.SS \f[CR]hpack_context:decode_headers(payload, header_list, pos)\f[R] 
+.SS http.hsts
+Data structures useful for HSTS (HTTP Strict Transport Security)
+.SS \f[CR]new_store()\f[R] 
+Creates and returns a new HSTS store.
+.SS \f[CR]hsts_store.max_items\f[R] 
+The maximum number of items allowed in the store.
+Decreasing this value will only prevent new items from being added, it
+will not remove old items.
+.PP
+Defaults to infinity (any number of items is allowed).
+.SS \f[CR]hsts_store:clone()\f[R] 
+Creates and returns a copy of a store.
+.SS \f[CR]hsts_store:store(host, directives)\f[R] 
+Add new directives to the store about the given \f[CR]host\f[R].
+\f[CR]directives\f[R] should be a table of directives, which
+\f[I]must\f[R] include the key \f[CR]\[dq]max\-age\[dq]\f[R].
+.PP
+Returns a boolean indicating if the item was accepted.
+.SS \f[CR]hsts_store:remove(host)\f[R] 
+Removes the entry for \f[CR]host\f[R] from the store (if it exists).
+.SS \f[CR]hsts_store:check(host)\f[R] 
+Returns a boolean indicating if the given \f[CR]host\f[R] is a known
+HSTS host.
+.SS \f[CR]hsts_store:clean_due()\f[R] 
+Returns the number of seconds until the next item in the store expires.
+.SS \f[CR]hsts_store:clean()\f[R] 
+Removes expired entries from the store.
+.SS http.proxies
+.SS \f[CR]new()\f[R] 
+Returns an empty `proxies' object
+.SS \f[CR]proxies:update(getenv)\f[R] 
+\f[CR]getenv\f[R] defaults to \c
+.UR http://www.lua.org/manual/5.4/manual.html#pdf-os.getenv
+\f[CR]os.getenv\f[R]
+.UE \c
+.PP
+Reads environmental variables that are used to control if requests go
+through a proxy.
+.IP \[bu] 2
+\f[CR]http_proxy\f[R] (or \f[CR]CGI_HTTP_PROXY\f[R] if running in a
+program with \f[CR]GATEWAY_INTERFACE\f[R] set): the proxy to use for
+normal HTTP connections
+.IP \[bu] 2
+\f[CR]https_proxy\f[R] or \f[CR]HTTPS_PROXY\f[R]: the proxy to use for
+HTTPS connections
+.IP \[bu] 2
+\f[CR]all_proxy\f[R] or \f[CR]ALL_PROXY\f[R]: the proxy to use for
+\f[B]all\f[R] connections, overridden by other options
+.IP \[bu] 2
+\f[CR]no_proxy\f[R] or \f[CR]NO_PROXY\f[R]: a list of hosts to
+\f[B]not\f[R] use a proxy for
+.PP
+Returns \f[CR]proxies\f[R].
+.SS \f[CR]proxies:choose(scheme, host)\f[R] 
+Returns the proxy to use for the given \f[CR]scheme\f[R] and
+\f[CR]host\f[R] as a URI.
+.SS http.request
+The http.request module encapsulates all the functionality required to
+retrieve an HTTP document from a server.
+.SS \f[CR]new_from_uri(uri)\f[R] 
+Creates a new \f[CR]http.request\f[R] object from the given URI.
+.SS \f[CR]new_connect(uri, connect_authority)\f[R] 
+Creates a new \f[CR]http.request\f[R] object from the given URI that
+will perform a \f[I]CONNECT\f[R] request.
+.SS \f[CR]request.host\f[R] 
+The host this request should be sent to.
+.SS \f[CR]request.port\f[R] 
+The port this request should be sent to.
+.SS \f[CR]request.bind\f[R] 
+The local outgoing address and optionally port to bind in the form of
+\f[CR]\[dq]address[:port]\[dq]\f[R].
+Default is to allow the kernel to choose an address+port.
+.PP
+IPv6 addresses may be specified via square bracket notation.
+e.g.\ \f[CR]\[dq]127.0.0.1\[dq]\f[R],
+\f[CR]\[dq]127.0.0.1:50000\[dq]\f[R], \f[CR]\[dq][::1]:30000\[dq]\f[R].
+.PP
+This option is rarely needed.
+Supplying an address can be used to manually select the network
+interface to make the request from, while supplying a port is only
+really used to interoperate with firewalls or devices that demand use of
+a certain port.
+.SS \f[CR]request.tls\f[R] 
+A boolean indicating if TLS should be used.
+.SS \f[CR]request.ctx\f[R] 
+An alternative \f[CR]SSL_CTX*\f[R] to use.
+If not specified, uses the default TLS settings (see \f[I]http.tls\f[R]
+for information).
+.SS \f[CR]request.sendname\f[R] 
+The TLS SNI host name used.
+.SS \f[CR]request.version\f[R] 
+The HTTP version to use; leave as \f[CR]nil\f[R] to auto\-select.
+.SS \f[CR]request.proxy\f[R] 
+Specifies the a proxy that the request will be made through.
+The value should be a URI or \f[CR]false\f[R] to turn off proxying for
+the request.
+.SS \f[CR]request.headers\f[R] 
+A \f[I]http.headers\f[R] object of headers that will be sent in the
+request.
+.SS \f[CR]request.hsts\f[R] 
+The \f[I]http.hsts\f[R] store that will be used to enforce HTTP strict
+transport security.
+An attempt will be made to add strict transport headers from a response
+to the store.
+.PP
+Defaults to a shared store.
+.SS \f[CR]request.proxies\f[R] 
+The \f[I]http.proxies\f[R] object used to select a proxy for the
+request.
+Only consulted if \f[CR]request.proxy\f[R] is \f[CR]nil\f[R].
+.SS \f[CR]request.cookie_store\f[R] 
+The \f[I]http.cookie.store\f[R] that will be used to find cookies for
+the request.
+An attempt will be made to add cookies from a response to the store.
+.PP
+Defaults to a shared store.
+.SS \f[CR]request.is_top_level\f[R] 
+A boolean flag indicating if this request is a \[lq]top level\[rq]
+request (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+)
+.PP
+Defaults to \f[CR]true\f[R]
+.SS \f[CR]request.site_for_cookies\f[R] 
+A string containing the host that should be considered as the \[lq]site
+for cookies\[rq] (See \c
+.UR https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-02#section-5.2
+RFC 6265bis\-02 Section 5.2
+.UE \c
+), can be \f[CR]nil\f[R] if unknown.
+.PP
+Defaults to \f[CR]nil\f[R].
+.SS \f[CR]request.follow_redirects\f[R] 
+Boolean indicating if \f[CR]:go()\f[R] should follow redirects.
+Defaults to \f[CR]true\f[R].
+.SS \f[CR]request.expect_100_timeout\f[R] 
+Number of seconds to wait for a 100 Continue response before proceeding
+to send a request body.
+Defaults to \f[CR]1\f[R].
+.SS \f[CR]request.max_redirects\f[R] 
+Maximum number of redirects to follow before giving up.
+Defaults to \f[CR]5\f[R].
+Set to \f[CR]math.huge\f[R] to not give up.
+.SS \f[CR]request.post301\f[R] 
+Respect RFC 2616 Section 10.3.2 and \f[B]don\[cq]t\f[R] convert POST
+requests into body\-less GET requests when following a 301 redirect.
+The non\-RFC behaviour is ubiquitous in web browsers and assumed by
+servers.
+Modern HTTP endpoints send status code 308 to indicate that they
+don\[cq]t want the method to be changed.
+Defaults to \f[CR]false\f[R].
+.SS \f[CR]request.post302\f[R] 
+Respect RFC 2616 Section 10.3.3 and \f[B]don\[cq]t\f[R] convert POST
+requests into body\-less GET requests when following a 302 redirect.
+The non\-RFC behaviour is ubiquitous in web browsers and assumed by
+servers.
+Modern HTTP endpoints send status code 307 to indicate that they
+don\[cq]t want the method to be changed.
+Defaults to \f[CR]false\f[R].
+.SS \f[CR]request:clone()\f[R] 
+Creates and returns a clone of the request.
+.PP
+The clone has its own deep copies of the \f[CR].headers\f[R] and
+\f[CR].h2_settings\f[R] fields.
+.PP
+The \f[CR].tls\f[R] and \f[CR].body\f[R] fields are shallow copied from
+the original request.
+.SS \f[CR]request:handle_redirect(headers)\f[R] 
+Process a redirect.
+.PP
+\f[CR]headers\f[R] should be response headers for a redirect.
+.PP
+Returns a new \f[CR]request\f[R] object that will fetch from new
+location.
+.SS \f[CR]request:to_uri(with_userinfo)\f[R] 
+Returns a URI for the request.
+.PP
+If \f[CR]with_userinfo\f[R] is \f[CR]true\f[R] and the request has an
+\f[CR]authorization\f[R] header (or \f[CR]proxy\-authorization\f[R] for
+a CONNECT request), the returned URI will contain a userinfo component.
+.SS \f[CR]request:set_body(body)\f[R] 
+Allows setting a request body.
+\f[CR]body\f[R] may be a string, function or lua file object.
+.IP \[bu] 2
+If \f[CR]body\f[R] is a string it will be sent as given.
+.IP \[bu] 2
+If \f[CR]body\f[R] is a function, it will be called repeatedly like an
+iterator.
+It should return chunks of the request body as a string or
+\f[CR]nil\f[R] if done.
+.IP \[bu] 2
+If \f[CR]body\f[R] is a lua file object, it will be \c
+.UR http://www.lua.org/manual/5.4/manual.html#pdf-file:seek
+\f[CR]:seek\f[R]\[cq]d
+.UE \c
+\ to the start, then sent as a body.
+Any errors encountered during file operations \f[B]will be thrown\f[R].
+.SS \f[CR]request:go(timeout)\f[R] 
+Performs the request.
+.PP
+The request object is \f[B]not\f[R] invalidated; and can be reused for a
+new request.
+On success, returns the response \f[I]headers\f[R] and a
+\f[I]stream\f[R].
+.SS http.server
+\f[I]http.server\f[R] objects are used to encapsulate the
+\f[CR]accept()\f[R] and dispatch of http clients.
+Each new client request will invoke the \f[CR]onstream\f[R] callback in
+a new cqueues managed coroutine.
+In addition to constructing and returning a HTTP response, an
+\f[CR]onstream\f[R] handler may decide to take ownership of the
+connection for other purposes, e.g.\ upgrade from a HTTP 1.1 connection
+to a WebSocket connection.
+.PP
+For examples of how to use the server library, please see the \c
+.UR https://github.com/daurnimator/lua-http/tree/master/examples
+examples directory
+.UE \c
+\ in the source tree.
+.SS \f[CR]new(options)\f[R] 
+Creates a new instance of an HTTP server listening on the given socket.
+.IP \[bu] 2
+\f[CR].socket\f[R] (\f[I]cqueues.socket\f[R]): the socket that
+\f[CR]accept()\f[R] will be called on
+.IP \[bu] 2
+\f[CR].onerror\f[R] (\f[I]function\f[R]): Function that will be called
+when an error occurs (default handler throws an error).
+See server:onerror()
+.IP \[bu] 2
+\f[CR].onstream\f[R] (\f[I]function\f[R]): Callback function for
+handling a new client request.
+The function receives the \f[I]server\f[R] and the new \f[I]stream\f[R]
+as parameters.
+If the callback throws an error it will be reported from
+\f[CR]:step()\f[R] or \f[CR]:loop()\f[R]
+.IP \[bu] 2
+\f[CR].tls\f[R] (\f[I]boolean\f[R]): Specifies if the system should use
+Transport Layer Security.
+Values are:
+.RS 2
+.IP \[bu] 2
+\f[CR]nil\f[R]: Allow both tls and non\-tls connections
+.IP \[bu] 2
+\f[CR]true\f[R]: Allows tls connections only
+.IP \[bu] 2
+\f[CR]false\f[R]: Allows non\-tls connections only
+.RE
+.IP \[bu] 2
+\f[CR].ctx\f[R] (\f[I]context object\f[R]): An
+\f[CR]openssl.ssl.context\f[R] object to use for tls connections.
+If \f[CR]nil\f[R] is passed, a self\-signed context will be generated.
+.IP \[bu] 2
+\f[CR].connection_setup_timeout\f[R] (\f[I]number\f[R]): Timeout (in
+seconds) to wait for client to send first bytes and/or complete TLS
+handshake.
+Default is 10 seconds.
+.IP \[bu] 2
+\f[CR].intra_stream_timeout\f[R] (\f[I]number\f[R]): Timeout (in
+seconds) to wait for a new \f[I]stream\f[R] on an idle connection before
+giving up and closing the connection
+.IP \[bu] 2
+\f[CR].version\f[R] (\f[I]number\f[R]): The http version to allow to
+connect (default: any)
+.IP \[bu] 2
+\f[CR].cq\f[R] (\f[I]cqueue\f[R]): A cqueues controller to use as a main
+loop.
+The default is a new controller for the server.
+.IP \[bu] 2
+\f[CR].max_concurrent\f[R] (\f[I]number\f[R]): Maximum number of
+connections to allow live at a time.
+Default is infinity.
+.SS \f[CR]listen(options)\f[R] 
+Creates a new socket and returns an HTTP server that will accept() from
+it.
+Parameters are the same as \f[CR]new(options)\f[R] except instead of
+\f[CR].socket\f[R] you provide the following:
+.IP \[bu] 2
+\f[CR].host\f[R] (\f[I]string\f[R]): Local IP address in dotted decimal
+or IPV6 notation.
+This value is required if \f[CR].path\f[R] is not specified.
+.IP \[bu] 2
+\f[CR].port\f[R] (\f[I]number\f[R]): IP port for the local socket.
+Specify 0 for automatic port selection.
+Ports 1\-1024 require the application has root privilege to run.
+Maximum value is 65535.
+If \f[CR].tls == nil\f[R] then this value is required.
+Otherwise, the defaults are:
+.RS 2
+.IP \[bu] 2
+\f[CR]80\f[R] if \f[CR].tls == false\f[R]
+.IP \[bu] 2
+\f[CR]443\f[R] if \f[CR].tls == true\f[R]
+.RE
+.IP \[bu] 2
+\f[CR].path\f[R] (\f[I]string\f[R]): Path to UNIX a socket.
+This value is required if \f[CR].host\f[R] is not specified.
+.IP \[bu] 2
+\f[CR].family\f[R] (\f[I]string\f[R]): Protocol family.
+Default is \f[CR]\[dq]AF_INET\[dq]\f[R]
+.IP \[bu] 2
+\f[CR].v6only\f[R] (\f[I]boolean\f[R]): Specify \f[CR]true\f[R] to limit
+all connections to ipv6 only (no ipv4\-mapped\-ipv6).
+Default is \f[CR]false\f[R].
+.IP \[bu] 2
+\f[CR].mode\f[R] (\f[I]string\f[R]): \f[CR]fchmod\f[R] or
+\f[CR]chmod\f[R] socket after creating UNIX domain socket.
+.IP \[bu] 2
+\f[CR].mask\f[R] (\f[I]boolean\f[R]): Set and restore umask when binding
+UNIX domain socket.
+.IP \[bu] 2
+\f[CR].unlink\f[R] (\f[I]boolean\f[R]): \f[CR]true\f[R] means unlink
+socket path before binding.
+.IP \[bu] 2
+\f[CR].reuseaddr\f[R] (\f[I]boolean\f[R]): Turn on
+\f[CR]SO_REUSEADDR\f[R] flag.
+.IP \[bu] 2
+\f[CR].reuseport\f[R] (\f[I]boolean\f[R]): Turn on
+\f[CR]SO_REUSEPORT\f[R] flag.
+.SS \f[CR]server:onerror(new_handler)\f[R] 
+If called with parameters, the function replaces the current error
+handler function with \f[CR]new_handler\f[R] and returns a reference to
+the old function.
+Calling the function with no parameters returns the current error
+handler.
+The default handler throws an error.
+The \f[CR]onerror\f[R] function for the server can be set during
+instantiation through the \f[CR]options\f[R] table passed to the
+\f[CR]server.listen(options)\f[R] function.
+.SS \f[CR]server:listen(timeout)\f[R] 
+Initializes the server socket and if required, resolves DNS.
+\f[CR]server:listen()\f[R] is required if \f[I]localname\f[R] is called
+before \f[I]step\f[R] or \f[I]loop\f[R].
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]server:localname()\f[R] 
+Returns the connection information for the local socket.
+Returns address family, IP address and port for an external socket.
+For Unix domain sockets, the function returns AF_UNIX and the path.
+If the connection object is not connected, returns AF_UNSPEC (0).
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]server:pause()\f[R] 
+Cause the server loop to stop processing new clients until
+\f[I]resume\f[R] is called.
+Existing client connections will run until closed.
+.SS \f[CR]server:resume()\f[R] 
+Resumes a \f[I]paused\f[R] \f[CR]server\f[R] and processes new client
+requests.
+.SS \f[CR]server:close()\f[R] 
+Shutdown the server and close the socket.
+A closed server cannot be reused.
+.SS \f[CR]server:pollfd()\f[R] 
+Returns a file descriptor (as an integer) or \f[CR]nil\f[R].
+.PP
+The file descriptor can be passed to a system API like \f[CR]select\f[R]
+or \f[CR]kqueue\f[R] to wait on anything this server object wants to do.
+This method is used for integrating with other main loops, and should be
+used in combination with \f[CR]:events()\f[R] and \f[CR]:timeout()\f[R].
+.SS \f[CR]server:events()\f[R] 
+Returns a string indicating the type of events the object is waiting on:
+the string will contain \f[CR]\[dq]r\[dq]\f[R] if it wants to be
+\f[I]step\f[R]ed when the file descriptor returned by
+\f[CR]pollfd()\f[R] has had POLLIN indicated; \f[CR]\[dq]w\[dq]\f[R] for
+POLLOUT or \f[CR]\[dq]p\[dq]\f[R] for POLLPRI.
+.PP
+This method is used for integrating with other main loops, and should be
+used in combination with \f[CR]:pollfd()\f[R] and \f[CR]:timeout()\f[R].
+.SS \f[CR]server:timeout()\f[R] 
+The maximum time (in seconds) to wait before calling
+\f[CR]server:step()\f[R].
+.PP
+This method is used for integrating with other main loops, and should be
+used in combination with \f[CR]:pollfd()\f[R] and \f[CR]:events()\f[R].
+.SS \f[CR]server:empty()\f[R] 
+Returns \f[CR]true\f[R] if the master socket and all client connection
+have been closed, \f[CR]false\f[R] otherwise.
+.SS \f[CR]server:step(timeout)\f[R] 
+Step once through server\[cq]s main loop: any waiting clients will be
+\f[CR]accept()\f[R]\-ed, any pending streams will start getting
+processed, and each \f[CR]onstream\f[R] handler will get be run at most
+once.
+This method will block for \f[I]up to\f[R] \f[CR]timeout\f[R] seconds.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.PP
+This can be used for integration with external main loops.
+.SS \f[CR]server:loop(timeout)\f[R] 
+Run the server as a blocking loop for up to \f[CR]timeout\f[R] seconds.
+The server will continue to listen and accept client requests until
+either \f[CR]:pause()\f[R] or \f[CR]:close()\f[R] is called, or an error
+is experienced.
+.SS \f[CR]server:add_socket(socket)\f[R] 
+Add a new connection socket to the server for processing.
+The server will use the current \f[CR]onstream\f[R] request handler and
+all \f[CR]options\f[R] currently specified through the
+\f[CR]server.listen(options)\f[R] constructor.
+\f[CR]add_socket\f[R] can be used to process connection sockets obtained
+from an external source such as:
+.IP \[bu] 2
+Another cqueues thread with some other master socket.
+.IP \[bu] 2
+From inetd for start on demand daemons.
+.IP \[bu] 2
+A Unix socket with \f[CR]SCM_RIGHTS\f[R].
+.SS \f[CR]server:add_stream(stream)\f[R] 
+Add an existing stream to the server for processing.
+.SS http.socks
+Implements a subset of the SOCKS proxy protocol.
+.SS \f[CR]connect(uri)\f[R] 
+\f[CR]uri\f[R] is a string with the address of the SOCKS server.
+A scheme of \f[CR]\[dq]socks5\[dq]\f[R] will resolve hosts locally, a
+scheme of \f[CR]\[dq]socks5h\[dq]\f[R] will resolve hosts on the SOCKS
+server.
+If the URI has a userinfo component it will be sent to the SOCKS server
+as a username and password.
+.PP
+Returns a \f[I]http.socks\f[R] object.
+.SS \f[CR]fdopen(socket)\f[R] 
+This function takes an existing cqueues.socket as a parameter and
+returns a \f[I]http.socks\f[R] object with \f[CR]socket\f[R] as its
+base.
+.SS \f[CR]socks.needs_resolve\f[R] 
+Specifies if the destination host should be resolved locally.
+.SS \f[CR]socks:clone()\f[R] 
+Make a clone of a given socks object.
+.SS \f[CR]socks:add_username_password_auth(username, password)\f[R] 
+Add username + password authorisation to the set of allowed
+authorisation methods with the given credentials.
+.SS \f[CR]socks:negotiate(host, port, timeout)\f[R] 
+Complete the SOCKS connection.
+.PP
+Negotiates a socks connection.
+\f[CR]host\f[R] is a required string passed to the SOCKS server as the
+host address.
+The address will be resolved locally if \f[CR].needs_resolve\f[R] is
+\f[CR]true\f[R].
+\f[CR]port\f[R] is a required number to pass to the SOCKS server as the
+connection port.
+On error, returns \f[CR]nil\f[R], an error message and an error number.
+.SS \f[CR]socks:close()\f[R] 
+.SS \f[CR]socks:take_socket()\f[R] 
+Take possession of the socket object managed by the http.socks object.
+Returns the socket (or \f[CR]nil\f[R] if not available).
+.SS http.tls
+.SS \f[CR]has_alpn\f[R] 
+Boolean indicating if ALPN is available in the current environment.
+.PP
+It may be disabled if OpenSSL was compiled without ALPN support, or is
+an old version.
+.SS \f[CR]has_hostname_validation\f[R] 
+Boolean indicating if \c
+.UR https://wiki.openssl.org/index.php/Hostname_validation
+hostname validation
+.UE \c
+\ is available in the current environment.
+.PP
+It may be disabled if OpenSSL is an old version.
+.SS \f[CR]modern_cipher_list\f[R] 
+The \c
+.UR https://wiki.mozilla.org/Security/Server_Side_TLS#Modern_compatibility
+Mozilla \[lq]Modern\[rq] cipher list
+.UE \c
+\ as a colon separated list, ready to pass to OpenSSL
+.SS \f[CR]intermediate_cipher_list\f[R] 
+The \c
+.UR 
https://wiki.mozilla.org/Security/Server_Side_TLS#Intermediate_compatibility_.28default.29
+Mozilla \[lq]Intermediate\[rq] cipher list
+.UE \c
+\ as a colon separated list, ready to pass to OpenSSL
+.SS \f[CR]old_cipher_list\f[R] 
+The \c
+.UR 
https://wiki.mozilla.org/Security/Server_Side_TLS#Old_backward_compatibility
+Mozilla \[lq]Old\[rq] cipher list
+.UE \c
+\ as a colon separated list, ready to pass to OpenSSL
+.SS \f[CR]banned_ciphers\f[R] 
+A set (table with string keys and values of \f[CR]true\f[R]) of the \c
+.UR https://http2.github.io/http2-spec/#BadCipherSuites
+ciphers banned in HTTP 2
+.UE \c
+\ where the keys are OpenSSL cipher names.
+.PP
+Ciphers not known by OpenSSL are missing from the set.
+.SS \f[CR]new_client_context()\f[R] 
+Create and return a new luaossl SSL context useful for HTTP client
+connections.
+.SS \f[CR]new_server_context()\f[R] 
+Create and return a new luaossl SSL context useful for HTTP server
+connections.
+.SS http.util
+.SS \f[CR]encodeURI(str)\f[R] 
+.SS \f[CR]encodeURIComponent(str)\f[R] 
+.SS \f[CR]decodeURI(str)\f[R] 
+.SS \f[CR]decodeURIComponent(str)\f[R] 
+.SS \f[CR]query_args(str)\f[R] 
+Returns an iterator over the pairs in \f[CR]str\f[R]
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] http_util = require \[dq]http.util\[dq]
+\f[B]for\f[R] name, value \f[B]in\f[R] 
http_util.query_args(\[dq]foo=bar&baz=qux\[dq]) \f[B]do\f[R]
+    print(name, value)
+\f[B]end\f[R]
+\f[I]\-\-[[ prints:\f[R]
+\f[I]\[dq]foo\[dq], \[dq]bar\[dq]\f[R]
+\f[I]\[dq]baz\[dq], \[dq]qux\[dq]\f[R]
+\f[I]]]\f[R]
+.EE
+.SS \f[CR]dict_to_query(dict)\f[R] 
+Converts a dictionary (table with string keys) with string values to an
+encoded query string.
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] http_util = require \[dq]http.util\[dq]
+print(http_util.dict_to_query({foo = \[dq]bar\[dq]; baz = \[dq]qux\[dq]})) 
\f[I]\-\-> \[dq]baz=qux&foo=bar\[dq]\f[R]
+.EE
+.SS \f[CR]resolve_relative_path(orig_path, relative_path)\f[R] 
+.SS \f[CR]is_safe_method(method)\f[R] 
+Returns a boolean indicating if the passed string \f[CR]method\f[R] is a
+\[lq]safe\[rq] method.
+See \c
+.UR https://tools.ietf.org/html/rfc7231#section-4.2.1
+RFC 7231 section 4.2.1
+.UE \c
+\ for more information.
+.SS \f[CR]is_ip(str)\f[R] 
+Returns a boolean indicating if the passed string \f[CR]str\f[R] is a
+valid IP.
+.SS \f[CR]scheme_to_port\f[R] 
+Map from schemes (as strings) to default ports (as integers).
+.SS \f[CR]split_authority(authority, scheme)\f[R] 
+Splits an \f[CR]authority\f[R] into host and port components.
+If the authority has no port component, will attempt to use the default
+for the \f[CR]scheme\f[R].
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] http_util = require \[dq]http.util\[dq]
+print(http_util.split_authority(\[dq]localhost:8000\[dq], \[dq]http\[dq])) 
\f[I]\-\-> \[dq]localhost\[dq], 8000\f[R]
+print(http_util.split_authority(\[dq]example.com\[dq], \[dq]https\[dq])) 
\f[I]\-\-> \[dq]localhost\[dq], 443\f[R]
+.EE
+.SS \f[CR]to_authority(host, port, scheme)\f[R] 
+Joins the \f[CR]host\f[R] and \f[CR]port\f[R] to create a valid
+authority component.
+Omits the port if it is the default for the \f[CR]scheme\f[R].
+.SS \f[CR]imf_date(time)\f[R] 
+Returns the time in HTTP preferred date format (See \c
+.UR https://tools.ietf.org/html/rfc7231#section-7.1.1.1
+RFC 7231 section 7.1.1.1
+.UE \c
+)
+.PP
+\f[CR]time\f[R] defaults to the current time
+.SS \f[CR]maybe_quote(str)\f[R] 
+.IP \[bu] 2
+If \f[CR]str\f[R] is a valid \f[CR]token\f[R], return it as\-is.
+.IP \[bu] 2
+If \f[CR]str\f[R] would be valid as a \f[CR]quoted\-string\f[R], return
+the quoted version
+.IP \[bu] 2
+Otherwise, returns \f[CR]nil\f[R]
+.SS http.version
+.SS \f[CR]name\f[R] 
+\f[CR]\[dq]lua\-http\[dq]\f[R]
+.SS \f[CR]version\f[R] 
+Current version of lua\-http as a string.
+.SS http.websocket
+.SS \f[CR]new_from_uri(uri, protocols)\f[R] 
+Creates a new \f[CR]http.websocket\f[R] object of type
+\f[CR]\[dq]client\[dq]\f[R] from the given URI.
+.IP \[bu] 2
+\f[CR]protocols\f[R] (optional) should be a lua table containing a
+sequence of protocols to send to the server
+.SS \f[CR]new_from_stream(stream, headers)\f[R] 
+Attempts to create a new \f[CR]http.websocket\f[R] object of type
+\f[CR]\[dq]server\[dq]\f[R] from the given request headers and stream.
+.IP \[bu] 2
+\f[CR]stream\f[R] should be a live HTTP 1 stream of the
+\f[CR]\[dq]server\[dq]\f[R] type.
+.IP \[bu] 2
+\f[CR]headers\f[R] should be headers of a suspected websocket upgrade
+request from an HTTP 1 client.
+.PP
+This function does \f[B]not\f[R] have side effects, and is hence okay to
+use tentatively.
+.SS \f[CR]websocket.close_timeout\f[R] 
+Amount of time (in seconds) to wait between sending a close frame and
+actually closing the connection.
+Defaults to \f[CR]3\f[R] seconds.
+.SS \f[CR]websocket:accept(options, timeout)\f[R] 
+Completes negotiation with a websocket client.
+.IP \[bu] 2
+\f[CR]options\f[R] is a table containing:
+.RS 2
+.IP \[bu] 2
+\f[CR]headers\f[R] (optional) a headers object to use as a prototype for
+the response headers
+.IP \[bu] 2
+\f[CR]protocols\f[R] (optional) should be a lua table containing a
+sequence of protocols to allow from the client
+.RE
+.PP
+Usually called after a successful \f[CR]new_from_stream\f[R]
+.SS \f[CR]websocket:connect(timeout)\f[R] 
+Connect to a websocket server.
+.PP
+Usually called after a successful \f[CR]new_from_uri\f[R]
+.SS \f[CR]websocket:receive(timeout)\f[R] 
+Reads and returns the next data frame plus its opcode.
+Any ping frames received while reading will be responded to.
+.PP
+The opcode \f[CR]0x1\f[R] will be returned as \f[CR]\[dq]text\[dq]\f[R]
+and \f[CR]0x2\f[R] will be returned as \f[CR]\[dq]binary\[dq]\f[R].
+.SS \f[CR]websocket:each()\f[R] 
+Iterator over \f[CR]websocket:receive()\f[R].
+.SS \f[CR]websocket:send_frame(frame, timeout)\f[R] 
+Low level function to send a raw frame.
+.SS \f[CR]websocket:send(data, opcode, timeout)\f[R] 
+Send the given \f[CR]data\f[R] as a data frame.
+.IP \[bu] 2
+\f[CR]data\f[R] should be a string
+.IP \[bu] 2
+\f[CR]opcode\f[R] can be a numeric opcode, \f[CR]\[dq]text\[dq]\f[R] or
+\f[CR]\[dq]binary\[dq]\f[R].
+If \f[CR]nil\f[R], defaults to a text frame.
+Note this \f[CR]opcode\f[R] is the websocket frame opcode, not an
+application specific opcode.
+The opcode should be one from the \c
+.UR https://www.iana.org/assignments/websocket/websocket.xhtml#opcode
+IANA registry
+.UE \c
+\&.
+.SS \f[CR]websocket:send_ping(data, timeout)\f[R] 
+Sends a ping frame.
+.IP \[bu] 2
+\f[CR]data\f[R] is optional
+.SS \f[CR]websocket:send_pong(data, timeout)\f[R] 
+Sends a pong frame.
+Works as a unidirectional keep\-alive.
+.IP \[bu] 2
+\f[CR]data\f[R] is optional
+.SS \f[CR]websocket:close(code, reason, timeout)\f[R] 
+Closes the websocket connection.
+.IP \[bu] 2
+\f[CR]code\f[R] defaults to \f[CR]1000\f[R]
+.IP \[bu] 2
+\f[CR]reason\f[R] is an optional string
+.SS http.zlib
+An abstraction layer over the various lua zlib libraries.
+.SS \f[CR]engine\f[R] 
+Currently either \c
+.UR https://github.com/brimworks/lua-zlib
+\f[CR]\[dq]lua\-zlib\[dq]\f[R]
+.UE \c
+\ or \c
+.UR https://github.com/LuaDist/lzlib
+\f[CR]\[dq]lzlib\[dq]\f[R]
+.UE \c
+.SS \f[CR]inflate()\f[R] 
+Returns a closure that inflates (uncompresses) a zlib stream.
+.PP
+The closure takes a string of compressed data and an end of stream flag
+(\f[CR]boolean\f[R]) as parameters and returns the inflated output as a
+string.
+The function will throw an error if the input is not a valid zlib
+stream.
+.SS \f[CR]deflate()\f[R] 
+Returns a closure that deflates (compresses) a zlib stream.
+.PP
+The closure takes a string of uncompressed data and an end of stream
+flag (\f[CR]boolean\f[R]) as parameters and returns the deflated output
+as a string.
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] zlib = require \[dq]http.zlib\[dq]
+\f[B]local\f[R] original = \[dq]the racecar raced around the racecar track\[dq]
+\f[B]local\f[R] deflater = zlib.deflate()
+\f[B]local\f[R] compressed = deflater(original, \f[B]true\f[R])
+print(#original, #compressed) \f[I]\-\- compressed should be smaller\f[R]
+\f[B]local\f[R] inflater = zlib.inflate()
+\f[B]local\f[R] uncompressed = inflater(compressed, \f[B]true\f[R])
+assert(original == uncompressed)
+.EE
+.SS http.compat.prosody
+Provides usage similar to \c
+.UR https://prosody.im/doc/developers/net/http
+prosody\[cq]s net.http
+.UE \c
+.SS \f[CR]request(url, ex, callback)\f[R] 
+A few key differences to the prosody \f[CR]net.http.request\f[R]:
+.IP \[bu] 2
+must be called from within a running cqueue
+.IP \[bu] 2
+The callback may be called from a different thread in the cqueue
+.IP \[bu] 2
+The returned object will be a \f[I]http.request\f[R] object
+.RS 2
+.IP \[bu] 2
+This object is passed to the callback on errors and as the fourth
+argument on success
+.RE
+.IP \[bu] 2
+The default user\-agent will be from lua\-http (rather than
+\f[CR]\[dq]Prosody XMPP Server\[dq]\f[R])
+.IP \[bu] 2
+lua\-http features (such as HTTP2) will be used where possible
+.SS Example
+.IP
+.EX
+\f[B]local\f[R] prosody_http = require \[dq]http.compat.prosody\[dq]
+\f[B]local\f[R] cqueues = require \[dq]cqueues\[dq]
+\f[B]local\f[R] cq = cqueues.new()
+cq:wrap(\f[B]function\f[R]()
+    prosody_http.request(\[dq]http://httpbin.org/ip\[dq], {}, 
\f[B]function\f[R](b, c, r)
+        print(c) \f[I]\-\-> 200\f[R]
+        print(b) \f[I]\-\-> {\[dq]origin\[dq]: \[dq]123.123.123.123\[dq]}\f[R]
+    \f[B]end\f[R])
+\f[B]end\f[R])
+assert(cq:loop())
+.EE
+.SS http.compat.socket
+Provides compatibility with \c
+.UR http://w3.impa.br/~diego/software/luasocket/http.html
+luasocket\[cq]s http.request module
+.UE \c
+\&.
+.PP
+Differences:
+.IP \[bu] 2
+Will automatically be non\-blocking when run inside a cqueues managed
+coroutine
+.IP \[bu] 2
+lua\-http features (such as HTTP2) will be used where possible
+.SS Example
+Using the `simple' interface as part of a normal script:
+.IP
+.EX
+\f[B]local\f[R] socket_http = require \[dq]http.compat.socket\[dq]
+\f[B]local\f[R] body, code = 
assert(socket_http.request(\[dq]http://lua.org\[dq]))
+print(code, #body) \f[I]\-\-> 200, 2514\f[R]
+.EE
+.SH Links
+.IP \[bu] 2
+\c
+.UR https://github.com/daurnimator/lua-http
+Github
+.UE \c
+.IP \[bu] 2
+\c
+.UR https://github.com/daurnimator/lua-http/issues
+Issue tracker
+.UE \c
+.SH AUTHORS
+Daurnimator \c
+.MT q...@daurnimator.com
+.ME \c.

diff --git a/dev-lua/lua-http/lua-http-20240908.ebuild 
b/dev-lua/lua-http/lua-http-0.4_p20240908.ebuild
similarity index 81%
rename from dev-lua/lua-http/lua-http-20240908.ebuild
rename to dev-lua/lua-http/lua-http-0.4_p20240908.ebuild
index c0e49196e..2d446bc7e 100644
--- a/dev-lua/lua-http/lua-http-20240908.ebuild
+++ b/dev-lua/lua-http/lua-http-0.4_p20240908.ebuild
@@ -9,6 +9,7 @@ inherit lua
 
 DESCRIPTION="HTTP Library for Lua. Supports HTTP(S) 1.0, 1.1 and 2.0; client 
and server."
 HOMEPAGE="https://daurnimator.github.io/lua-http/";
+HOMEPAGE+=" https://github.com/daurnimator/lua-http";
 EGIT_COMMIT="ee3cf4b4992479b8ebfb39b530694af3bbd1d1eb"
 SRC_URI="https://github.com/daurnimator/${PN}/archive/${EGIT_COMMIT}.tar.gz -> 
${P}.tar.gz"
 S="${WORKDIR}/${PN}-${EGIT_COMMIT}"
@@ -17,12 +18,11 @@ LICENSE="MIT"
 SLOT="0"
 KEYWORDS="~amd64"
 
+IUSE="doc"
 REQUIRED_USE="${LUA_REQUIRED_USE}"
 
 DEPEND="
        ${LUA_DEPS}
-       lua_targets_luajit? ( dev-lua/compat53[lua_targets_luajit(-)] )
-       lua_targets_lua5-1? ( dev-lua/compat53[lua_targets_lua5-1(-)] )
        dev-lua/basexx[${LUA_USEDEP}]
        dev-lua/binaryheap[${LUA_USEDEP}]
        dev-lua/cqueues[${LUA_USEDEP}]
@@ -31,11 +31,19 @@ DEPEND="
        dev-lua/lpeg-patterns[${LUA_USEDEP}]
        dev-lua/LuaBitOp[${LUA_USEDEP}]
        dev-lua/luaossl[${LUA_USEDEP}]
+       lua_targets_luajit? ( dev-lua/compat53[lua_targets_luajit(-)] )
+       lua_targets_lua5-1? ( dev-lua/compat53[lua_targets_lua5-1(-)] )
 "
 RDEPEND="${DEPEND}"
+BDEPEND="doc? ( virtual/pandoc )"
 
 lua_enable_tests busted
 
+src_compile() {
+       default
+       use doc && emake -C doc lua-http.html
+}
+
 lua_src_install() {
        insinto $(lua_get_lmod_dir)/http/
        doins http/*.lua http/compat/*.lua
@@ -43,5 +51,8 @@ lua_src_install() {
 
 src_install() {
        lua_foreach_impl lua_src_install
+       use doc && local HTML_DOCS=( doc/lua-http.html )
+       dodoc -r "examples"
+       doman "${FILESDIR}"/lua-http.3
        einstalldocs
 }


Reply via email to