servlet

NAME SYNOPSIS DESCRIPTION SERVER LISTENER HTTP_SERVLET / HTTP_REQUEST STREAM_SERVLET / STREAM_REQUEST DATAGRAM_SERVLET / DATAGRAM_REQUEST SERVLET / REQUEST SOURCE PARAMETERS TABLE STRINGVEC COOKIEVEC COOKIE PTRVEC OB UTIL FACTORY SEE ALSO AUTHOR

NAME

servlet - C servlet API

SYNOPSIS

#include <servlet.h>

DESCRIPTION

This is the API used by the coleman web server.

A servlet is a small C program that runs within a server. Servlets receive and respond to requests from clients.

Servlets are contained in listeners, which in turn are contained in servers. Servlets come in different varieties, which are related to each other in a single-inheritance tree. Each variety of servlet has a corresponding variety of request:
servlet request
datagram_servlet datagram_request
stream_servlet stream_request
http_servlet http_request
There are also a few support types such as cookies, parameters, and sources. Sources also come in different varieties, organized in an inheritance tree:
source
stringsource
filesource
filereadsource
filemmapsource
If this all sounds like an object-oriented class hierarchy, that’s because it’s loosely based on the original Java servlet classes.

Below is a list of everything available in the API. We start with server, listener, and http_servlet/http_request, which are the important ones. After that are the less important classes, the data structures, and some utility routines.

SERVER

A server is a group of listeners.
server* server_make( parameters* initial_params );
void server_free( server* svr );
void server_init( server* svr, parameters* initial_params );
void server_term( server* svr );

Create / destroy / initialize / terminate a server.

const char* server_get_server_info( const server* svr );

Returns a string describing the server.

const char* server_get_server_url( const server* svr );

Returns a URL for information about the server.

void server_add_content_encoding( server* svr, const char* ext, const
char* content_encoding);
void server_add_content_type( server* svr, const char* ext, const char*
content_type);

Adds a content-encoding or content-type mapping.

void server_add_listener( server* svr, listener* lst );

Adds a listener.

void server_get_content_encoding( const server* svr, const char* path,
char* str, size_t size );
void server_get_content_type( const server* svr, const char* path,
char* str, size_t size );

Looks up the content-encoding or content-type for a given path. Note that the result is returned in str instead of as the return value.

void server_serve( server* svr );

The "main loop" of a server - reads requests and dispatches them to listeners.

util_bool server_handoff( server* svr, request* req, source* src );

This is a special back-door interface that a servlet can use to offer a request to the server to handle on its own. The server may or may not accept it. If the server returns util_false, indicating that it does not accept the request, the servlet should continue serving it as usual.

void server_log( const server* svr, const char* message );

Writes a message to the log file.

LISTENER

A listener is a group of servlets, listening on a specified port.
listener* listener_make( server* svr, parameters* initial_params );
void listener_free( listener* lst );
void listener_init( listener* lst, server* svr, parameters*
initial_params );
void listener_term( listener* lst );

Create / destroy / initialize / terminate a listener.

void listener_add_servlet( listener* lst, servlet* svt, const char*
pattern );

Adds a servlet to the listener. The pattern gets matched against a request’s URL to find the right servlet to run. If the pattern is null then it matches any request.

server* listener_get_server( const listener* lst );

Returns the server that contains this listener.

const char* listener_get_local_address( const listener* lst );

Returns the local address that the listener is listening on. If it’s null then the listener is listening on all local addresses.

int listener_get_port( const listener* lst );

Returns the port that the listener is listening on.

const char* listener_get_listener_info( const listener* lst );

Returns a string describing the listener.

void listener_dispatch( listener* lst, int listen_fd );

Accepts a new connecton from the listen_fd and dispatches it to an appropriate servlet.

void listener_log( const listener* lst, const char* message );

Writes a message to the log file.

HTTP_SERVLET / HTTP_REQUEST

Sub-classes of stream_servlet and stream_request for HTTP.
http_servlet* http_servlet_make( parameters* initial_params, listener*
lst, const char* pattern );
void http_servlet_free( http_servlet* httsvt );
void http_servlet_init( http_servlet* httsvt, parameters*
initial_params, listener* lst, const char* pattern );
void http_servlet_term( http_servlet* httsvt );

Create / destroy / initialize / terminate a http_servlet.

