ReqWebSocket (req_web_socket v0.1.2)

View Source

Req plugin for establishing WebSocket connections, using Mint.WebSocket. See attach/2 for supported options.

Examples

resp =
  Req.new()
  |> ReqWebSocket.attach()
  |> Req.get!(into: :self, url: "wss://echo.websocket.org/")

message = receive do message -> message end
{:ok, resp, [text: _]} = ReqWebSocket.parse_message(resp, message)

{:ok, resp} = ReqWebSocket.send_frame(resp, :ping)

message = receive do message -> message end
{:ok, resp, [pong: ""]} = ReqWebSocket.parse_message(resp, message)

Summary

Functions

Adds the plugin to the Req.Request struct. Since this plugin replaces the adapter that is used, not all of the options supported by Req.new/1 are applicable, this also means there is no connection pooling. This plugin does not add any additional options beyond what Req itself provides.

Closes WebSocket connection.

Attempts to parse message into WebSocket frames, if the given message is not from the connection's socket, this function returns :unknown.

Encodes frame and sends encoded data on the established WebSocket connection.

Encodes frames and sends encoded data on an established WebSocket connection. See send_frame/2 for supported frame types.

Functions

attach(request, options \\ [])

@spec attach(
  Req.Request.t(),
  keyword()
) :: Req.Request.t()

Adds the plugin to the Req.Request struct. Since this plugin replaces the adapter that is used, not all of the options supported by Req.new/1 are applicable, this also means there is no connection pooling. This plugin does not add any additional options beyond what Req itself provides.

Supported Options

Basic request options:

  • :url - the request URL. This plugin will only replace the adapter if the URL scheme is wss or ws, otherwise this plugin will have no affect on the request.

  • :headers - the request headers as a {key, value} enumerable (e.g. map, keyword list).

    The header names should be downcased.

    The headers are automatically encoded using these rules:

    • atom header names are turned into strings, replacing _ with -. For example, :user_agent becomes "user-agent".

    • string header names are downcased.

    • %DateTime{} header values are encoded as "HTTP date".

    If you set :headers options both in Req.new/1 and Req.request/2, the header lists are merged.

    See also "Headers" section in the module documentation.

Additional URL options:

  • :base_url - if set, the request URL is prepended with this base URL (via put_base_url step.)

  • :params - if set, appends parameters to the request query string (via put_params step.)

  • :path_params - if set, uses a templated request path (via put_path_params step.)

  • :path_params_style (available since v0.5.1) - how path params are expressed (via put_path_params step). Can be one of:

    • :colon - (default) for Plug-style parameters, such as :code in https://httpbin.org/status/:code.

    • :curly - for OpenAPI-style parameters, such as {code} in https://httpbin.org/status/{code}.

Authentication options:

  • :auth - sets request authentication (via auth step.)

    Can be one of:

    • {:basic, userinfo} - uses Basic HTTP authentication.

    • {:bearer, token} - uses Bearer HTTP authentication.

    • :netrc - load credentials from the default .netrc file.

    • {:netrc, path} - load credentials from path.

    • string - sets to this value.

    • &fun/0 - a function that returns one of the above (such as a {:bearer, token}).

AWS Signature Version 4 options (put_aws_sigv4 step):

  • :aws_sigv4 - if set, the AWS options to sign request:

    • :access_key_id - the AWS access key id.

    • :secret_access_key - the AWS secret access key.

    • :service - the AWS service.

    • :region - if set, AWS region. Defaults to "us-east-1".

    • :datetime - the request datetime, defaults to DateTime.utc_now(:second).

Response body options:

  • :into - where to send the response body. It can be one of:

    • fun - stream response body using a function. The first argument is a {:data, frames} tuple containing the message frames of the response body. The second argument is a {request, response} tuple. To continue streaming frames, return {:cont, {req, resp}} or {:cont, frames, {req, resp}}. To cancel, return {:halt, {req, resp}} or {:halt, frames, {req, resp}}. See send_frame/2 for supported frame types. For example:

      into: fn {:data, [{:ping, string}]}, {req, resp} ->
        {:cont, [{:pong, string}], {req, resp}}
      end
    • :self - stream response body into the current process mailbox.

      Received messages should be parsed with ReqWebSocket.parse_message/2.

