HttpServer::AbstractStreamRequest Class Reference

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

## Public Member Functions

| constructor (HttpListenerInterface listener, AbstractHttpRequestHandler handler, Socket s, hash< auto > cx, hash< auto > hdr, auto 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 More...
auto | sendImpl ()
| callback method for sending chunked data 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 | listener,
|  | AbstractHttpRequestHandler | handler,
|  | Socket | s,
|  | hash< auto > | cx,
|  | hash< auto > | hdr,
|  | auto | body
| ) |  |

creates the object with the given attributes

Parameters

  listener | an HttpListenerInterface object for the listener serving the request for logging purposes
  handler | the handler serving the request
  s | the Socket for serving the request
  cx | a call context hash

  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"`)

  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)

## send()

auto HttpServer::AbstractStreamRequest::send | ( |  | ) |

protected

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

## 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).