Skip to content

Session

[Source]

An HTTP Session is the external API to the communication link between client and server.

Every request is executed as part of a HTTP Session. An HTTP Session lives as long as the underlying TCP connection and receives request data from it and writes response data to it.

Receiving data and parsing this data into Requests is happening on the TCPConnection actor. The Session actor is started when a new TCPConnection is accepted, and shut down, when the connection is closed.

Receiving a Request

As part of the Request-Response handling internal to this HTTP library, a Session is instantiated that forwards requests to a Handler, to actual application code, which in turn sends Responses back to the Session instance it was instantiated with (See HandlerFactory.

See Handler on how requests are received by application code.

Sending a Response

trait tag Session

Public Behaviours

send_start

[Source]

Verbose API

Start sending a response, submitting the Response status and headers.

Sending a response via the verbose API needs to be done in 2 or more steps:

  • Session.send_start - exactly once - submit status and headers
  • Session.send_chunk - 0 or more times - submit body
  • Session.send_finished - exactly once - clean up resources
be send_start(
  respone: Response val,
  request_id: USize val)

Parameters


send_chunk

[Source]

Verbose API

Send a piece of body data of the request identified by request_id. This might be the whole body or just a piece of it.

Notify the Session that the body has been fully sent, by calling Session.send_finished.

be send_chunk(
  data: (String val | Array[U8 val] val),
  request_id: USize val)

Parameters


send_finished

[Source]

Verbose API

Indicate that the response for request_id has been completed, that is, its status, headers and body have been sent.

This will clean up resources on the session and might send pending pipelined responses in addition to this response.

If this behaviour isnt called, the server might misbehave, especially with clients doing HTTP pipelining.

be send_finished(
  request_id: USize val)

Parameters


send_cancel

[Source]

Cancel sending an in-flight response. As the Session will be invalid afterwards, as the response might not have been sent completely, it is best to close the session afterwards using Session.dispose().

be send_cancel(
  request_id: USize val)

Parameters


send_no_body

[Source]

Simple API

Send a bodyless Response in one call.

This call will do all the work of sending the response and cleaning up resources. No need to call Session.send_finished() anymore for this request.

be send_no_body(
  response: Response val,
  request_id: USize val)

Parameters


send

[Source]

Simple API

Send an Response with a body in one call.

The body must be a ByteArrays instance.

Example:

// ...
var bytes = ByteArrays
bytes = bytes + "first line" + "\n"
bytes = bytes + "second line" + "\n"
bytes = bytes + "third line"

session.send(response, bytes, request_id)
// ...

This call will do all the work of sending the response and cleaning up resources. No need to call Session.send_finished() anymore for this request.

be send(
  response: Response val,
  body: ByteArrays val,
  request_id: USize val)

Parameters


send_raw

[Source]

Optimized raw API

Send raw bytes to the Session in form of a ByteSeqIter.

These bytes may or may not include the response body. You can use Session.send_chunk() to send the response body piece by piece.

If the session should be closed after sending this response, no matter the requested standard HTTP connection handling, set close_session to true. To be a good HTTP citizen, include a Connection: close header in the raw response, to signal to the client to also close the session. If set to false, then normal HTTP connection handling applies (request Connection header, HTTP/1.0 without Connection: keep-alive, etc.).

To finish sending the response, it is required to call Session.send_finished() to wrap things up, otherwise the server might misbehave.

This API uses the TCPConnection.writev method to optimize putting the given bytes out to the wire.

To make this optimized path more usable, this library provides the ResponseBuilder, which builds up a response into a ByteSeqIter, thus taylored towards being used with this API.

Example:

class MyHandler is Handler
  let _session: Session

  new create(session: Session) =>
    _session = session

  fun ref apply(request: Request val, request_id: RequestID): Any =>
    let body =
      match request.content_length()
      | let cl: USize =>
        "You've sent us " + cl.string() + " bytes! Thank you!"
      | None if request.transfer_coding() is Chunked =>
        "You've sent us some chunks! That's cool!"
      | None =>
        "Dunno how much you've sent us. Probably nothing. That's alright."
      end

    _session.send_raw(
      Responses.builder()
        .set_status(StatusOK)
        .add_header("Content-Type", "text/plain; charset=UTF-8")
        .add_header("Content-Length", body.size().string())
        .finish_headers()
        .add_chunk(body)
        .build(),
      request_id
    )
    // never forget !!!
    _session.send_finished(request_id)
be send_raw(
  raw: ByteSeqIter val,
  request_id: USize val,
  close_session: Bool val = false)

Parameters


dispose

[Source]

Close the connection from this end.

be dispose()

upgrade_protocol

[Source]

Upgrade this TCP connection to another handler, serving another protocol (e.g. WebSocket).

Note that this method does not send an HTTP Response with a status of 101. This needs to be done before calling this behaviour. Also, the passed in notify will not have its methods accepted or connected called, as the connection is already established.

After calling this behaviour, this session and the connected Handler instance will not be called again, so it is necessary to do any required clean up right after this call.

See:

be upgrade_protocol(
  notify: TCPConnectionNotify iso)

Parameters