void http_servlet_do_get( http_servlet* httsvt, http_request* httreq );
void http_servlet_do_post( http_servlet* httsvt, http_request* httreq
);
void http_servlet_do_put( http_servlet* httsvt, http_request* httreq );
void http_servlet_do_delete( http_servlet* httsvt, http_request* httreq
);
void http_servlet_do_trace( http_servlet* httsvt, http_request* httreq
);

Handlers for the standard HTTP methods.

http_request* http_request_make( listener* lst, int conn_fd,
util_sockaddr* from_addrP );
void http_request_free( http_request* httreq );
void http_request_init( http_request* httreq, listener* lst, int
conn_fd, util_sockaddr* from_addrP );
void http_request_term( http_request* httreq );

Create / destroy / initialize / terminate a http_request.

util_bool http_request_auth_check( const http_request* httreq, const
char* path, util_bool is_dir );

Does an authorization check on the given path. If there’s no restrictions or if authorization is successful, returns util_true; if authorization fails, returns util_false.

util_bool http_request_referrer_check( const http_request* httreq );

Does a referrer check. If non-local referrers are prohibited and the request has one, returns util_false.

util_bool http_request_headers_only( const http_request* httreq );

Whether the request is for headers only, i.e. the "HEAD" method.

const parameters* http_request_get_headers( const http_request* httreq
);

Returns all the request headers.

const char* http_request_get_header( const http_request* httreq, const
char* name );

Returns the named request header, or null if it doesn’t exist.

int http_request_get_int_header( const http_request* httreq, const
char* name );

Returns the named request header as an int.

int64_t http_request_get_int64_header( const http_request* httreq,
const char* name );

Returns the named request header as an int64_t.

time_t http_request_get_date_header( const http_request* httreq, const
char* name );

Returns the named request header as a date.

const cookievec* http_request_get_cookies( const http_request* httreq
);

Returns all the request cookies.

const cookie* http_request_get_cookie( const http_request* httreq,
const char* name );

Returns the named request cookie, or null if it doesn’t exist.

const char* http_request_get_method( const http_request* httreq );

Returns the request method - "GET", POST", etc.

const char* http_request_get_request_uri( const http_request* httreq );

Returns the request URI - that’s the path part.

const char* http_request_get_version( const http_request* httreq );

Returns the HTTP version, typically either "HTTP/1.0" or "HTTP/1.1".

const char* http_request_get_request_url( const http_request* httreq );

Returns the full request URL.

off_t http_request_get_content_length( const http_request* httreq );

Returns the length of the request body - the part after the headers - or -1 if there isn’t one. Typically "GET" requests do not have a body and "POST" requests do.

const char* http_request_get_content_type( const http_request* httreq
);

Returns the content-type of the request body, or null if there isn’t one.

const char* http_request_get_query_string( const http_request* httreq
);

Returns the request’s query string - the part after the ? - or null if there isn’t one.

const char* http_request_get_auth_type( const http_request* httreq );

Returns the authorization type, or null if the request is not authenticated.

const char* http_request_get_remote_user( const http_request* httreq );

Returns the authenticated username, or null if the request is not authenticated.

const parameters* http_request_get_request_params( const http_request*
httreq );

Parses any request parameters, either in a query string or in a "POST" body, and returns them.

void http_request_set_status( http_request* httreq, status_code status,
const char* title, const char* message );

Sets the response status. If title and/or message are null they get default values.

void http_request_set_content_length( http_request* httreq, off_t len
);

Declares how long the response will be. There’s no enforecement of this, if you end up sending more or fewer bytes no one will stop you. But something may break on the receiving end.

void http_request_set_content_encoding( http_request* httreq, const
char* content_encoding );

Set the response’s content-encoding.

void http_request_set_content_type( http_request* httreq, const char*
content_type );

Sets the response’s content-type.

void http_request_add_header( http_request* httreq, const char* name,
const char* value );

Add a header to the response.

void http_request_add_int_header( http_request* httreq, const char*
name, int value );

Add an int header to the response.

void http_request_add_int64_header( http_request* httreq, const char*
name, int64_t value );

Add an int64_t header to the response.

void http_request_add_date_header( http_request* httreq, const char*
name, time_t value );

Add a date header to the response.

void http_request_add_cookie( http_request* httreq, cookie* cky );

Add a cookie to the response.

void http_request_send_error( http_request* httreq, status_code status,
const char* title, const char* message );

Send an error response. If the title and/or message are null they get default values.

