API Reference

Client Requests

HTTP.requestFunction
HTTP.request(method, url [, headers [, body]]; <keyword arguments>]) -> HTTP.Response

Send a HTTP Request Message and receive a HTTP Response Message.

e.g.

r = HTTP.request("GET", "http://httpbin.org/ip")
r = HTTP.get("http://httpbin.org/ip") # equivalent shortcut
println(r.status)
println(String(r.body))

headers can be any collection where [string(k) => string(v) for (k,v) in headers] yields Vector{Pair}. e.g. a Dict(), a Vector{Tuple}, a Vector{Pair} or an iterator. By convention, if a header value is an empty string, it will not be written when sending a request (following the curl convention). By default, a copy of provided headers is made (since required headers are typically set during the request); to avoid this copy and have HTTP.jl mutate the provided headers array, pass copyheaders=false as an additional keyword argument to the request.

The body argument can be a variety of objects:

  • an AbstractDict or NamedTuple to be serialized as the "application/x-www-form-urlencoded" content type
  • any AbstractString or AbstractVector{UInt8} which will be sent "as is" for the request body
  • a readable IO stream or any IO-like type T for which eof(T) and readavailable(T) are defined. This stream will be read and sent until eof is true. This object should support the mark/reset methods if request retries are desired (if not, no retries will be attempted).
  • Any collection or iterable of the above (AbstractDict, AbstractString, AbstractVector{UInt8}, or IO) which will result in a "chunked" request body, where each iterated element will be sent as a separate chunk
  • a HTTP.Form, which will be serialized as the "multipart/form-data" content-type

The HTTP.Response struct contains:

  • status::Int16 e.g. 200
  • headers::Vector{Pair{String,String}} e.g. ["Server" => "Apache", "Content-Type" => "text/html"]
  • body::Vector{UInt8} or ::IO, the Response Body bytes or the io argument provided via the response_stream keyword argument

Functions HTTP.get, HTTP.put, HTTP.post and HTTP.head are defined as shorthand for HTTP.request("GET", ...), etc.

Supported optional keyword arguments:

  • query = nothing, a Pair or Dict of key => values to be included in the url
  • response_stream = nothing, a writeable IO stream or any IO-like type T for which write(T, AbstractVector{UInt8}) is defined. The response body will be written to this stream instead of returned as a Vector{UInt8}.
  • verbose = 0, set to 1 or 2 for increasingly verbose logging of the request and response process
  • connect_timeout = 30, close the connection after this many seconds if it is still attempting to connect. Use connect_timeout = 0 to disable.
  • pool = nothing, an HTTP.Pool object to use for managing the reuse of connections between requests. By default, a global pool is used, which is shared across all requests. To create a pool for a specific set of requests, use pool = HTTP.Pool(max::Int), where max controls the maximum number of concurrent connections allowed to be used for requests at a given time.
  • readtimeout = 0, abort a request after this many seconds. Will trigger retries if applicable. Use readtimeout = 0 to disable.
  • status_exception = true, throw HTTP.StatusError for response status >= 300.
  • Basic authentication is detected automatically from the provided url's userinfo (in the form scheme://user:password@host) and adds the Authorization: Basic header; this can be disabled by passing basicauth=false
  • canonicalize_headers = false, rewrite request and response headers in Canonical-Camel-Dash-Format.
  • proxy = proxyurl, pass request through a proxy given as a url; alternatively, the http_proxy, HTTP_PROXY, https_proxy, HTTPS_PROXY, and no_proxy environment variables are also detected/used; if set, they will be used automatically when making requests.
  • detect_content_type = false: if true and the request body is not a form or IO, it will be inspected and the "Content-Type" header will be set to the detected content type.
  • decompress = nothing, by default, decompress the response body if the response has a "Content-Encoding" header set to "gzip". If decompress=true, decompress the response body regardless of Content-Encoding header. If decompress=false, do not decompress the response body.
  • logerrors = false, if true, HTTP.StatusError, HTTP.TimeoutError, HTTP.IOError, and HTTP.ConnectError will be logged via @error as they happen, regardless of whether the request is then retried or not. Useful for debugging or monitoring requests where there's worry of certain errors happening but ignored because of retries.
  • logtag = nothing, if provided, will be used as the tag for error logging. Useful for debugging or monitoring requests.
  • observelayers = false, if true, enables the HTTP.observelayer to wrap each client-side "layer" to track the amount of time spent in each layer as a request is processed. This can be useful for debugging performance issues. Note that when retries or redirects happen, the time spent in each layer is cumulative, as noted by the [layer]_count. The metrics are stored in the Request.context dictionary, and can be accessed like HTTP.get(...).request.context

Retry arguments:

  • retry = true, retry idempotent requests in case of error.
  • retries = 4, number of times to retry.
  • retry_non_idempotent = false, retry non-idempotent requests too. e.g. POST.
  • retry_delays = ExponentialBackOff(n = retries), provide a custom ExponentialBackOff object to control the delay between retries.
  • retry_check = (s, ex, req, resp, resp_body) -> Bool, provide a custom function to control whether a retry should be attempted. The function should accept 5 arguments: the delay state, exception, request, response (an HTTP.Response object if a request was successfully made, otherwise nothing), and resp_body response body (which may be nothing if there is no response yet, otherwise a Vector{UInt8}), and return true if a retry should be attempted.

Redirect arguments:

  • redirect = true, follow 3xx redirect responses; i.e. additional requests will be made to the redirected location
  • redirect_limit = 3, maximum number of times a redirect will be followed
  • redirect_method = nothing, the method to use for the redirected request; by default, GET will be used, only responses with 307/308 will use the same original request method. Pass redirect_method=:same to pass the same method as the orginal request though note that some servers may not respond/accept the same method. It's also valid to pass the exact method to use as a string, like redirect_method="PUT".
  • forwardheaders = true, forward original headers on redirect.

SSL arguments:

  • require_ssl_verification = NetworkOptions.verify_host(host), pass MBEDTLS_SSL_VERIFY_REQUIRED to the mbed TLS library. "... peer must present a valid certificate, handshake is aborted if verification failed."
  • sslconfig = SSLConfig(require_ssl_verification)
  • socket_type_tls = MbedTLS.SSLContext, the type of socket to use for TLS connections. Defaults to MbedTLS.SSLContext. Also supported is passing socket_type_tls = OpenSSL.SSLStream. To change the global default, set HTTP.SOCKET_TYPE_TLS[] = OpenSSL.SSLStream.