Response redirect options (redirect step):

  • :redirect - if set to false, disables automatic response redirects. Defaults to true.

  • :redirect_trusted - by default, authorization credentials are only sent on redirects with the same host, scheme and port. If :redirect_trusted is set to true, credentials will be sent to any host.

  • :max_redirects - the maximum number of redirects, defaults to 10.

Other response options:

  • :http_errors - how to handle HTTP 4xx/5xx error responses (via handle_http_errors step). Can be one of the following:
    • :return (default) - return the response

    • :raise - raise an error

Retry options (retry step):

  • :retry - can be one of the following:

    • :safe_transient (default) - retry safe (GET/HEAD) requests on one of:

      • HTTP 408/429/500/502/503/504 responses

      • Req.TransportError with reason: :timeout | :econnrefused | :closed

      • Req.HTTPError with protocol: :http2, reason: :unprocessed

    • :transient - same as :safe_transient except retries all HTTP methods (POST, DELETE, etc.)

    • fun - a 2-arity function that accepts a Req.Request and either a Req.Response or an exception struct and returns one of the following:

      • true - retry with the default delay controller by default delay option described below.

      • {:delay, milliseconds} - retry with the given delay.

      • false/nil - don't retry.

    • false - don't retry.

  • :retry_delay - if not set, which is the default, the retry delay is determined by the value of the Retry-After header on HTTP 429/503 responses. If the header is not set, the default delay follows a simple exponential backoff: 1s, 2s, 4s, 8s, ...

    :retry_delay can be set to a function that receives the retry count (starting at 0) and returns the delay, the number of milliseconds to sleep before making another attempt.

  • :retry_log_level - the log level to emit retry logs at. Can also be set to false to disable logging these messages. Defaults to :warning.

  • :max_retries - maximum number of retry attempts, defaults to 3 (for a total of 4 requests to the server, including the initial one.)

Other request options:

  • :connect_options - used when establishing HTTP connection, (see Mint.HTTP.connect/4 for details):

    • :timeout - socket connect timeout in milliseconds, defaults to 30_000.

    • :protocols - the HTTP protocols to use, defaults to [:http1, :http2].

    • :hostname - Mint explicit hostname.

    • :transport_opts - Mint transport options.

    • :proxy_headers - Mint proxy headers.

    • :proxy - Mint HTTP/1 proxy settings, a {schema, address, port, options} tuple.

    • :client_settings - Mint HTTP/2 client settings.

close(response)

@spec close(Req.Response.t()) :: {:ok, Req.Response.t()}

Closes WebSocket connection.

parse_message(response, message)

@spec parse_message(Req.Response.t(), term()) ::
  {:ok, Req.Response.t(), [Mint.WebSocket.frame()]}
  | {:error, Req.Response.t(), any()}
  | :unknown

Attempts to parse message into WebSocket frames, if the given message is not from the connection's socket, this function returns :unknown.

A WebSocket frame:

  • {:binary, binary} - a frame containing binary data. Binary frames can be used to send arbitrary binary data such as a PDF.
  • {:close, code, reason} - a control frame used to request that a connection be closed or to acknowledge a close frame sent by the server.
  • {:ping, binary} - a control frame which the server should respond to with a pong. The binary data must be echoed in the pong response.
  • {:pong, binary} - a control frame which forms a reply to a ping frame. Pings and pongs may be used to check the connection is alive or to estimate latency.
  • {:text, text} - a frame containing string data. Text frames must be valid utf8. Elixir has wonderful support for utf8: String.valid?/1 can detect valid and invalid utf8.

send_frame(response, frame)

@spec send_frame(
  Req.Response.t(),
  Mint.WebSocket.shorthand_frame() | Mint.WebSocket.frame()
) ::
  {:ok, Req.Response.t()} | {:error, Req.Response.t(), any()}

Encodes frame and sends encoded data on the established WebSocket connection.

Supported frame types:

  • :close - shorthand for {:close, nil, nil}
  • :ping - shorthand for {:ping, ""}
  • :pong - shorthand for {:pong, ""}
  • {:binary, binary}
  • {:close, code, reason}
  • {:ping, binary}
  • {:pong, binary}
  • {:text, text} - text must be valid utf8 encoded binary

send_frames(response, frames)

@spec send_frames(Req.Response.t(), [
  Mint.WebSocket.shorthand_frame() | Mint.WebSocket.frame()
]) ::
  {:ok, Req.Response.t()} | {:error, Req.Response.t(), any()}

Encodes frames and sends encoded data on an established WebSocket connection. See send_frame/2 for supported frame types.