Payload

This class represent a single HTTP message, which can be either a request or a response.

Transfer Modes

HTTP provides two ways to encode the transmission of a message 'body', of any size. This package supports both of them:

  1. StreamTransfer. This is used for payload bodies where the exact length is known in advance, including most transfers of files. It is selected by calling Payload.set_length with an integer bytecount. Appication buffer sizes determine how much data is fed to the TCP connection at once, but the total amount must match this size.

  2. ChunkedTransfer. This is used when the payload length can not be known in advance, but can be large. It is selected by calling Payload.set_length with a parameter of None. On the TCP link this mode can be detected because there is no Content-Length header at all, being replaced by the Transfer-Encoding: chunked header. In addition, the message body is separated into chunks, each with its own bytecount. As with StreamTransfer mode, transmission can be spread out over time with the difference that it is the original data source that determines the chunk size.

If Payload.set_length is never called at all, a variation on StreamTransfer called OneshotTransfer is used. In this case, all of the message body is placed into the message at once, using Payload.add_chunk calls. The size will be determined when the message is submitted for transmission. Care must be taken not to consume too much memory, especially on a server where there can be multiple messages in transit at once.

The type of transfer being used by an incoming message can be determined from its transfer_mode field, which will be one of the TransferMode types.

Sequence

For example, to send a message of possibly large size:

  1. Create the message with a call to Payload.request or Payload.response.
  2. Set the session field of the message.
  3. Call Payload.set_length to indicate the length of the body.
  4. Add any additional headers that may be required, such as Content-type.
  5. Submit the message for transmission by calling the either the HTTPSession.apply method (in servers) or the HTTPCLient.apply method in clients.
  6. Wait for the send_body notification.
  7. Make any number of calls to Payload.send_chunk.
  8. Call Payload.finish.

To send a message of small, reasonable size (say, under 20KB), this simplified method can be used instead:

  1. Create the message with a call to Payload.request or Payload.response.
  2. Set the session field of the message.
  3. Add any additional headers that may be required, such as Content-type.
  4. Call add_chunk one or more times to add body data.
  5. Submit the message for transmission by calling the either the HTTPSession.apply method (in servers) or the HTTPClient.apply method in clients.
class trn Payload

Constructors

request

new iso request(
  method': String val = seq,
  url': URL val = seq)
: Payload iso^

Parameters

  • method': String val = seq
  • url': URL val = seq

Returns


response

new iso response(
  status': Status val = seq)
: Payload iso^

Parameters

Returns


_empty

new iso _empty(
  response': Bool val = seq)
: Payload iso^

Parameters

  • response': Bool val = seq

Returns


Public fields


  • var status: U16 val


  • var url: URL val





Public Functions

apply

Get a header.

fun box apply(
  key: String val)
: String val ?

Parameters

Returns


is_safe

A request method is "safe" if it does not modify state in the resource. These methods can be guaranteed not to have any body data. Return true for a safe request method, false otherwise.

fun box is_safe()
: Bool val

Returns


body

Get the body in OneshotTransfer mode. In the other modes it raises an error.

fun box body()
: this->Array[(String val | Array[U8 val] val)] ref ?

Returns


set_length

Set the body length when known in advance. This determines the transfer mode that will be used. A parameter of 'None' will use Chunked Transfer Encoding. A numeric value will use Streamed transfer. Not calling this function at all will use Oneshot transfer.

fun ref set_length(
  bytecount: (USize val | None val))
: None val

Parameters

Returns


update

Set any header. If we've already received the header, append the value as a comma separated list, as per RFC 2616 section 4.2.

fun ref update(
  key: String val,
  value: String val)
: Payload ref^

Parameters

Returns


headers

Get all the headers.

fun box headers()
: this->HashMap[String val, String val, HashEq[String val] val] ref

Returns


body_size

Get the total intended size of the body. ServerConnection accumulates actual size transferred for logging.

fun box body_size()
: (USize val | None val)

Returns


add_chunk

This is how application code adds data to the body in OneshotTransfer mode. For large bodies, call set_length and use send_chunk instead.

fun ref add_chunk(
  data: (String val | Array[U8 val] val))
: Payload ref^

Parameters

Returns


send_chunk

This is how application code sends body data in StreamTransfer and ChunkedTransfer modes. For smaller body lengths, add_chunk in Oneshot mode can be used instead.

fun box send_chunk(
  data: (String val | Array[U8 val] val))
: None val

Parameters

Returns


finish

Mark the end of body transmission. This does not do anything, and is unnecessary, in Oneshot mode.

fun val finish()
: None val

Returns


respond

Start sending a response from the server to the client.

fun val respond(
  response': Payload trn)
: None val

Parameters

Returns


has_body

Determines whether a message has a body portion.

fun box has_body()
: Bool val

Returns


Private Functions

_client_fail

Start sending an error response.

fun val _client_fail()
: None val

Returns


_write

Writes the payload to an HTTPSession. Requests and Responses differ only in the first line of text - everything after that is the same format.

fun val _write(
  keepalive: Bool val = seq,
  conn: TCPConnection tag)
: None val

Parameters

Returns


_write_request

Writes the 'request' parts of an HTTP message.

fun val _write_request(
  keepalive: Bool val,
  conn: TCPConnection tag)
: None val

Parameters

Returns


_write_common

Writes the parts of an HTTP message common to both requests and responses.

fun val _write_common(
  conn: TCPConnection tag)
: None val

Parameters

Returns


_write_response

Write the response-specific parts of an HTTP message. This is the status line, consisting of the protocol name, the status value, and a string representation of the status (carried in the method field). Since writing it out is an actor behavior call, we go to the trouble of packaging it into a single string before sending.

fun val _write_response(
  keepalive: Bool val,
  conn: TCPConnection tag)
: None val

Parameters

Returns


_write_headers

Write all of the HTTP headers to the comm link.

fun box _write_headers(
  conn: TCPConnection tag)
: None val

Parameters

Returns