Cookie arguments:

  • cookies::Union{Bool, Dict{<:AbstractString, <:AbstractString}} = true, enable cookies, or alternatively, pass a Dict{AbstractString, AbstractString} of name-value pairs to manually pass cookies in the request "Cookie" header
  • cookiejar::HTTP.CookieJar=HTTP.COOKIEJAR: threadsafe cookie jar struct for keeping track of cookies per host; a global cookie jar is used by default.

Request Body Examples

String body:

HTTP.request("POST", "http://httpbin.org/post", [], "post body data")

Stream body from file:

io = open("post_data.txt", "r")
HTTP.request("POST", "http://httpbin.org/post", [], io)

Generator body:

chunks = ("chunk$i" for i in 1:1000)
HTTP.request("POST", "http://httpbin.org/post", [], chunks)

Collection body:

chunks = [preamble_chunk, data_chunk, checksum(data_chunk)]
HTTP.request("POST", "http://httpbin.org/post", [], chunks)

open() do io body:

HTTP.open("POST", "http://httpbin.org/post") do io
    write(io, preamble_chunk)
    write(io, data_chunk)
    write(io, checksum(data_chunk))
end

Response Body Examples

String body:

r = HTTP.request("GET", "http://httpbin.org/get")
println(String(r.body))

Stream body to file:

io = open("get_data.txt", "w")
r = HTTP.request("GET", "http://httpbin.org/get", response_stream=io)
close(io)
println(read("get_data.txt"))

Stream body through buffer:

r = HTTP.get("http://httpbin.org/get", response_stream=IOBuffer())
println(String(take!(r.body)))

Stream body through open() do io:

r = HTTP.open("GET", "http://httpbin.org/stream/10") do io
   while !eof(io)
       println(String(readavailable(io)))
   end
end

HTTP.open("GET", "https://tinyurl.com/bach-cello-suite-1-ogg") do http
    n = 0
    r = startread(http)
    l = parse(Int, HTTP.header(r, "Content-Length"))
    open(`vlc -q --play-and-exit --intf dummy -`, "w") do vlc
        while !eof(http)
            bytes = readavailable(http)
            write(vlc, bytes)
            n += length(bytes)
            println("streamed $n-bytes $((100*n)÷l)%\u1b[1A")
        end
    end
end

Interfacing with RESTful JSON APIs:

using JSON
params = Dict("user"=>"RAO...tjN", "token"=>"NzU...Wnp", "message"=>"Hello!")
url = "http://api.domain.com/1/messages.json"
r = HTTP.post(url, body=JSON.json(params))
println(JSON.parse(String(r.body)))

Stream bodies from and to files:

in = open("foo.png", "r")
out = open("foo.jpg", "w")
HTTP.request("POST", "http://convert.com/png2jpg", [], in, response_stream=out)

Stream bodies through: open() do io:

HTTP.open("POST", "http://music.com/play") do io
    write(io, JSON.json([
        "auth" => "12345XXXX",
        "song_id" => 7,
    ]))
    r = startread(io)
    @show r.status
    while !eof(io)
        bytes = readavailable(io)
        play_audio(bytes)
    end
end
source
HTTP.getFunction
HTTP.get(url [, headers]; <keyword arguments>) -> HTTP.Response

Shorthand for HTTP.request("GET", ...). See HTTP.request.

source
HTTP.putFunction
HTTP.put(url, headers, body; <keyword arguments>) -> HTTP.Response

Shorthand for HTTP.request("PUT", ...). See HTTP.request.

source
HTTP.postFunction
HTTP.post(url, headers, body; <keyword arguments>) -> HTTP.Response

Shorthand for HTTP.request("POST", ...). See HTTP.request.

source
HTTP.headFunction
HTTP.head(url; <keyword arguments>) -> HTTP.Response

Shorthand for HTTP.request("HEAD", ...). See HTTP.request.

source
HTTP.patchFunction
HTTP.patch(url, headers, body; <keyword arguments>) -> HTTP.Response

Shorthand for HTTP.request("PATCH", ...). See HTTP.request.

source
HTTP.deleteFunction
HTTP.delete(url [, headers]; <keyword arguments>) -> HTTP.Response

Shorthand for HTTP.request("DELETE", ...). See HTTP.request.

source
HTTP.openFunction
WebSockets.open(handler, url; verbose=false, kw...)

