Table of Contents

Struct - Http1WriterBase

Module
juptune.http.v1
struct Http1WriterBase( SocketT )
{
  // Finishes the headers. 
  alias finishHeaders = <todo: marmos support pending>
  // Ditto. 
  alias finishTrailers = <todo: marmos support pending>
  // 
  alias Machine = <todo: marmos support pending>
  // Writes a single header. 
  alias putHeader = <todo: marmos support pending>
  // Ditto. 
  alias putTrailer = <todo: marmos support pending>
  // 
  alias StateMachine = <todo: marmos support pending>

  // 
  Result bufferedWrite( const scope void[] data ) 
  // 
  Result bufferHeaderName( const scope char[] name, out scope char[] buffered ) 
  // Finishes the body. 
  Result finishBody() 
  // 
  Result finishHeadersImpl( bool trailers )() 
  // Acknowledges that the entire HTTP message has been written, and returns a summary 
  Result finishMessage( out scope Http1MessageSummary summary ) 
  // 
  Result flush() 
  // 
  Result processHeader( const scope char[] name, const scope char[] value ) 
  // Writes body data. 
  Result putBody( const scope void[] data ) 
  // 
  Result putBodyChunked( const scope void[] data ) 
  // 
  Result putBodyContentLength( const scope void[] data ) 
  // 
  Result putHeaderImpl(
    bool trailers
  )(
    const scope char[] name,
    const scope char[] value
  ) 
  // Writes an entire request line. This will configure this writer to be a request writer for the remainder of the message, until `finishMessage` is called. 
  Result putRequestLine(
    const scope char[] method,
    const scope char[] path,
    Http1Version httpVersion
  ) 
  // Writes an entire response line. This will configure this writer to be a response writer for the remainder of the message, until `finishMessage` is called. 
  Result putResponseLine(
    Http1Version httpVersion,
    uint statusCode,
    const scope char[] reason
  ) 
  // Writes the HTTP message stored within the provided `result` to the socket. 
  Result putResultResponse( Result result ) 
}

About

A low-level writer for the HTTP/1.0 and HTTP/1.1 protocols.

Performance

No explicit effort has been made to optimise this writer for performance, but it should be reasonably fast.

Memory wise the writer does not directly allocate heap memory as it uses the user-provided buffer, however the I/O calls can of course do whatever they want.

If the writer would have to perform more than 1 flush due to the data being larger than the buffer, then the writer will perform two flushes at most - one for the currently buffered data, and one for the entire remaining data (without needing to buffer the remaining data directly).

Buffer

The writer operates directly on a buffer provided by the user.

The size of the buffer dictates how many bytes can be stored before a flush is forced. Certain actions, such as calling finishMessage , will also force a flush.

Generally the idea of the buffer is to reduce the amount of I/O calls, more than anything else.

Flow

The writer is a low-level, state-machine API, and thus requires quite a lot of involvement from the user as well as a magical incantation of calls to create fully valid HTTP messages.

Similar to the Http1Reader any HttpError result will contain a valid HTTP response, however it's not really useful due to the fact these errors will almost always occur mid-message, making it impossible to relay the information to the client.

Generally, if a protocol error is encountered simply close the connection.

RequestFlow

1.1. Call `putRequestLine` to write the request line. 

1.1. Call `putHeader` to write any headers. 
  1. If you plan to write a body, you must either write a content-length header, or write a transfer-encoding: chunked header.

    1.1. Call finishHeaders to finish the headers.

    1.1. Call putBody to write any body data, if any.

    1.1. Call finishBody to finish the body.

    1.1. Call finishMessage to finish the message.

ResponseFlow

The response flow is very similar to the request flow except we need to account for being able to write trailer headers.

1.1. Call `putResponseLine` to write the response line. 

1.1. Call `putHeader` to write any headers. 
  1. If you plan to write a body, you must either write a content-length header, or write a transfer-encoding: chunked header.

    1.1. Call finishHeaders to finish the headers.

    1.1. Call putBody to write any body data, if any.

    1.1. Call finishBody to finish the body.

    1.1. If the transfer-encoding: chunked header was written:

  2. Call putTrailer to write any trailer headers, if any.

    1.1. Call finishTrailer to finish the trailer headers. You must do this regardless of if you wrote/can use trailers.

    1.1. Call finishMessage to finish the message.

Notes

The writer currently does not support scattered writes.

The writer will never close the socket as it does not have ownership of it.

Security

The writer internally makes use of a type-system-based state machine to make it more difficult to perform a bad state transition.

No other specific security issues are addressed beyond ensuring that the data written is valid according to RFC 9110 & 9112

Issues

The writer is currently in an early state, and is not yet ready for production.

The current API is not stable, and may change in the future.

The writer does not natively perform compression.

The writer is not very extensively tested yet.

Specific differences between HTTP/1.0 and HTTP/1.1 are not fully implemented, as HTTP/1.1 has been the main focus.

Aliases

Name Description
finishHeaders Finishes the headers.
finishTrailers Ditto.
Machine
putHeader Writes a single header.
putTrailer Ditto.
StateMachine

Enums

Name Description
BodyEncoding
State

Functions

Name Description
bufferedWrite
bufferHeaderName
finishBody Finishes the body.
finishHeadersImpl
finishMessage Acknowledges that the entire HTTP message has been written, and returns a summary
flush
processHeader
putBody Writes body data.
putBodyChunked
putBodyContentLength
putHeaderImpl
putRequestLine Writes an entire request line. This will configure this writer to be a request writer for the remainder of the message, until finishMessage is called.
putResponseLine Writes an entire response line. This will configure this writer to be a response writer for the remainder of the message, until finishMessage is called.
putResultResponse Writes the HTTP message stored within the provided result to the socket.

Structs

Name Description
MessageState