HttpServer::AbstractStreamRequest Class Reference

abstract class for streaming HTTP chunked requests/responses More...

## Public Member Functions

| constructor (HttpListenerInterface n_listener, AbstractHttpRequestHandler n_handler, Socket n_s, hash< auto > n_cx, hash< auto > n_hdr, auto n_body)
| creates the object with the given attributes More...
hash< HttpHandlerResponseInfo > | handleRequest ()
| handles the request

## Protected Member Functions

hash< HttpHandlerResponseInfo > | getResponseHeaderMessage ()
| this method returns the response message description hash by calling getResponseHeaderMessageImpl() More...
hash< HttpResponseInfo > | getResponseHeaderMessageImpl ()
| this method should return the response message description hash More...
| logChunk (bool send, int size)
| this method can be overridden in base classes to log each HTTP chunk sent More...
nothing | recv (hash< auto > v)
| this is the primary callback for receiving chunked data; data will be logged, and then recvImpl() is called More...
nothing | recvImpl (hash< auto > v)
| callback method for receiving chunked data; the default implementation in this base class does nothing More...
auto | send ()
| this is the primary callback for sending chunked responses; first sendImpl() is called to get the raw data, and then any chunked data is encoded by this method if required
auto | sendImpl ()
| callback method for sending chunked data; the default implementation in this base class does nothing and returns nothing More...
hash< HttpHandlerResponseInfo > | sendResponse ()
| called to either create the response hash or send a chunked response directly More...

## Protected Attributes

auto | body
| any message body given in a non-chunked request; could already be deserialized
hash< auto > | cx
| the call context variable
AbstractHttpRequestHandler | handler
| the request handler for the request
hash< auto > | hdr
| a hash of request headers
HttpListenerInterface | listener
| an HttpListenerInterface object for the listener serving the request for logging purposes
Socket | s
| the Socket object for the response
timeout | timeout_ms = HttpServer::DefaultTimeout
| send and receive timeout

## Detailed Description

abstract class for streaming HTTP chunked requests/responses

This class is the base class for handling HTTP stream requests; i.e. with chunked data

The calling order is as follows:

- constructor(): this is called when the request is received
- recv(): this is called once for each HTTP chunk (if data is sent chunked), and then once with any message trailer. If data is sent non-chunked, then this method is called with the monolithic message body and then again with NOTHING to signify the end of the transfer and to simulate a chunked transfer. The simulation of a chunked transfer or the actual chunked receive with the callbacks is made by the handleRequest() method. Subclasses should re-implement recvImpl() which is called by this method
- getResponseHeaderMessage(): this is called after the message body has been received to get the response headers and optionally a message body. Subclasses should reimplement getResponseHeaderMessageImpl() which is called by this method
- send(): this is called if no message body is returned by getResponseHeaderMessage(); each time this method returns data, the data is sent in a response chunk; when this method returns NOTHING, then no more data is sent. Subclasses should re-implement sendImpl() which is called by this method

## Member Function Documentation

## constructor()

HttpServer::AbstractStreamRequest::constructor | ( | HttpListenerInterface | n_listener,
|  | AbstractHttpRequestHandler | n_handler,
|  | Socket | n_s,
|  | hash< auto > | n_cx,
|  | hash< auto > | n_hdr,
|  | auto | n_body
| ) |  |

creates the object with the given attributes

Parameters

  n_listener | an HttpListenerInterface object for the listener serving the request for logging purposes
  n_handler | the handler serving the request
  n_s | the Socket for serving the request
  n_cx | a call context hash

  n_hdr

  incoming header hash; all keys will be converted to lower-case, additionally the following keys will be present:
  - `method:` the HTTP method received (ie `"GET"`, `"POST"`, etc)
  - `path:` the HTTP path given in the request, after processing by Qore::decode_uri_request()
  - `http_version:` the HTTP version number in the request (either `"1.0"` or `"1.1"`)

  n_body | any message body in the request already received from the incoming socket

## getResponseHeaderMessage()

hash<HttpHandlerResponseInfo> HttpServer::AbstractStreamRequest::getResponseHeaderMessage | ( |  | ) |