void http_request_send_redirect( http_request* httreq, const char*
location );

Send a redirect (302 Found) response.

void http_request_set_keep_alive( http_request* httreq, util_bool
keep_alive );

Sets or clears the keep-alive flag, which tells the server to reuse the same connection for another request. Normally this is set according to the client sending or not sending a "Connection: keep-alive" header, but in some cases a servlet may need to override it.

STREAM_SERVLET / STREAM_REQUEST

Sub-classes of servlet and request for TCP protocols.
stream_servlet* stream_servlet_make( parameters* initial_params,
listener* lst, const char* pattern );
void stream_servlet_free( stream_servlet* strsvt );
void stream_servlet_init( stream_servlet* strsvt, parameters*
initial_params, listener* lst, const char* pattern );
void stream_servlet_term( stream_servlet* strsvt );

Create / destroy / initialize / terminate a stream_servlet.

stream_request* stream_request_make( listener* lst, int conn_fd,
util_sockaddr* from_addrP );
void stream_request_free( stream_request* strreq );
void stream_request_init( stream_request* strreq, listener* lst, int
conn_fd, util_sockaddr* from_addrP );
void stream_request_term( stream_request* strreq );

Create / destroy / initialize / terminate a stream_request.

FILE* stream_request_get_input_stream( stream_request* strreq );

Returns an input stream for reading the request.

FILE* stream_request_get_output_stream( stream_request* strreq );

Returns an output stream for writing the response.

DATAGRAM_SERVLET / DATAGRAM_REQUEST

Sub-classes of servlet and request for UDP protocols.
datagram_servlet* datagram_servlet_make( parameters* initial_params,
listener* lst, const char* pattern );
void datagram_servlet_free( datagram_servlet* dgmsvt );
void datagram_servlet_init( datagram_servlet* dgmsvt, parameters*
initial_params, listener* lst, const char* pattern );
void datagram_servlet_term( datagram_servlet* dgmsvt );

Create / destroy / initialize / terminate a datagram_servlet.

datagram_request* datagram_request_make( listener* lst, int conn_fd,
util_sockaddr* from_addrP );
void datagram_request_free( datagram_request* dgmreq );
void datagram_request_init( datagram_request* dgmreq, listener* lst,
int conn_fd, util_sockaddr* from_addrP );
void datagram_request_term( datagram_request* dgmreq );

Create / destroy / initialize / terminate a datagram_request.

const unsigned char* datagram_request_get_packet( const request* dgmreq
);

Returns the request packet.

size_t datagram_request_get_packet_length( const request* dgmreq );

Returns the request packet length.

void datagram_request_send_packet( request* dgmreq, const unsigned
char* packet, size_t len );

Sends a response packet.

SERVLET / REQUEST

Here are the base classes for servlets and requests. A servlet is the piece of code that handles requests. A request represents the client asking for some data.
servlet* servlet_make( parameters* initial_params, listener* lst, const
char* pattern );
void servlet_free( servlet* svt );
void servlet_init( servlet* svt, parameters* initial_params, listener*
lst, const char* pattern );
void servlet_term( servlet* svt );

Create / destroy / initialize / terminate a servlet.

listener* servlet_get_listener( const servlet* svt );

Returns the listener that contains this servlet.

void servlet_get_servlet_info( const servlet* svt );

Returns a string describing the servlet.

void servlet_service( servlet* svt, request* req );

The basic routine for handling a request.

void servlet_log( const servlet* svt, const char* message );

Writes a message to the log file.

request* request_make( listener* lst, int conn_fd, util_sockaddr*
from_addrP );
void request_free( request* req );
void request_init( request* req, listener* lst, int conn_fd,
util_sockaddr* from_addrP );
void request_term( request* req );

Create / destroy / initialize / terminate a request.

servlet* request_get_servlet( const request* req );

Returns the servlet that contains this request.

listener* request_get_listener( const request* req );

Returns the listener that contains this request.

void request_get_remote_addr( const request* req );

The IP address that the request came from.

void request_get_remote_host( const request* req );

The hostname that the request came from.

void request_get_scheme( const request* req );

The scheme is the part of a URL before the colon - typically "http" or "https".

void request_get_server_name( const request* req );

The hostname of the server.

void request_get_port( const request* req );

The port the request came in on.

void request_is_secure( const request* req );

Whether the request is using a secure protocol, such as SSL.