Initiate a websocket connection to url (which should have schema like ws:// or wss://), and call handler(ws) with the websocket connection. Passing verbose=true or verbose=2 will enable debug logging for the life of the websocket connection. handler should be a function of the form f(ws) -> nothing, where ws is a WebSocket. Supported keyword arguments are the same as supported by HTTP.request. Typical websocket usage is:

WebSockets.open(url) do ws
    # iterate incoming websocket messages
    for msg in ws
        # send message back to server or do other logic here
        send(ws, msg)
    end
    # iteration ends when the websocket connection is closed by server or error
end
source
HTTP.open(method, url, [,headers]) do io
    write(io, body)
    [startread(io) -> HTTP.Response]
    while !eof(io)
        readavailable(io) -> AbstractVector{UInt8}
    end
end -> HTTP.Response

The HTTP.open API allows the request body to be written to (and/or the response body to be read from) an IO stream.

e.g. Streaming an audio file to the vlc player:

HTTP.open(:GET, "https://tinyurl.com/bach-cello-suite-1-ogg") do http
    open(`vlc -q --play-and-exit --intf dummy -`, "w") do vlc
        write(vlc, http)
    end
end
source
HTTP.downloadFunction
download(url, [local_path], [headers]; update_period=1, kw...)

Similar to Base.download this downloads a file, returning the filename. If the local_path:

  • is not provided, then it is saved in a temporary directory
  • if part to a directory is provided then it is saved into that directory
  • otherwise the local path is uses as the filename to save to.

When saving into a directory, the filename is determined (where possible), from the rules of the HTTP.

  • update_period controls how often (in seconds) to report the progress.
    • set to Inf to disable reporting
  • headers specifies headers to be used for the HTTP GET request
  • any additional keyword args (kw...) are passed on to the HTTP request.
source

Request/Response Objects

HTTP.Messages.RequestType
HTTP.Request(
    method, target, headers=[], body=nobody;
    version=v"1.1", url::URI=URI(), responsebody=nothing, parent=nothing, context=HTTP.Context()
)

Represents a HTTP Request Message with fields:

  • method::String RFC7230 3.1.1

  • target::String RFC7230 5.3

  • version::HTTPVersion RFC7230 2.6

  • headers::HTTP.Headers RFC7230 3.2

  • body::Union{Vector{UInt8}, IO} RFC7230 3.3

  • response, the Response to this Request

  • url::URI, the full URI of the request

  • parent, the Response (if any) that led to this request (e.g. in the case of a redirect). RFC7230 6.4

  • context, a Dict{Symbol, Any} store used by middleware to share state

source
HTTP.Streams.StreamType
Stream(::Request, ::IO)

Creates a HTTP.Stream that wraps an existing IO stream.

  • startwrite(::Stream) sends the Request headers to the IO stream.

  • write(::Stream, body) sends the body (or a chunk of the body).

  • closewrite(::Stream) sends the final 0 chunk (if needed) and calls closewrite on the IO stream.

  • startread(::Stream) calls startread on the IO stream then reads and parses the Response headers.

  • eof(::Stream) and readavailable(::Stream) parse the body from the IO stream.

  • closeread(::Stream) reads the trailers and calls closeread on the IO stream. When the IO stream is a HTTP.Connections.Connection, calling closeread releases the connection back to the connection pool for reuse. If a complete response has not been received, closeread throws EOFError.

source
HTTP.WebSockets.WebSocketType
WebSocket(io::HTTP.Connection, req, resp; client=true)

Representation of a websocket connection. Use WebSockets.open to open a websocket connection, passing a handler function f(ws) to send and receive messages. Use WebSockets.listen to listen for incoming websocket connections, passing a handler function f(ws) to send and receive messages.

Call send(ws, msg) to send a message; if msg is an AbstractString, a TEXT websocket message will be sent; if msg is an AbstractVector{UInt8}, a BINARY websocket message will be sent. Otherwise, msg should be an iterable of either AbstractString or AbstractVector{UInt8}, and a fragmented message will be sent, one frame for each iterated element.

Control frames can be sent by calling ping(ws[, data]), pong(ws[, data]), or close(ws[, body::WebSockets.CloseFrameBody]). Calling close will initiate the close sequence and close the underlying connection.

To receive messages, call receive(ws), which will block until a non-control, full message is received. PING messages will automatically be responded to when received. CLOSE messages will also be acknowledged and then a WebSocketError will be thrown with the WebSockets.CloseFrameBody payload, which may include a non-error CLOSE frame status code. WebSockets.isok(err) can be called to check if the CLOSE was normal or unexpected. Fragmented messages will be received until the final frame is received and the full concatenated payload can be returned. receive(ws) returns a Vector{UInt8} for BINARY messages, and a String for TEXT messages.

For convenience, WebSockets support the iteration protocol, where each iteration will receive a non-control message, with iteration terminating when the connection is closed. E.g.:

WebSockets.open(url) do ws
    for msg in ws
        # do cool stuff with msg
    end
end
source
HTTP.Messages.headerFunction
HTTP.header(::Message, key [, default=""]) -> String

Get header value for key (case-insensitive).

source
HTTP.Messages.hasheaderFunction
HTTP.hasheader(::Message, key) -> Bool

Does header value for key exist (case-insensitive)?

source
HTTP.hasheader(::Message, key, value) -> Bool

Does header for key match value (both case-insensitive)?

source
HTTP.Messages.headercontainsFunction
HTTP.headercontains(::Message, key, value) -> Bool

Does the header for key (interpreted as comma-separated list) contain value (both case-insensitive)?

source
HTTP.Messages.decodeFunction
HTTP.decode(r::Union{Request, Response}) -> Vector{UInt8}

For a gzip encoded request/response body, decompress it and return the decompressed body.

source

Request body types

HTTP.Forms.FormType
HTTP.Form(data; boundary=string(rand(UInt128), base=16))

Construct a request body for multipart/form-data encoding from data.

data must iterate key-value pairs (e.g. AbstractDict or Vector{Pair}) where the key/value of the iterator is the key/value of each mutipart boundary chunk. Files and other large data arguments can be provided as values as IO arguments: either an IOStream such as returned via open(file), or an IOBuffer for in-memory data.

For complete control over a multipart chunk's details, an HTTP.Multipart type is provided to support setting the filename, Content-Type, and Content-Transfer-Encoding.

Examples

data = Dict(
    "text" => "text data",
    # filename (cat.png) and content-type (image/png) inferred from the IOStream
    "file1" => open("cat.png"),
    # manully controlled chunk
    "file2" => HTTP.Multipart("dog.jpeg", open("mydog.jpg"), "image/jpeg"),
)
body = HTTP.Form(data)
headers = []
HTTP.post(url, headers, body)
source
HTTP.Forms.MultipartType
HTTP.Multipart(filename::String, data::IO, content_type=HTTP.sniff(data), content_transfer_encoding="")

A type to represent a single multipart upload chunk for a file. This type would be used as the value in a key-value pair when constructing a HTTP.Form for a request body (see example below). The data argument must be an IO type such as IOStream, or IOBuffer. The content_type and content_transfer_encoding arguments allow manual setting of these multipart headers. Content-Type will default to the result of the HTTP.sniff(data) mimetype detection algorithm, whereas Content-Transfer-Encoding will be left out if not specified.

Examples

body = HTTP.Form(Dict(
    "key" => HTTP.Multipart("File.txt", open("MyFile.txt"), "text/plain"),
))
headers = []
HTTP.post(url, headers, body)

Extended help

Filename SHOULD be included when the Multipart represents the contents of a file RFC7578 4.2

Content-Disposition set to "form-data" MUST be included with each Multipart. An additional "name" parameter MUST be included An optional "filename" parameter SHOULD be included if the contents of a file are sent This will be formatted such as: Content-Disposition: form-data; name="user"; filename="myfile.txt" RFC7578 4.2

Content-Type for each Multipart is optional, but SHOULD be included if the contents of a file are sent. RFC7578 4.4

Content-Transfer-Encoding for each Multipart is deprecated RFC7578 4.7

Other Content- header fields MUST be ignored RFC7578 4.8

source

Request exceptions

Request functions may throw the following exceptions:

HTTP.Exceptions.ConnectErrorType
HTTP.ConnectError

Raised when an error occurs while trying to establish a request connection to the remote server. To see the underlying error, see the error field.

source
HTTP.Exceptions.StatusErrorType
HTTP.StatusError

Raised when an HTTP.Response has a 4xx, 5xx or unrecognised status code.

Fields:

  • status::Int16, the response status code.
  • method::String, the request method.
  • target::String, the request target.
  • response, the HTTP.Response
source
HTTP.Exceptions.RequestErrorType
HTTP.RequestError

Raised when an error occurs while physically sending a request to the remote server or reading the response back. To see the underlying error, see the error field.

source

URIs

HTTP.jl uses the URIs.jl package for handling URIs. Some functionality from URIs.jl, relevant to HTTP.jl, are listed below:

URIs.URIType
URI(; scheme="", host="", port="", etc...)
URI(str) = parse(URI, str::String)

A type representing a URI (e.g. a URL). Can be constructed from distinct parts using the various supported keyword arguments, or from a string. The URI constructors will automatically escape any provided query arguments, typically provided as "key"=>"value"::Pair or Dict("key"=>"value"). For all other components, you need to manually percent encode them before passing them to the URI constructor. Note that multiple values for a single query key can provided like Dict("key"=>["value1", "value2"]), in which case the constructor will percent encode only the values you pass in as the query part.

When constructing a URI from a String, you need to ensure that the string is correctly percent encoded already.

The URI struct stores the complete URI in the uri::String field and the component parts in the following SubString fields:

  • scheme, e.g. "http" or "https"
  • userinfo, e.g. "username:password"
  • host e.g. "julialang.org"
  • port e.g. "80" or ""
  • path e.g "/"
  • query e.g. "Foo=1&Bar=2"
  • fragment

The queryparams(::URI) function returns a Dict containing the query.

Note that you manually need to percent decode the content of the individual component fields before you further use their content, as they are returned in percent-encoded form.

URIs.escapeuriFunction
escapeuri(x)

Apply URI percent-encoding to escape special characters in x.

URIs.unescapeuriFunction
unescapeuri(str)

Percent-decode a string according to the URI escaping rules.

URIs.splitpathFunction
URIs.splitpath(path|uri; rstrip_empty_segment=true)

Splits the path into component segments based on /, according to http://tools.ietf.org/html/rfc3986#section-3.3. Any fragment and query parts of the string are ignored if present.

A final empty path segment (trailing '/') is removed, if present. This is technically incompatible with the segment grammar of RFC3986, but it seems to be a common recommendation to make paths with and without a trailing slash equivalent. To preserve any final empty path segment, set rstrip_empty_segment=false.

Examples

julia> URIs.splitpath(URI("http://example.com/foo/bar?a=b&c=d"))
2-element Array{String,1}:
 "foo"
 "bar"

julia> URIs.splitpath("/foo/bar/")
2-element Array{String,1}:
 "foo"
 "bar"

Cookies

HTTP.Cookies.CookieType
Cookie()
Cookie(; kwargs...)
Cookie(name, value; kwargs...)

A Cookie represents an HTTP cookie as sent in the "Set-Cookie" header of an HTTP response or the Cookie header of an HTTP request. Supported fields (which can be set using keyword arguments) include:

  • name::String: name of the cookie
  • value::String: value of the cookie
  • path::String: applicable path for the cookie
  • domain::String: applicable domain for the cookie
  • expires::Dates.DateTime: when the cookie should expire
  • maxage::Int: maxage == 0 means no max age, maxage < 0 means delete cookie now, maxage > 0 means the # of seconds until expiration
  • secure::Bool: secure cookie attribute
  • httponly::Bool: httponly cookie attribute
  • hostonly::Bool: hostonly cookie attribute
  • samesite::Bool: SameSite cookie attribute

See IETF RFC 6265 for details.

The string representation of a cookie is generated by calling stringify(cookie; isrequest=true), where isrequest=true will only include the name=value pair for requests, and if false, will generate the "Set-Cookie" representation for a response header.

A Vector{Cookie} can be retrieved from a Request/Response object by calling Cookies.cookies(r).

A Cookie can be added to a Request/Response object by calling Cookies.addcookie!(r, cookie).

source
HTTP.Cookies.stringifyFunction
stringify(cookie::Cookie, isrequest=true)

Generate the string representation of a cookie. By default, isrequest=true, and only the name=value pair will be included in the cookie string. For isrequest=false, the other cookie attributes will be included, ;-separated, for use in a "Set-Cookie" header.

source
HTTP.Cookies.addcookie!Function
Cookies.addcookie!(r::Union{HTTP.Request, HTTP.Response}, c::Cookie)

Convenience function for adding a single cookie to a request or response object. For requests, the cookie will be stringified and concatenated to any existing "Cookie" header. For responses, an additional "Set-Cookie" header will be appended.

source
HTTP.Cookies.cookiesFunction
HTTP.cookies(r::Union{Request, Response}) -> Vector{Cookie}

Return a list of cookies, if any, parsed from the request "Cookie" or response "Set-Cookie" headers.

source

WebSockets

Sockets.sendMethod
send(ws::WebSocket, msg)

Send a message on a websocket connection. If msg is an AbstractString, a TEXT websocket message will be sent; if msg is an AbstractVector{UInt8}, a BINARY websocket message will be sent. Otherwise, msg should be an iterable of either AbstractString or AbstractVector{UInt8}, and a fragmented message will be sent, one frame for each iterated element.

Control frames can be sent by calling ping(ws[, data]), pong(ws[, data]), or close(ws[, body::WebSockets.CloseFrameBody]). Calling close will initiate the close sequence and close the underlying connection.

source
HTTP.WebSockets.receiveFunction
receive(ws::WebSocket) -> Union{String, Vector{UInt8}}

Receive a message from a websocket connection. Returns a String if the message was TEXT, or a Vector{UInt8} if the message was BINARY. If control frames (ping or pong) are received, they are handled automatically and a non-control message is waited for. If a CLOSE message is received, it is responded to and a WebSocketError is thrown with the WebSockets.CloseFrameBody as the error value. This error can be checked with WebSockets.isok(err) to see if the closing was "normal" or if an actual error occurred. For fragmented messages, the incoming frames will continue to be read until the final fragment is received. The bodies of each fragment are concatenated into the final message returned by receive. Note that WebSocket objects can be iterated, where each iteration yields a message until the connection is closed.

source
Missing docstring.

Missing docstring for HTTP.WebSockets.close(::HTTP.WebSockets.WebSocket, body). Check Documenter's build log for details.

HTTP.WebSockets.pingFunction
ping(ws, data=[])

Send a PING control frame on a websocket connection. data is an optional body to send with the message. PONG messages are automatically responded to when a PING message is received by a websocket connection.

source
HTTP.WebSockets.pongFunction
pong(ws, data=[])

Send a PONG control frame on a websocket connection. data is an optional body to send with the message. Note that PING messages are automatically responded to internally by the websocket connection with a corresponding PONG message, but in certain cases, a unidirectional PONG message can be used as a one-way heartbeat.

source
Base.iterateMethod
iterate(ws)

Continuously call receive(ws) on a WebSocket connection, with each iteration yielding a message until the connection is closed. E.g.

for msg in ws
    # do something with msg
end
source
HTTP.WebSockets.isokFunction
WebSockets.isok(x::WebSocketError) -> Bool

Returns true if the WebSocketError has a non-error status code. When calling receive(websocket), if a CLOSE frame is received, the CLOSE frame body is parsed and thrown inside the WebSocketError, but if the CLOSE frame has a non-error status code, it's safe to ignore the error and return from the WebSockets.open or WebSockets.listen calls without throwing.

source

Utilities

HTTP.Sniff.sniffFunction
HTTP.sniff(content::Union{Vector{UInt8}, String, IO}) => String (mimetype)

HTTP.sniff will look at the first 512 bytes of content to try and determine a valid mimetype. If a mimetype can't be determined appropriately, "application/octet-stream" is returned.

Supports JSON detection through the HTTP.isjson(content) function.

Examples

julia> HTTP.sniff("Hello world!!")
"text/plain; charset=utf-8"

julia> HTTP.sniff("<html><body>Hello world!!</body></html>")
"text/html; charset=utf-8"

julia> HTTP.sniff("{"a": -1.0}")
"application/json; charset=utf-8"
source
HTTP.StatusCodes.statustextFunction
statustext(::Int) -> String

String representation of a HTTP status code.

Examples

julia> statustext(200)
"OK"

julia> statustext(404)
"Not Found"
source

Server / Handlers

Core Server

HTTP.Servers.listenFunction
HTTP.listen(handler, host=Sockets.localhost, port=8081; kw...)
HTTP.listen(handler, port::Integer=8081; kw...)
HTTP.listen(handler, server::Base.IOServer; kw...)
HTTP.listen!(args...; kw...) -> HTTP.Server

Listen for HTTP connections and execute the handler function for each request. Listening details can be passed as host/port pair, a single port (host will default to localhost), or an already listening server object, as returned from Sockets.listen. To open up a server to external requests, the host argument is typically "0.0.0.0".

The HTTP.listen! form is non-blocking and returns an HTTP.Server object which can be wait(server)ed on manually, or close(server)ed to gracefully shut down the server. Calling HTTP.forceclose(server) will immediately force close the server and all active connections. HTTP.listen will block on the server listening loop until interrupted or and an irrecoverable error occurs.

The handler function should be of the form f(::HTTP.Stream)::Nothing, and should at the minimum set a status via setstatus() and call startwrite() either explicitly or implicitly by writing out a response via write(). Failure to do this will result in an HTTP 500 error being transmitted to the client.

Optional keyword arguments:

  • sslconfig=nothing, Provide an MbedTLS.SSLConfig object to handle ssl connections. Pass sslconfig=MbedTLS.SSLConfig(false) to disable ssl verification (useful for testing). Construct a custom SSLConfig object with MbedTLS.SSLConfig(certfile, keyfile).
  • tcpisvalid = tcp->true, function f(::TCPSocket)::Bool to check if accepted connections are valid before processing requests. e.g. to do source IP filtering.
  • readtimeout::Int=0, close the connection if no data is received for this many seconds. Use readtimeout = 0 to disable.
  • reuseaddr::Bool=false, allow multiple servers to listen on the same port. Not supported on some OS platforms. Can check HTTP.Servers.supportsreuseaddr().
  • server::Base.IOServer=nothing, provide an IOServer object to listen on; allows manually closing or configuring the server socket.
  • verbose::Bool=false, log connection information to stdout.
  • access_log::Function, function for formatting access log messages. The function should accept two arguments, io::IO to which the messages should be written, and http::HTTP.Stream which can be used to query information from. See also @logfmt_str.
  • on_shutdown::Union{Function, Vector{<:Function}, Nothing}=nothing, one or more functions to be run if the server is closed (for example by an InterruptException). Note, shutdown function(s) will not run if an IOServer object is supplied to the server keyword argument and closed by close(server).

e.g.

# start a blocking server
HTTP.listen("127.0.0.1", 8081) do http
    HTTP.setheader(http, "Content-Type" => "text/html")
    write(http, "target uri: $(http.message.target)<BR>")
    write(http, "request body:<BR><PRE>")
    write(http, read(http))
    write(http, "</PRE>")
    return
end

# non-blocking server
server = HTTP.listen!("127.0.0.1", 8081) do http
    @show http.message
    @show HTTP.header(http, "Content-Type")
    while !eof(http)
        println("body data: ", String(readavailable(http)))
    end
    HTTP.setstatus(http, 404)
    HTTP.setheader(http, "Foo-Header" => "bar")
    startwrite(http)
    write(http, "response body")
    write(http, "more response body")
end
# can gracefully close server manually
close(server)

To run the following HTTP chat example, open two Julia REPL windows and paste the example code into both of them. Then in one window run chat_server() and in the other run chat_client(), then type hello and press return. Whatever you type on the client will be displayed on the server and vis-versa.

using HTTP

function chat(io::HTTP.Stream)
    Threads.@spawn while !eof(io)
        write(stdout, readavailable(io), "\n")
    end
    while isopen(io)
        write(io, readline(stdin))
    end
end

chat_server() = HTTP.listen("127.0.0.1", 8087) do io
    write(io, "HTTP.jl Chat Server. Welcome!")
    chat(io)
end

chat_client() = HTTP.open("POST", "http://127.0.0.1:8087") do io
    chat(io)
end
source
HTTP.Handlers.serveFunction
HTTP.serve(handler, host=Sockets.localhost, port=8081; kw...)
HTTP.serve(handler, port::Integer=8081; kw...)
HTTP.serve(handler, server::Base.IOServer; kw...)
HTTP.serve!(args...; kw...) -> HTTP.Server

Listen for HTTP connections and execute the handler function for each request. Listening details can be passed as host/port pair, a single port (host will default to localhost), or an already listening server object, as returned from Sockets.listen. To open up a server to external requests, the host argument is typically "0.0.0.0".

The HTTP.serve! form is non-blocking and returns an HTTP.Server object which can be wait(server)ed on manually, or close(server)ed to gracefully shut down the server. Calling HTTP.forceclose(server) will immediately force close the server and all active connections. HTTP.serve will block on the server listening loop until interrupted or and an irrecoverable error occurs.

The handler function should be of the form f(req::HTTP.Request)::HTTP.Response. Alternatively, passing stream=true requires the handler to be of the form f(stream::HTTP.Stream) -> Nothing. See HTTP.Router for details on using it as a request handler.

Optional keyword arguments:

  • sslconfig=nothing, Provide an MbedTLS.SSLConfig object to handle ssl connections. Pass sslconfig=MbedTLS.SSLConfig(false) to disable ssl verification (useful for testing). Construct a custom SSLConfig object with MbedTLS.SSLConfig(certfile, keyfile).
  • tcpisvalid = tcp->true, function f(::TCPSocket)::Bool to check if accepted connections are valid before processing requests. e.g. to do source IP filtering.
  • readtimeout::Int=0, close the connection if no data is received for this many seconds. Use readtimeout = 0 to disable.
  • reuseaddr::Bool=false, allow multiple servers to listen on the same port. Not supported on some OS platforms. Can check HTTP.Servers.supportsreuseaddr().
  • server::Base.IOServer=nothing, provide an IOServer object to listen on; allows manually closing or configuring the server socket.
  • verbose::Bool=false, log connection information to stdout.
  • access_log::Function, function for formatting access log messages. The function should accept two arguments, io::IO to which the messages should be written, and http::HTTP.Stream which can be used to query information from. See also @logfmt_str.
  • on_shutdown::Union{Function, Vector{<:Function}, Nothing}=nothing, one or more functions to be run if the server is closed (for example by an InterruptException). Note, shutdown function(s) will not run if an IOServer object is supplied to the server keyword argument and closed by close(server).
# start a blocking echo server
HTTP.serve("127.0.0.1", 8081) do req
    return HTTP.Response(200, req.body)
end

# non-blocking server
server = HTTP.serve!(8081) do req
    return HTTP.Response(200, "response body")
end
# can gracefully close server manually
close(server)
source
HTTP.WebSockets.listenFunction
WebSockets.listen(handler, host, port; verbose=false, kw...)
WebSockets.listen!(handler, host, port; verbose=false, kw...) -> HTTP.Server

Listen for websocket connections on host and port, and call handler(ws), which should be a function taking a single WebSocket argument. Keyword arguments kw... are the same as supported by HTTP.listen. Typical usage is like:

WebSockets.listen(host, port) do ws
    # iterate incoming websocket messages
    for msg in ws
        # send message back to client or do other logic here
        send(ws, msg)
    end
    # iteration ends when the websocket connection is closed by client or error
end
source

Middleware / Handlers

HTTP.Handlers.HandlerType
Handler

Abstract type for the handler interface that exists for documentation purposes. A Handler is any function of the form f(req::HTTP.Request) -> HTTP.Response. There is no requirement to subtype Handler and users should not rely on or dispatch on Handler. A Handler function f can be passed to HTTP.serve wherein a server will pass each incoming request to f to be handled and a response to be returned. Handler functions are also the inputs to Middleware functions which are functions of the form f(::Handler) -> Handler, i.e. they take a Handler function as input, and return a "modified" or enhanced Handler function.

For advanced cases, a Handler function can also be of the form f(stream::HTTP.Stream) -> Nothing. In this case, the server would be run like HTTP.serve(f, ...; stream=true). For this use-case, the handler function reads the request and writes the response to the stream directly. Note that any middleware used with a stream handler also needs to be of the form f(stream_handler) -> stream_handler, i.e. it needs to accept a stream Handler function and return a stream Handler function.

source
HTTP.Handlers.MiddlewareType
Middleware

Abstract type for the middleware interface that exists for documentation purposes. A Middleware is any function of the form f(::Handler) -> Handler (ref: Handler). There is no requirement to subtype Middleware and users should not rely on or dispatch on the Middleware type. While HTTP.serve(f, ...) requires a handler function f to be passed, middleware can be "stacked" to create a chain of functions that are called in sequence, like HTTP.serve(base_handler |> cookie_middleware |> auth_middlware, ...), where the base_handler Handler function is passed to cookie_middleware, which takes the handler and returns a "modified" handler (that parses and stores cookies). This "modified" handler is then an input to the auth_middlware, which further enhances/modifies the handler.

source
HTTP.Handlers.streamhandlerFunction
streamhandler(request_handler) -> stream handler

Middleware that takes a request handler and returns a stream handler. Used by default in HTTP.serve to take the user-provided request handler and process the Stream from HTTP.listen and pass the parsed Request to the handler.

Is included by default in HTTP.serve as the base "middleware" when stream=false is passed.

source
HTTP.Handlers.RouterType
HTTP.Router(_404, _405, middleware=nothing)

Define a router object that maps incoming requests by path to registered routes and associated handlers. Paths can be registered using HTTP.register!. The router object itself is a "request handler" that can be called like:

r = HTTP.Router()
resp = r(request)

Which will inspect the request, find the matching, registered handler from the url, and pass the request on to be handled further.

See HTTP.register! for additional information on registering handlers based on routes.

If a request doesn't have a matching, registered handler, the _404 handler is called which, by default, returns a HTTP.Response(404). If a route matches the path, but not the method/verb (e.g. there's a registerd route for "GET /api", but the request is "POST /api"), then the _405 handler is called, which by default returns HTTP.Response(405) (method not allowed).

