mist
Types
Re-exported type that represents the default Request
body type. See
mist.read_body
to convert this type into a BitString
. The Connection
also holds some additional information about the request. Currently, the
only useful field is client_ip
which is a Result
with a tuple of
integers representing the IPv4 address.
pub type Connection =
@internal Connection
Potential errors when opening a file to send. This list is currently not exhaustive with POSIX errors.
pub type FileError {
IsDir
NoAccess
NoEntry
UnknownFileError
}
Constructors
-
IsDir
-
NoAccess
-
NoEntry
-
UnknownFileError
When accessing client information, these are the possible shapes of the IP addresses. A best effort will be made to determine whether IPv4 is most relevant.
pub type IpAddress {
IpV4(Int, Int, Int, Int)
IpV6(Int, Int, Int, Int, Int, Int, Int, Int)
}
Constructors
-
IpV4(Int, Int, Int, Int)
-
IpV6(Int, Int, Int, Int, Int, Int, Int, Int)
The possible errors from reading the request body. If the size is larger
than the provided value, ExcessBody
is returned. If there is an error
reading the body from the socket or the body is malformed (i.e a chunked
request with invalid sizes), MalformedBody
is returned.
pub type ReadError {
ExcessBody
MalformedBody
}
Constructors
-
ExcessBody
-
MalformedBody
The response body type. This allows mist
to handle these different cases
for you. Bytes
is the regular data return. Websocket
will upgrade the
socket to websockets, but should not be used directly. See the
mist.upgrade
function for usage. Chunked
will use
Transfer-Encoding: chunked
to send an iterator in chunks. File
will use
Erlang’s sendfile
to more efficiently return a file to the client.
pub type ResponseData {
Websocket(process.Selector(process.Down))
Bytes(bytes_tree.BytesTree)
Chunked(yielder.Yielder(bytes_tree.BytesTree))
File(
descriptor: @internal FileDescriptor,
offset: Int,
length: Int,
)
ServerSentEvents(process.Selector(process.Down))
}
Constructors
-
Websocket(process.Selector(process.Down))
-
Bytes(bytes_tree.BytesTree)
-
Chunked(yielder.Yielder(bytes_tree.BytesTree))
-
File( descriptor: @internal FileDescriptor, offset: Int, length: Int, )
See
mist.send_file
to use this response type. -
ServerSentEvents(process.Selector(process.Down))
pub opaque type SSEConnection
pub type WebsocketConnection =
@internal WebsocketConnection
These are the types of messages that a websocket handler may receive.
pub type WebsocketMessage(custom) {
Text(String)
Binary(BitArray)
Closed
Shutdown
Custom(custom)
}
Constructors
-
Text(String)
-
Binary(BitArray)
-
Closed
-
Shutdown
-
Custom(custom)
Values
pub fn after_start(
builder: Builder(in, out),
after_start: fn(Int, http.Scheme, IpAddress) -> Nil,
) -> Builder(in, out)
Override the default function to be called after the service starts. The default is to log a message with the listening port.
pub fn bind(
builder: Builder(in, out),
interface: String,
) -> Builder(in, out)
Specify an interface to listen on. This is a string that can have the following values: “localhost”, a valid IPv4 address (i.e. “127.0.0.1”), or a valid IPv6 address (i.e. “::1”). An invalid value will cause the application to crash.
pub fn event(data: string_tree.StringTree) -> SSEEvent
pub fn get_client_info(
conn: @internal Connection,
) -> Result(ConnectionInfo, Nil)
Tries to get the IP address and port of a connected client.
pub fn ip_address_to_string(address: IpAddress) -> String
Convenience function for printing the IpAddress
type. It will convert the
IPv6 loopback to the short-hand ::1
.
pub fn new(
handler: fn(request.Request(in)) -> response.Response(out),
) -> Builder(in, out)
Create a new mist
handler with a given function. The default port is
4000.
pub fn port(
builder: Builder(in, out),
port: Int,
) -> Builder(in, out)
Assign a different listening port to the service.
pub fn read_body(
req: request.Request(@internal Connection),
max_body_limit max_body_limit: Int,
) -> Result(request.Request(BitArray), ReadError)
The request body is not pulled from the socket until requested. The
content-length
header is used to determine whether the socket is read
from or not. The read may also fail, and a ReadError
is raised.
pub fn read_request_body(
builder: Builder(BitArray, out),
bytes_limit bytes_limit: Int,
failure_response failure_response: response.Response(out),
) -> Builder(@internal Connection, out)
This function allows for implicitly reading the body of requests up
to a given size. If the size is too large, or the read fails, the provided
failure_response
will be sent back as the response.
pub fn send_binary_frame(
connection: @internal WebsocketConnection,
frame: BitArray,
) -> Result(Nil, socket.SocketReason)
Sends a binary frame across the websocket.
pub fn send_event(
conn: SSEConnection,
event: SSEEvent,
) -> Result(Nil, Nil)
pub fn send_file(
path: String,
offset offset: Int,
limit limit: option.Option(Int),
) -> Result(ResponseData, FileError)
To respond with a file using Erlang’s sendfile
, use this function
with the specified offset and limit (optional). It will attempt to open the
file for reading, get its file size, and then send the file. If the read
errors, this will return the relevant FileError
. Generally, this will be
more memory efficient than manually doing this process with mist.Bytes
.
pub fn send_text_frame(
connection: @internal WebsocketConnection,
frame: String,
) -> Result(Nil, socket.SocketReason)
Sends a text frame across the websocket.
pub fn server_sent_events(
request req: request.Request(@internal Connection),
initial_response resp: response.Response(discard),
init init: fn(process.Subject(message)) -> Result(
actor.Initialised(state, message, data),
String,
),
loop loop: fn(state, message, SSEConnection) -> actor.Next(
state,
message,
),
) -> response.Response(ResponseData)
Sets up the connection for server-sent events. The initial response provided
here will have its headers included in the SSE setup. The body is discarded.
The init
and loop
parameters follow the same shape as the
gleam/otp/actor
module.
NOTE: There is no proper way within the spec for the server to “close” the SSE connection. There are ways around it.
See: examples/eventz
for a sample usage.
pub fn start(
builder: Builder(@internal Connection, ResponseData),
) -> Result(
actor.Started(static_supervisor.Supervisor),
actor.StartError,
)
Start a mist
service with the provided builder.
pub fn stop_abnormal(reason: String) -> Next(state, user_message)
pub fn stream(
req: request.Request(@internal Connection),
) -> Result(fn(Int) -> Result(Chunk, ReadError), ReadError)
Rather than explicitly reading either the whole body (optionally up to
N
bytes), this function allows you to consume a stream of the request
body. Any errors reading the body will propagate out, or Chunk
s will be
emitted. This provides a consume
method to attempt to grab the next
size
chunk from the socket.
pub fn supervised(
builder: Builder(@internal Connection, ResponseData),
) -> supervision.ChildSpecification(static_supervisor.Supervisor)
Start the mist
supervisor as a child of a supervision tree.
pub fn websocket(
request request: request.Request(@internal Connection),
handler handler: fn(
state,
WebsocketMessage(message),
@internal WebsocketConnection,
) -> Next(state, message),
on_init on_init: fn(@internal WebsocketConnection) -> #(
state,
option.Option(process.Selector(message)),
),
on_close on_close: fn(state) -> Nil,
) -> response.Response(ResponseData)
Upgrade a request to handle websockets. If the request is malformed, or the websocket process fails to initialize, an empty 400 response will be sent to the client.
The on_init
method will be called when the actual WebSocket process
is started, and the return value is the initial state and an optional
selector for receiving user messages.
The on_close
method is called when the WebSocket process shuts down
for any reason, valid or otherwise.
pub fn with_ipv6(builder: Builder(in, out)) -> Builder(in, out)
By default, mist
will listen on localhost
over IPv4. If you specify an
IPv4 address to bind to, it will still only serve over IPv4. Calling this
function will listen on both IPv4 and IPv6 for the given interface. If it is
not supported, your application will crash. If you provide an IPv6 address
to mist.bind
, this function will have no effect.
pub fn with_selector(
next: Next(state, user_message),
selector: process.Selector(user_message),
) -> Next(state, user_message)