void request_set_lingering_close( const request* req, util_bool
lingering_close );

Sets or clears the lingering close flag, which tells the server to end this request with a lingering close because there may be unread data in the connection. The default is no lingering close.

void request_start( const request* req );

Read in a request .

void request_finish( const request* req );

Finish off a request.

void request_log( const request* req );

Writes a message to the log file.

SOURCE

A source represents bytes to be sent out over the net. There are a couple of sub-classes.
source* source_make( void );
void source_free( source* src );
void source_init( source* src );
void source_term( source* src );

Create / destroy / initialize / terminate a source.

util_bool source_next_hunk( source* src );

Prepares the next hunk of data for sending; return util_false if there isn’t any more.

unsigned char* source_get_hunk( source* src );

Returns a pointer to the current hunk of data to be sent.

off_t source_get_hunk_offset( source* src );

The offset of the current hunk within the full set of data.

off_t source_get_hunk_length( source* src );

The length of the current hunk.

string_source is a source backed by a string.
string_source* string_source_make( const char* str );
void string_source_free( string_source* strsrc );
void string_source_init( string_source* strsrc, const char* str );
void string_source_term( string_source* strsrc );

Create / destroy / initialize / terminate a string_source.

file_source is a source backed by a file. It can optionally represent a partial sub-range of the file; if range_offset and range_length are -1 then the full range is used.
file_source* file_source_make( int fd, off_t full_length, off_t
range_offset, off_t range_length );
void file_source_free( file_source* filsrc );
void file_source_init( file_source* filsrc, int fd, off_t full_length,
off_t range_offset, off_t range_length );
void file_source_term( file_source* filsrc );

Create / destroy / initialize / terminate a file_source.

file_read_source is a file_source that uses read(2).
find_read_source* find_read_source_make( int fd, off_t full_length,
off_t range_offset, off_t range_length );
void find_read_source_free( find_read_source* frdsrc );
void find_read_source_init( find_read_source* frdsrc, int fd, off_t
full_length, off_t range_offset, off_t range_length );
void find_read_source_term( find_read_source* frdsrc );

Create / destroy / initialize / terminate a find_read_source.

file_mmap_source is a file_source that uses mmap(2).
file_mmap_source* file_mmap_source_make( int fd, off_t full_length,
off_t range_offset, off_t range_length );
void file_mmap_source_free( file_mmap_source* fmmsrc );
void file_mmap_source_init( file_mmap_source* fmmsrc, int fd, off_t
full_length, off_t range_offset, off_t range_length );
void file_mmap_source_term( file_mmap_source* fmmsrc );

Create / destroy / initialize / terminate a file_mmap_source.

PARAMETERS

Parameters are a group of name-value pairs. The only unusual part is that there can be more than one value for a name. Oh and the names are case-insensitive.
parameters* parameters_make( int initial_size );
void parameters_free( parameters* params );
void parameters_init( parameters* params, int initial_size );
void parameters_term( parameters* params );

Create / destroy / initialize / terminate parameters.

void parameters_add( parameters* params, const char* name, const char*
value );

Add a name-value pair.

const char* parameters_get_value( const parameters* params, const char*
name );

Returns a value for the given name, or null if there are no values. You can use this when you know there is at most one value, or you don’t care which one of multiple values you get.

const stringvec* parameters_get_values( const parameters* params, const
char* name );

Returns all the values for the given name, or null if there are none.

const stringvec* parameters_get_names( const parameters* params );

Returns the names of all the parameters.

util_bool parameters_contains( const parameters* params, const char*
name );

Checks whether the given name is present.

TABLE

strtable* strtable_make( int initial_size );
void strtable_free( strtable* strtab );

Create / destroy a strtable.

int strtable_len( const strtable* strtab );

Get the current length of a strtable.

void strtable_add( strtable* strtab, const char* name, void* value );

Add an item to a strtable.

void* strtable_get( const strtable* strtab, int i );

Get an item by index.

void* strtable_find( const strtable* strtab, const char* name );

Get an item by name.

STRINGVEC

String vector.
stringvec* stringvec_make( int initial_size );
void stringvec_free( stringvec* strvec );

Create / destroy a stringvec.

int stringvec_len( const stringvec* strvec );

Get the current length of a stringvec.

void stringvec_add( stringvec* strvec, const char* str );

Add a string to a stringvec.

void stringvec_insert( stringvec* strvec, const char* str, int i );