A middleware (Middleware) can optionally be provided as well, which will be called after the router has matched the request to a route, but before the route's handler is called. This provides a "hook" for matched routes that can be helpful for metric tracking, logging, etc. Note that the middleware is only called if the route is matched; for the 404 and 405 cases, users should wrap those handlers in the middleware manually.

source
HTTP.Handlers.register!Function
HTTP.register!(r::Router, method, path, handler)
HTTP.register!(r::Router, path, handler)

Register a handler function that should be called when an incoming request matches path and the optionally provided method (if not provided, any method is allowed). Can be used to dynamically register routes. When a registered route is matched, the original route string is stored in the request.context[:route] variable. The following path types are allowed for matching:

  • /api/widgets: exact match of static strings
  • /api/*/owner: single * to wildcard match anything for a single segment
  • /api/widget/{id}: Define a path variable id that matches any valued provided for this segment; path variables are available in the request context like HTTP.getparams(req)["id"]
  • /api/widget/{id:[0-9]+}: Define a path variable id that does a regex match for integers for this segment
  • /api/**: double wildcard matches any number of trailing segments in the request path; the double wildcard must be the last segment in the path
source
HTTP.Handlers.getparamFunction
HTTP.getparam(req, name, default=nothing) -> String

Retrieve a matched path parameter with name name from request context. If a path was registered with a router via HTTP.register! like "/api/widget/{id}", then the path parameter can be retrieved like `id = HTTP.getparam(req, "id").

source
HTTP.Handlers.getparamsFunction
HTTP.getparams(req) -> Dict{String, String}

Retrieve any matched path parameters from the request context. If a path was registered with a router via HTTP.register! like "/api/widget/{id}", then the path parameters are available in the request context and can be retrieved like id = HTTP.getparams(req)["id"].

source
HTTP.Handlers.cookie_middlewareFunction
HTTP.Handlers.cookie_middleware(handler) -> handler

Middleware that parses and stores any cookies in the incoming request in the request context. Cookies can then be retrieved by calling HTTP.getcookies(req) in subsequent middlewares/handlers.

source
HTTP.@logfmt_strMacro
logfmt"..."

Parse an NGINX-style log format string and return a function mapping (io::IO, http::HTTP.Stream) -> body suitable for passing to HTTP.listen using the access_log keyword argument.

The following variables are currently supported:

  • $http_name: arbitrary request header (with - replaced with _, e.g. http_user_agent)
  • $sent_http_name: arbitrary response header (with - replaced with _)
  • $request: the request line, e.g. GET /index.html HTTP/1.1
  • $request_method: the request method
  • $request_uri: the request URI
  • $remote_addr: client address
  • $remote_port: client port
  • $remote_user: user name supplied with the Basic authentication
  • $server_protocol: server protocol
  • $time_iso8601: local time in ISO8601 format
  • $time_local: local time in Common Log Format
  • $status: response status code
  • $body_bytes_sent: number of bytes in response body

Examples

logfmt"[$time_iso8601] \"$request\" $status" # [2021-05-01T12:34:40+0100] "GET /index.html HTTP/1.1" 200

logfmt"$remote_addr \"$http_user_agent\"" # 127.0.0.1 "curl/7.47.0"
source

Advanced Topics

Messages Interface

HTTP.Messages.readheadersFunction
readheaders(::IO, ::Message)

Read headers (and startline) from an IO stream into a Message struct. Throw EOFError if input is incomplete.

source
HTTP.HeadersRequest.setuseragent!Function
setuseragent!(x::Union{String, Nothing})

Set the default User-Agent string to be used in each HTTP request. Can be manually overridden by passing an explicit User-Agent header. Setting nothing will prevent the default User-Agent header from being passed.

source
HTTP.Messages.writeheadersFunction
writeheaders(::IO, ::Message)

Write Message start line and a line for each "name: value" pair and a trailing blank line.

source
Base.writeMethod
write(::IO, ::Message)

Write start line, headers and body of HTTP Message.

source
HTTP.Streams.isabortedFunction
isaborted(::Stream{<:Response})

Has the server signaled that it does not wish to receive the message body?

"If [the response] indicates the server does not wish to receive the message body and is closing the connection, the client SHOULD immediately cease transmitting the body and close the connection." RFC7230, 6.5

source
HTTP.Cookies.CookieJarType
CookieJar()

A thread-safe object for storing cookies returned in "Set-Cookie" response headers. Keyed by appropriate host from the original request made. Can be created manually and passed like HTTP.get(url; cookiejar=mycookiejar) to avoid using the default global CookieJar. The 2 main functions for interacting with a CookieJar are Cookies.getcookies!, which returns a Vector{Cookie} for a given url (and will remove expired cookies from the jar), and Cookies.setcookies!, which will store "Set-Cookie" response headers in the cookie jar.

source
HTTP.Cookies.getcookies!Function
Cookies.getcookies!(jar::CookieJar, url::URI)

Retrieve valid Cookies from the CookieJar according to the provided url. Cookies will be returned as a Vector{Cookie}. Only cookies for http or https scheme in the url will be returned. Cookies will be checked according to the canonical host of the url and any cookie max age or expiration will be accounted for. Expired cookies will not be returned and will be removed from the cookie jar.

source
HTTP.Cookies.setcookies!Function
Cookies.setcookies!(jar::CookieJar, url::URI, headers::Headers)

Identify, "Set-Cookie" response headers from headers, parse the Cookies, and store valid entries in the cookie jar according to the canonical host in url. Cookies can be retrieved from the jar via Cookies.getcookies!.

source

Client-side Middleware (Layers)

HTTP.LayerType
Layer

Abstract type to represent a client-side middleware that exists for documentation purposes. A layer is any function of the form f(::Handler) -> Handler, where Handler is a function of the form f(::Request) -> Response. Note that the Handler definition is from the server-side documentation, and is "hard-coded" on the client side. It may also be apparent that a Layer is the same as the Middleware interface from server-side, which is true, but we define Layer to clarify the client-side distinction and its unique usage. Custom layers can be deployed in one of two ways:

  • HTTP.@client: Create a custom "client" with shorthand verb definitions, but which include custom layers; only these new verb methods will use the custom layers.
  • HTTP.pushlayer!/HTTP.poplayer!: Allows globally adding and removing layers from the default HTTP.jl layer stack; all http requests will then use the custom layers

Quick Examples

module Auth

using HTTP

function auth_layer(handler)
    # returns a `Handler` function; check for a custom keyword arg `authcreds` that
    # a user would pass like `HTTP.get(...; authcreds=creds)`.
    # We also accept trailing keyword args `kw...` and pass them along later.
    return function(req; authcreds=nothing, kw...)
        # only apply the auth layer if the user passed `authcreds`
        if authcreds !== nothing
            # we add a custom header with stringified auth creds
            HTTP.setheader(req, "X-Auth-Creds" => string(authcreds))
        end
        # pass the request along to the next layer by calling `auth_layer` arg `handler`
        # also pass along the trailing keyword args `kw...`
        return handler(req; kw...)
    end
end

# Create a new client with the auth layer added
HTTP.@client [auth_layer]

end # module

# Can now use custom client like:
Auth.get(url; authcreds=creds) # performs GET request with auth_layer layer included

# Or can include layer globally in all HTTP.jl requests
HTTP.pushlayer!(Auth.auth_layer)

# Now can use normal HTTP.jl methods and auth_layer will be included
HTTP.get(url; authcreds=creds)
source
HTTP.@clientMacro
HTTP.@client requestlayers
HTTP.@client requestlayers streamlayers
HTTP.@client (first=requestlayers, last=requestlayers) (first=streamlayers, last=streamlayers)

Convenience macro for creating a custom HTTP.jl client that will include custom layers when performing requests. It's common to want to define a custom Layer to enhance a specific category of requests, such as custom authentcation for a web API. Instead of affecting the global HTTP.jl request stack via HTTP.pushlayer!, a custom wrapper client can be defined with convenient shorthand methods. See Layer for an example of defining a custom layer and creating a new client that includes the layer.

Custom layer arguments can be provided as a collection of request or stream-based layers; alternatively, a NamedTuple with keys first and last can be provided with values being a collection of layers. The NamedTuple form provides finer control over the order in which the layers will be included in the default http layer stack: first request layers are executed before all other layers, last request layers are executed right before all stream layers, and similarly for stream layers.

An empty collection can always be passed for request or stream layers when not needed.

One use case for custom clients is to control the value of standard HTTP.request keyword arguments. This can be achieved by passing a (first=[defaultkeywordlayer],) where defaultkeywordlayer is defined like:

defaultkeywordlayer(handler) = (req; kw...) -> handler(req; retry=false, redirect=false, kw...)

This client-side layer is basically a no-op as it doesn't modify the request at all, except that it hard-codes the value of the retry and redirect keyword arguments. When we pass this layer as (first=[defaultkeywordlayer],) this ensures this layer will be executed before all other layers, effectively over-writing the default and any user-provided keyword arguments for retry or redirect.

source
HTTP.pushlayer!Function
HTTP.pushlayer!(layer; request=true)

Push a layer onto the stack of layers that will be applied to all requests. The "layer" is expected to be a function that takes and returns a Handler function. See Layer for more details. If request=false, the layer is expected to take and return a "stream" handler function. The custom layer will be put on the top of the stack, so it will be the first layer executed. To add a layer at the bottom of the stack, see HTTP.pushfirstlayer!.

source
HTTP.pushfirstlayer!Function
HTTP.pushfirstlayer!(layer; request=true)

Push a layer to the start of the stack of layers that will be applied to all requests. The "layer" is expected to be a function that takes and returns a Handler function. See Layer for more details. If request=false, the layer is expected to take and return a "stream" handler function. The custom layer will be put on the bottom of the stack, so it will be the last layer executed. To add a layer at the top of the stack, see HTTP.pushlayer!.

source
HTTP.poplayer!Function
HTTP.poplayer!(; request=true)

Inverse of HTTP.pushlayer!, removes the top layer of the global HTTP.jl layer stack. Can be used to "cleanup" after a custom layer has been added. If request=false, will remove the top "stream" layer as opposed to top "request" layer.

source
HTTP.popfirstlayer!Function
HTTP.popfirstlayer!(; request=true)

Inverse of HTTP.pushfirstlayer!, removes the bottom layer of the global HTTP.jl layer stack. Can be used to "cleanup" after a custom layer has been added. If request=false, will remove the bottom "stream" layer as opposed to bottom "request" layer.

source
HTTP.CookieRequest.cookielayerFunction
cookielayer(handler) -> handler

Check for host-appropriate cookies to include in the outgoing request from the cookiejar keyword argument (by default, a global cookiejar is used). Store "Set-Cookie" cookies from the response headers.

source
HTTP.RetryRequest.retrylayerFunction
retrylayer(handler) -> handler

Retry the request if it throws a recoverable exception.

Base.retry and Base.ExponentialBackOff implement a randomised exponentially increasing delay is introduced between attempts to avoid exacerbating network congestion.

By default, requests that have a retryable body, where the request wasn't written or is idempotent will be retried. If the request is made and a response is received with a status code of 403, 408, 409, 429, or 5xx, the request will be retried.

retries controls the # of total retries that will be attempted.

retry_check allows passing a custom retry check in the case where the default retry check wouldn't retry, if retry_check returns true, then the request will be retried anyway.

source
HTTP.ConnectionRequest.connectionlayerFunction
connectionlayer(handler) -> handler

Retrieve an IO connection from the Connections.

Close the connection if the request throws an exception. Otherwise leave it open so that it can be reused.

source
HTTP.StreamRequest.streamlayerFunction
streamlayer(stream) -> HTTP.Response

Create a Stream to send a Request and body to an IO stream and read the response.

Send the Request body in a background task and begins reading the response immediately so that the transmission can be aborted if the Response status indicates that the server does not wish to receive the message body. RFC7230 6.5.

source

Raw Request Connection

HTTP.openrawFunction
HTTP.openraw(method, url, [, headers])::Tuple{Connection, Response}

Open a raw socket that is unmanaged by HTTP.jl. Useful for doing HTTP upgrades to other protocols. Any bytes of the body read from the socket when reading headers, is returned as excess bytes in the last tuple argument.

Example of a WebSocket upgrade:

headers = Dict(
    "Upgrade" => "websocket",
    "Connection" => "Upgrade",
    "Sec-WebSocket-Key" => "dGhlIHNhbXBsZSBub25jZQ==",
    "Sec-WebSocket-Version" => "13")

socket, response, excess = HTTP.openraw("GET", "ws://echo.websocket.org", headers)

# Write a WebSocket frame
frame = UInt8[0x81, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58]
write(socket, frame)
source
HTTP.Connections.ConnectionType
Connection

A Sockets.TCPSocket, MbedTLS.SSLContext or OpenSSL.SSLStream connection to a HTTP host and port.

Fields:

  • host::String
  • port::String, exactly as specified in the URI (i.e. may be empty).
  • idle_timeout, No. of seconds to maintain connection after last request/response.
  • require_ssl_verification, whether ssl verification is required for an ssl connection
  • keepalive, whether the tcp socket should have keepalive enabled
  • peerip, remote IP adress (used for debug/log messages).
  • peerport, remote TCP port number (used for debug/log messages).
  • localport, local TCP port number (used for debug messages).
  • io::T, the Sockets.TCPSocket, MbedTLS.SSLContext or OpenSSL.SSLStream.
  • clientconnection::Bool, whether the Connection was created from client code (as opposed to server code)
  • buffer::IOBuffer, left over bytes read from the connection after the end of a response header (or chunksize). These bytes are usually part of the response body.
  • timestamp, time data was last received.
  • readable, whether the Connection object is readable
  • writable, whether the Connection object is writable
source

Parser Interface

HTTP.Parsers.parse_status_line!Function

Parse HTTP response-line bytes and set the status and version fields of response. Return a SubString containing the header-field lines.

source
HTTP.Parsers.parse_request_line!Function

Parse HTTP request-line bytes and set the method, target and version fields of request. Return a SubString containing the header-field lines.

source