All Classes Namespaces Functions Variables Groups Pages
HttpServerUtil.qm.dox.h
// -*- mode: c++; indent-tabs-mode: nil -*-
// @file HttpServerUtil.qm HTTP server base code
/* HttpServerUtil.qm Copyright (C) 2014 - 2016 David Nichols
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
// need mime definitions
namespace HttpServer {
const HttpServerVersion = "0.3.11";
const HttpServerString = sprintf("Qore-HTTP-Server/%s", HttpServerVersion);
const DefaultTimeout = 30s; // recvs timeout after 30 seconds
const ReadTimeout = DefaultTimeout;
const HttpCodes = (
// 100s: Informational
"100": "Continue",
"101": "Switching Protocols",
// RFC 2518: WebDAV
"102": "Processing",
// 200s: Success
"200": "OK",
"201": "Created",
"202": "Accepted",
"203": "Non-Authoritative Information",
"204": "No Content",
"205": "Reset Content",
"206": "Partial Content",
// RFC 4918: WebDAV: The message body that follows is an XML message and can contain a number of separate response codes, depending on how many sub-requests were made
"207": "Multi-Status",
// RFC 5842: WebDAV: The members of a DAV binding have already been enumerated in a previous reply to this request, and are not being included again
"208": "Already Reported",
// RFC 3229
"226": "IM Used",
// 300s: Redirection
"300": "Multiple Choices",
"301": "Moved Permanently",
"302": "Found",
"303": "See Other",
"304": "Not Modified",
"305": "Use Proxy",
//"306": "(Reserved)",
"307": "Temporary Redirect",
// 400s: Client Errors
"400": "Bad Request",
"401": "Unauthorized",
"402": "Payment Required",
"403": "Forbidden",
"404": "Not Found",
"405": "Method Not Allowed",
"406": "Not Acceptable",
"407": "Proxy Authentication Required",
"408": "Request Timeout",
"409": "Conflict",
"410": "Gone",
"411": "Length Required",
"412": "Precondition Failed",
"413": "Request Entity Too Large",
"414": "Request-URI Too Long",
"415": "Unsupported Media Type",
"416": "Requested Range Not Satisfiable",
"417": "Expectation Failed",
// RFC 2324: http://tools.ietf.org/html/rfc2324
"418": "I'm a teapot",
// Returned by the Twitter Search and Trends API when the client is being rate limited
"420": "Enhance Yextern Calm",
// RFC 4918: WebDAV: The request was well-formed but was unable to be followed due to semantic errors
"422": "Unprocessable Entity",
// RFC 4918: WebDAV: The resource that is being accessed is locked
"423": "Locked",
// RFC 4918: WebDAV: The request failed due to failure of a previous request (e.g. a PROPPATCH)
"424": "Failed Dependency",
// Internet draft: Defined in drafts of "WebDAV Advanced Collections Protocol", but not present in "Web Distributed Authoring and Versioning (WebDAV) Ordered Collections Protocol"
"425": "Unordered Collection",
// RFC 2817: The client should switch to a different protocol such as TLS/1.0
"426": "Upgrade Required",
// RFC 6585: The origin server requires the request to be conditional. Intended to prevent "the 'lost update' problem, where a client GETs a resource's state, modifies it, and PUTs it back to the server, when meanwhile a third party has modified the state on the server, leading to a conflict."
"428": "Precondition Required",
// RFC 6585: The user has sent too many requests in a given amount of time. Intended for use with rate limiting schemes
"429": "Too Many Requests",
// RFC 6585
"431": "Request Header Fields Too Large",
// 500s: Server Errors
"500": "Internal Server Error",
"501": "Not Implemented",
"502": "Bad Gateway",
"503": "Service Unavailable",
"504": "Gateway Timeout",
"505": "HTTP Version Not Supported",
"509": "Bandwidth Limit Exceeded",
// RFC 2774: Further extensions to the request are required for the server to fulfill it
"510": "Not Extended",
// RFC 6585: The client needs to authenticate to gain network access. Intended for use by intercepting proxies used to control access to the network (e.g. "captive portals" used to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot)
"511": "Network Authentication Required",
);
const LP_LOGPARAMS = 1 << 16;
const LP_LEVELMASK = LP_LOGPARAMS - 1;
string http_get_url_from_bind(softstring bind, *string host);
hash parse_uri_query(string path);
nothing http_set_reply_headers(Socket s, hash cx, reference rv, *string server_string);
};
class HttpServer::AbstractLogger {
public:
abstract log(string fmt);
abstract logError(string fmt);
logArgs(*softlist args);
logErrorArgs(*softlist args);
};
class HttpServer::HttpListenerInterface : public HttpServer::AbstractLogger {
public:
abstract addUserThreadContext(hash uctx);
abstract any removeUserThreadContext(*string k);
};
class HttpServer::AbstractAuthenticator {
public:
bool requiresAuthentication();
string getRealm();
authenticate(string user, string pass = "");
authenticateByIP(string ip, reference user);
private hash getAuthHeader();
private hash do401(string msg = "Authentication is required to access this server");
*hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx);
};
class HttpServer::PermissiveAuthenticator : public HttpServer::AbstractAuthenticator {
public:
*hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx);
};
class HttpServer::AbstractStreamRequest {
public:
private:
public:
private :
HttpListenerInterface listener;
AbstractHttpRequestHandler handler;
Socket s;
hash cx;
hash hdr;
any body;
timeout timeout_ms = HttpServer::DefaultTimeout;
public:
constructor(HttpListenerInterface n_listener, AbstractHttpRequestHandler n_handler, Socket n_s, hash n_cx, hash n_hdr, any n_body);
hash handleRequest();
private hash sendResponse();
private hash getResponseHeaderMessage();
private nothing recv(hash v);
private any send();
private logChunk(bool send, int size);
private hash getResponseHeaderMessageImpl();
private nothing recvImpl(hash v);
private any sendImpl();
};
class HttpServer::AbstractHttpRequestHandler {
public:
public :
*AbstractAuthenticator auth;
bool decompress = True;
bool decompress_to_string = True;
bool stream;
timeout timeout_ms = HttpServer::DefaultTimeout;
const NotificationThreadKey = "_AHRH_pc";
const PersistenceThreadKey = "_AHRH_p";
public:
constructor(*AbstractAuthenticator n_auth, softbool n_stream = False);
bool isPersistent();
setPersistent(bool p = True);
notifyClosed(*code c);
static staticNotificationCleanup();
static staticPersistenceCleanup();
nothing persistentClosed();
private nothing checkPersistent(hash cx, hash hdr);
hash handleRequest(hash cx, hash hdr, *data body);
hash handleRequest(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body);
private AbstractStreamRequest getStreamRequestImpl(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body);
static data decodeBody(string ce, binary body, *string enc);
static binary encodeBody(string ce, data body);
*data getMessageBody(Socket s, hash hdr, *data body, bool decode = True);
static *string getLogMessage(hash cx, hash api, reference params, *reference args);
*hash saveThreadLocalData();
restoreThreadLocalData(*hash data);
static hash makeResponse(int code, string fmt);
static hash makeResponse(hash hdr, int code, string fmt);
static hash makeResponse(int code, *data body, *hash hdr);
static hash make400(string fmt);
static hash make400(hash hdr, string fmt);
static hash make501(string fmt);
static hash make501(hash hdr, string fmt);
static hash redirect(hash cx, hash hdr, string path);
};
class HttpServer::AbstractUrlHandler : public HttpServer::AbstractHttpRequestHandler {
public:
public :
string url_root;
public:
constructor(string n_url_root, *AbstractAuthenticator auth) ;
string getRelativePath(string path);
};
class HttpServer::AbstractHttpSocketHandler : public HttpServer::AbstractHttpRequestHandler {
public:
private :
bool stop = False;
hash lh;
hash lsh;
Mutex m();
public:
constructor(*AbstractAuthenticator auth) ;
start(softstring lid, hash cx, hash hdr, Socket s);
stop(softstring lid);
stop();
abstract hash handleRequest(hash cx, hash hdr, *data b);
private abstract startImpl(softstring lid, hash cx, hash hdr, Socket s);
private stopImpl(string lid);
private stopImpl();
};
sprintf
string sprintf(string fmt,...)
HttpServer::AbstractLogger::logErrorArgs
logErrorArgs(*softlist args)
calls logError() with the given args
HttpServer::AbstractStreamRequest::hdr
hash hdr
a hash of request headers
Definition: HttpServerUtil.qm.dox.h:367
HttpServer::AbstractStreamRequest::recvImpl
private nothing recvImpl(hash v)
callback method for receiving chunked data; the default implementation in this base class does nothin...
HttpServer::ReadTimeout
const ReadTimeout
read timeout in ms
Definition: HttpServerUtil.qm.dox.h:87
HttpServer::HttpCodes
const HttpCodes
map of HTTP result codes and text messages
Definition: HttpServerUtil.qm.dox.h:90
HttpServer::AbstractStreamRequest
abstract class for streaming HTTP chunked requests/responses
Definition: HttpServerUtil.qm.dox.h:350
HttpServer::AbstractHttpSocketHandler::handleRequest
abstract hash handleRequest(hash cx, hash hdr, *data b)
called by the HTTP server to handle incoming HTTP requests
HttpServer::LP_LOGPARAMS
const LP_LOGPARAMS
bit for logging argument
Definition: HttpServerUtil.qm.dox.h:196
HttpServer::AbstractAuthenticator::getRealm
string getRealm()
returns the authentication realm as a string
HttpServer::AbstractHttpRequestHandler
abstract class that all HTTP request handler objects must inherit from
Definition: HttpServerUtil.qm.dox.h:472
HttpServer::PermissiveAuthenticator
class providing automatic authentication for all requests
Definition: HttpServerUtil.qm.dox.h:327
HttpServer::AbstractHttpRequestHandler::auth
*AbstractAuthenticator auth
the optional AbstractAuthenticator for requests to this handler
Definition: HttpServerUtil.qm.dox.h:477
HttpServer::AbstractLogger::log
abstract log(string fmt)
called to log information to the registered log code
HttpServer::AbstractHttpSocketHandler::lh
hash lh
hash of listener references; this is to stop all connections associated with a particular listener ...
Definition: HttpServerUtil.qm.dox.h:658
True
const True
HttpServer::AbstractHttpSocketHandler::start
start(softstring lid, hash cx, hash hdr, Socket s)
called from the HTTP server after the handleRequest() method indicates that a dedicated connection sh...
HttpServer::AbstractUrlHandler::getRelativePath
string getRelativePath(string path)
returns the relative path anchored from the url_root if possible; URI query arguments are stripped of...
HttpServer::HttpListenerInterface
this abstract class defines the public interface of the private HttpListener class defined in the Htt...
Definition: HttpServerUtil.qm.dox.h:254
HttpServer::AbstractAuthenticator::authenticateRequest
*hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx)
primary method called to authenticate each request
HttpServer::AbstractHttpRequestHandler::getMessageBody
*data getMessageBody(Socket s, hash hdr, *data body, bool decode=True)
optionally retrieves and post-processes any message body
HttpServer::AbstractStreamRequest::sendResponse
private hash sendResponse()
called to either create the response hash or send a chunked response directly
HttpServer::AbstractStreamRequest::handler
AbstractHttpRequestHandler handler
the request handler for the request
Definition: HttpServerUtil.qm.dox.h:361
HttpServer::AbstractHttpRequestHandler::decompress
bool decompress
if POSTed data should be decompressed automatically if there is content-encoding
Definition: HttpServerUtil.qm.dox.h:480
HttpServer::AbstractHttpSocketHandler::startImpl
abstract private startImpl(softstring lid, hash cx, hash hdr, Socket s)
called from the HTTP server after the handleRequest() method indicates that a dedicated connection sh...
HttpServer::AbstractStreamRequest::constructor
constructor(HttpListenerInterface n_listener, AbstractHttpRequestHandler n_handler, Socket n_s, hash n_cx, hash n_hdr, any n_body)
creates the object with the given attributes
HttpServer::AbstractStreamRequest::getResponseHeaderMessageImpl
private hash getResponseHeaderMessageImpl()
this method should return the response message description hash
binary
binary binary()
HttpServer::AbstractHttpRequestHandler::stream
bool stream
if the handler supports streaming requests/responses with chunked data
Definition: HttpServerUtil.qm.dox.h:486
HttpServer::AbstractUrlHandler::constructor
constructor(string n_url_root, *AbstractAuthenticator auth)
creates the object based on the URL root and optional authenticator
HttpServer::AbstractHttpSocketHandler::m
Mutex m()
listener reference hash mutex
HttpServer::AbstractHttpSocketHandler::stopImpl
private stopImpl()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
HttpServer::AbstractHttpRequestHandler::make501
static hash make501(string fmt)
creates a hash for an HTTP 501 error response with the response message body as a string ...
False
const False
HttpServer::AbstractAuthenticator::requiresAuthentication
bool requiresAuthentication()
called to check if the connection requires authentication
HttpServer::AbstractHttpRequestHandler::notifyClosed
notifyClosed(*code c)
calls the argument when the persistent connection is closed
HttpServer::http_get_url_from_bind
string http_get_url_from_bind(softstring bind, *string host)
returns a complete URL from a bind address
HttpServer::AbstractAuthenticator
abstract base class for external authentication
Definition: HttpServerUtil.qm.dox.h:271
HttpServer::HttpListenerInterface::removeUserThreadContext
abstract any removeUserThreadContext(*string k)
removes the given key from the &quot;uctx&quot; context key; if no argument is provided, then the &quot;uctx&quot; contex...
HttpServer::AbstractHttpRequestHandler::staticNotificationCleanup
static staticNotificationCleanup()
removes the thread-local data key in case the object is destroyed in another thread ...
HttpServer::AbstractHttpRequestHandler::makeResponse
static hash makeResponse(int code, string fmt)
creates a hash for an HTTP response with the response code and the response message body as a formatt...
HttpServer::AbstractHttpRequestHandler::make400
static hash make400(string fmt)
creates a hash for an HTTP 400 error response with the response message body as a string ...
HttpServer::AbstractHttpRequestHandler::restoreThreadLocalData
restoreThreadLocalData(*hash data)
called after handleRequest() with any data returned from saveThreadData()
HttpServer::AbstractStreamRequest::recv
private nothing recv(hash v)
this is the primary callback for receiving chunked data; data will be logged, and then recvImpl() is ...
HttpServer::AbstractStreamRequest::timeout_ms
timeout timeout_ms
send and receive timeout
Definition: HttpServerUtil.qm.dox.h:371
HttpServer::AbstractHttpSocketHandler::stop
stop()
called from the HTTP server when the socket should be closed due to an external request; the start() ...
HttpServer::AbstractStreamRequest::cx
hash cx
the call context variable
Definition: HttpServerUtil.qm.dox.h:365
HttpServer::AbstractStreamRequest::s
Socket s
the Socket object for the response
Definition: HttpServerUtil.qm.dox.h:363
HttpServer::AbstractStreamRequest::sendImpl
private any sendImpl()
callback method for sending chunked data; the default implementation in this base class does nothing ...
HttpServer::HttpServerVersion
const HttpServerVersion
version of the HttpServer&#39;s implementation
Definition: HttpServerUtil.qm.dox.h:78
HttpServer::AbstractHttpRequestHandler::staticPersistenceCleanup
static staticPersistenceCleanup()
removes the thread-local data key in case the object is destroyed in another thread ...
HttpServer::AbstractHttpSocketHandler::constructor
constructor(*AbstractAuthenticator auth)
create the object optionally with the given AbstractAuthenticator
HttpServer::PermissiveAuthenticator::authenticateRequest
*hash authenticateRequest(HttpListenerInterface listener, hash hdr, reference cx)
primary method called to authenticate each request
HttpServer::parse_uri_query
hash parse_uri_query(string path)
parses a URI path for a arguments and a method; where the method is the part of the path before the f...
HttpServer::AbstractStreamRequest::listener
HttpListenerInterface listener
an HttpListenerInterface object for the listener serving the request for logging purposes ...
Definition: HttpServerUtil.qm.dox.h:359
HttpServer::AbstractHttpRequestHandler::encodeBody
static binary encodeBody(string ce, data body)
encodes a message body with content-encoding
HttpServer::AbstractHttpRequestHandler::getLogMessage
static *string getLogMessage(hash cx, hash api, reference params, *reference args)
helper method for handling log messages
HttpServer::AbstractLogger
this abstract class defines the interface for classes that provide logging methods ...
Definition: HttpServerUtil.qm.dox.h:227
HttpServer::HttpListenerInterface::addUserThreadContext
abstract addUserThreadContext(hash uctx)
adds user-defined data to be returned in the &quot;uctx&quot; context key when serving requests from this liste...
HttpServer::DefaultTimeout
const DefaultTimeout
default timeout in ms
Definition: HttpServerUtil.qm.dox.h:84
HttpServer::AbstractStreamRequest::send
private any send()
this is the primary callback for sending chunked responses; first sendImpl() is called to get the raw...
HttpServer::AbstractHttpSocketHandler
abstract class that all HTTP dedicated socket handler objects must inherit from
Definition: HttpServerUtil.qm.dox.h:650
HttpServer::AbstractUrlHandler
abstract class for HTTP request handlers anchored at a specific URL
Definition: HttpServerUtil.qm.dox.h:626
HttpServer::AbstractHttpRequestHandler::decodeBody
static data decodeBody(string ce, binary body, *string enc)
decodes a message body with content-encoding
HttpServer::AbstractHttpRequestHandler::handleRequest
hash handleRequest(hash cx, hash hdr, *data body)
will be called when a request is received that should be directed to the handler
HttpServer::LP_LEVELMASK
const LP_LEVELMASK
mask for the log level
Definition: HttpServerUtil.qm.dox.h:199
HttpServer::AbstractStreamRequest::getResponseHeaderMessage
private hash getResponseHeaderMessage()
this method returns the response message description hash by calling getResponseHeaderMessageImpl() ...
HttpServer::AbstractHttpRequestHandler::constructor
constructor(*AbstractAuthenticator n_auth, softbool n_stream=False)
create the object optionally with the given AbstractAuthenticator
HttpServer::HttpServerString
const HttpServerString
default HTTP server string
Definition: HttpServerUtil.qm.dox.h:81
HttpServer::AbstractHttpRequestHandler::timeout_ms
timeout timeout_ms
send and receive socket timeout in milliseconds
Definition: HttpServerUtil.qm.dox.h:489
HttpServer::AbstractHttpRequestHandler::decompress_to_string
bool decompress_to_string
if automatically decompressed POSTed data should be converted to a string (if False, then it will be decompressed to a binary)
Definition: HttpServerUtil.qm.dox.h:483
HttpServer::AbstractStreamRequest::handleRequest
hash handleRequest()
handles the request
HttpServer::AbstractAuthenticator::authenticate
authenticate(string user, string pass="")
called to authenticate a user for a connection
HttpServer::AbstractHttpRequestHandler::setPersistent
setPersistent(bool p=True)
called externally to notify the handler that the connection will be persistent
HttpServer::AbstractHttpRequestHandler::NotificationThreadKey
const NotificationThreadKey
thread-local key string for notification callbacks
Definition: HttpServerUtil.qm.dox.h:492
HttpServer::AbstractLogger::logError
abstract logError(string fmt)
called to log error information to the registered error log code
HttpServer::AbstractHttpRequestHandler::saveThreadLocalData
*hash saveThreadLocalData()
called before handleRequest() any data returned here will be given to restoreThreadLocalData() after ...
HttpServer::AbstractHttpRequestHandler::getStreamRequestImpl
private AbstractStreamRequest getStreamRequestImpl(HttpListenerInterface listener, Socket s, hash cx, hash hdr, *data body)
returns the AbstractStreamRequest object for handling chunked requests
HttpServer::AbstractLogger::logArgs
logArgs(*softlist args)
calls log() with the given args
HttpServer::http_set_reply_headers
nothing http_set_reply_headers(Socket s, hash cx, reference rv, *string server_string)
helper function for setting HTTP response headers
HttpServer::AbstractAuthenticator::authenticateByIP
authenticateByIP(string ip, reference user)
called when the connection requires authentication, but no authentication credentials were supplied...
hash
hash hash(object obj)
HttpServer::AbstractUrlHandler::url_root
string url_root
root part of URL for matching requests
Definition: HttpServerUtil.qm.dox.h:631
HttpServer::AbstractHttpRequestHandler::persistentClosed
nothing persistentClosed()
called externally when a persistent connection is closed
HttpServer::AbstractHttpRequestHandler::redirect
static hash redirect(hash cx, hash hdr, string path)
generates a redirect hash for the given path
HttpServer::AbstractHttpRequestHandler::PersistenceThreadKey
const PersistenceThreadKey
thread-local key string for the persistent flag
Definition: HttpServerUtil.qm.dox.h:495
HttpServer::AbstractHttpSocketHandler::lsh
hash lsh
hash of listener stop flags
Definition: HttpServerUtil.qm.dox.h:661
HttpServer::AbstractStreamRequest::body
any body
any message body given in a non-chunked request; could already be deserialized
Definition: HttpServerUtil.qm.dox.h:369
HttpServer::AbstractHttpRequestHandler::isPersistent
bool isPersistent()
returns True if the current connection is persistent, False if not
HttpServer::AbstractHttpRequestHandler::checkPersistent
private nothing checkPersistent(hash cx, hash hdr)
this method will throw an exception if a persistent connection cannot be granted