protected

this method returns the response message description hash by calling getResponseHeaderMessageImpl()

Returns
  a hash with the following keys:
  - `"code"`: the HTTP return code (see HttpServer::HttpCodes)
  - `"body"`: the message body to return in the response; if this key is returned, then the reply is sent immediately; a chunked reply is not made, and send() and sendImpl() are not called
  - `"close"`: (optional) set this key to True if the connection should be unconditionally closed when the handler returns
  - `"hdr"`: (optional) set this key to a hash of extra header information to be returned with the response

Note
  this method is called after the message body has been received

## getResponseHeaderMessageImpl()

hash<HttpResponseInfo> HttpServer::AbstractStreamRequest::getResponseHeaderMessageImpl | ( |  | ) |

protected

this method should return the response message description hash

The default implementation in this class is to return a 501 Not Implemented response; override in subclasses to return a custom response. Omit the `"body"` key to ensure that a chunked response is sent and the send() and sendImpl() callbacks are called.

Returns
  a hash with the following keys:
  - `"code"`: the HTTP return code (see HttpServer::HttpCodes)
  - `"body"`: the message body to return in the response; if this key is returned, then the reply is sent immediately; a chunked reply is not made, and send() and sendImpl() are not called
  - `"close"`: (optional) set this key to True if the connection should be unconditionally closed when the handler returns
  - `"hdr"`: (optional) set this key to a hash of extra header information to be returned with the response

Note
  this method is called after the message body has been received

## logChunk()

HttpServer::AbstractStreamRequest::logChunk | ( | bool | send,
|  | int | size
| ) |  |

protected

this method can be overridden in base classes to log each HTTP chunk sent

  private logChunk(bool send, int size) {
  listener.log("cid %d %s CHUNK %d bytes", cx.id, send ? "send" : "recv", size);
  }

By default this method does nothing

## recv()

nothing HttpServer::AbstractStreamRequest::recv | ( | hash< auto > | v | ) |

protected

this is the primary callback for receiving chunked data; data will be logged, and then recvImpl() is called

content decoding is not possible with chunked data because only the entire message can be decoded

## recvImpl()

nothing HttpServer::AbstractStreamRequest::recvImpl | ( | hash< auto > | v | ) |

protected

callback method for receiving chunked data; the default implementation in this base class does nothing

Parameters

  v

  the first time this method is called with a hash of the message headers in the `"hdr"` key, and then with any message body in the `"data"`; if a chunked HTTP message is received, then this method is called once for each chunk; when the message has been received, then this method is called with a hash representing any trailer data received in a chunked transfer or NOTHING if the data was received in a normal message body or if there was no trailer data in a chunked transfer. The argument to this callback is always a hash; data calls have the following keys:
  - `"data"`: the string or binary data
  - `"chunked"`: True if the data was received with chunked transfer encoding, False if not
  Header or trailer data is placed in a hash with the following keys:
  - `"hdr"`: this can be assigned to NOTHING for the trailer hash if the data was not sent chunked or no trailers were included in a chunked message
  - `"obj"`: this is the owning object (so socket parameters can be changed based on headers received, such as, for example, socket character encoding)

## sendImpl()

auto HttpServer::AbstractStreamRequest::sendImpl | ( |  | ) |

protected

callback method for sending chunked data; the default implementation in this base class does nothing and returns nothing

Returns
  The chunked HTTP data to send; this method must return either a string or a binary value each time it is called to give the chunked data to send; when all data has been sent, then a hash of message trailers can be returned or simply NOTHING which will close the chunked message

## sendResponse()

hash<HttpHandlerResponseInfo> HttpServer::AbstractStreamRequest::sendResponse | ( |  | ) |

protected

called to either create the response hash or send a chunked response directly

This method calls getResponseHeaderMessageImpl() to get the response code, headers and optionally a response message body. If a `"Transfer-Encoding: chunked"` header is included, then the response is sent chunked using the send() callback; in this case the `"reply_sent"` key in the response is set to True. Otherwise, any message body is immediately encoded (if accepted by the requestor).