Insert a string into a stringvec at a specified position.

char* stringvec_get( const stringvec* strvec, int i );

Get a string by index.

COOKIEVEC

A vector of cookies.
cookievec* cookievec_make( int initial_size );
void cookievec_free( cookievec* ckyvec );

Create / destroy a cookievec.

int cookievec_len( const cookievec* ckyvec );

Get the current length of a cookievec.

void cookievec_add( cookievec* ckyvec, cookie* cky );

Add a cookie to a cookievec.

cookie* cookievec_get( const cookievec* ckyvec, int i );

Get a cookie by index.

cookie* cookievec_find( const cookievec* ckyvec, const char* name );

Get a cookie by name.

COOKIE

An HTTP cookie.
cookie* cookie_make( const char* name, const char* value );
void cookie_free( cookie* cky );
void cookie_init( cookie* cky, const char* name, const char* value );
void cookie_term( cookie* cky );

Create / destroy / initialize / terminate a cookie.

cookie* cookie_copy( const cookie* cky );

Copy a cookie.

const char* cookie_get_name( const cookie* cky );
const char* cookie_get_value( const cookie* cky );
const char* cookie_get_comment( const cookie* cky );
const char* cookie_get_domain( const cookie* cky );
const char* cookie_get_path( const cookie* cky );
time_t cookie_get_max_age( const cookie* cky );
util_bool cookie_get_secure( const cookie* cky );

Get various attributes of a cookie.

void cookie_set_comment( cookie* cky, const char* comment );
void cookie_set_domain( cookie* cky, const char* domain );
void cookie_set_path( cookie* cky, const char* path );

Set various attributes of a cookie.

PTRVEC

A simple vector class. Only stores pointers.
ptrvec* ptrvec_make( int initial_size );
void ptrvec_free( ptrvec* vec );
void ptrvec_init( ptrvec* vec, int initial_size );
void ptrvec_term( ptrvec* vec );

Create / destroy / initialize / terminate a ptrvec. If initial_size is zero it uses a default.

int ptrvec_len( ptrvec* vec );

Find the length of a ptrvec.

void ptrvec_add( ptrvec* vec, void* ptr );

Add a pointer to the end of a ptrvec.

void ptrvec_insert( ptrvec* vec, void* ptr, int i );

Insert a pointer at a specified spot in a ptrvec.

void ptrvec_delete( ptrvec* vec, int i );

Remove a specified pointer from a ptrvec.

void* ptrvec_get( ptrvec* vec, int i );

Get a specified pointer from a ptrvec.

OB

The base class for all objects.
typedef enum { ... } ob_class;

An enum for all the classes in the class hierarchy. As this is hard-coded, the hierarchy is not really extensible.

ob* ob_make( void );
void ob_free( ob* o );
void ob_init( ob* o );
void ob_term( ob* o );

Create / destroy / initialize / terminate an ob. The _make / _free versions allocate and free storage, while the _init / _term versions operate on obs you have allocated yourself.

void ob_set_class( ob* o, ob_class oc );

Set an ob’s class.

ob_class ob_get_class( const ob* o );

Get an ob’s class.

util_bool ob_is_a( const ob* o, ob_class oc );

Check if an ob is, or inherits from, a given class.

UTIL

A few utility defs and routines.
util_min( a, b );

Returns the smaller of the two args.

util_max( a, b );

Returns the larger of the two args.

typedef util_bool;

Typedef for booleans, so we get type-checking.

typedef util_sockaddr;

Opaque type for sockaddrs.

void* util_malloc( size_t size );
void* util_realloc( void* ptr, size_t size );
char* util_strdup( const char* str );

Malloc routines with checking.

void util_strencode( char* to, size_t tosize, const char* from );

Copies and encodes a string.

void util_strdecode( char* to, const char* from );

Copies and decodes a string. It’s ok for from and to to be the same string.

long long util_atoll( const char* cp );
size_t util_strlcpy( char* dst, const char* src, size_t size );

In case the OS doesn’t have atoll() and strlcpy(), we include our own.

FACTORY

Finally, all servlets must include a factory routine with precisely this signature:
extern servlet* factory( parameters* params, listener* lst, const char* pattern );
The factory should create and initialize a servlet, do any necessary customization, and return it.

SEE ALSO

coleman(8)

AUTHOR

Copyright © 2011,2014 by Jef Poskanzer <jef@mail.acme.com>. All rights reserved.