Mainly specifies the Erlang Webserver callback API but also provide some test and admin. functionality.
ModData = #mod{}
-record(mod, { data = [], socket_type = ip_comm, socket, config_db, method, absolute_uri, request_uri, http_version, request_line, parsed_header = [], entity_body, connection }).
The fields of the mod
record has the following meaning:
data
[{InteractionKey,InteractionValue}]
is used to
propagate data between modules. Depicted
interaction_data()
in function type declarations.
socket_type
socket_type()
,
Indicates whether it is a ip socket or a ssl socket.
socket
ip_comm
or ssl
format
depending on the socket_type
.
config_db
config_db()
in function type
declarations.
method
"GET" | "POST" | "HEAD" | "TRACE"
, that is the
HTTP metod.
absolute_uri
"http://ServerName:Part/cgi-bin/find.pl?person=jocke"
request_uri
Request-URI
as defined
in RFC 1945, for example "/cgi-bin/find.pl?person=jocke"
http_version
HTTP
version of the
request, that is "HTTP/0.9", "HTTP/1.0", or "HTTP/1.1".
request_line
Request-Line
as
defined in RFC 1945, for example "GET
/cgi-bin/find.pl?person=jocke HTTP/1.0"
.
parsed_header
[{HeaderKey,HeaderValue}]
, parsed_header
contains
all HTTP header fields from the HTTP-request stored in a list as
key-value tuples. See RFC 2616 for a listing of all header
fields. For example the date field would be stored as:
{"date","Wed, 15 Oct 1997 14:35:17 GMT"}. RFC 2616 defines
that HTTP is a case insensitive protocol and the header fields
may be in lowercase or upper case. Httpd will ensure that all
header field names are in lowe case
.
entity_body
Entity-Body
as defined
in RFC 2616, for example data sent from a CGI-script using the
POST method.
connection
true | false
If set to true the connection to the
client is a persistent connections and will not be closed when
the request is served.
Module:do(ModData)-> {proceed, OldData} | {proceed, NewData} | {break, NewData} | done
Types:
OldData = list()
NewData = [{response,{StatusCode,Body}}] | [{response,{response,Head,Body2}}] |
[{response,{already_sent,Statuscode,Size}]
StausCode = integer()
Body = io_list() | nobody | {Fun, Arg}
Head = [HeaderOption]
HeaderOption = {Key, Value} | {code, StatusCode}
Key = allow | cache_control | content_MD5 | content_encoding
| content_encoding | content_language | content_length
| content_location | content_range | content_type | date | etag
| expires | last_modified | location | pragma | retry_after |
server | trailer | transfer_encoding
Value = string()
Fun = fun( Arg ) -> sent| close | Body
Arg = [term()]
When a valid request reaches httpd it calls do/1
in
each module defined by the Modules configuration
directive. The function may generate data for other modules
or a response that can be sent back to the client.
The field data
in ModData is a list. This list will be
the list returned from the from the last call to
do/1
.
Body
is the body of the http-response that will be
sent back to the client an appropriate header will be
appended to the message. StatusCode
will be the
status code of the response see RFC2616 for the appropriate
values.
Head
is a key value list of HTTP header fields. the
server will construct a HTTP header from this data. See RFC
2616 for the appropriate value for each header field. If the
client is a HTTP/1.0 client then the server will filter the
list so that only HTTP/1.0 header fields will be sent back
to the client.
If Body2
is returned and equal to {Fun,Arg}
The Web server will try apply/2
. on Fun
with
Arg
as argument and excpect that the fun either
returns a list (Body)
that is a HTTP-repsonse or the
atom sent if the HTTP-response is sent back to the
client. If close is returned from the fun something has gone
wrong and the server will signal this to the client by
closing the connection.
Types:
Line = string()
Context = NewContext = DirectiveList = [Directive]
Directive = {DirectiveKey , DirectiveValue}
DirectiveKey = DirectiveValue = term()
Reason = term()
load/2
takes a row Line
from the configuration
file and tries to convert it to a key value tuple. If a
directive is dependent on other directives, the directive
may create a context. If the directive is not dependent on
other directives return {ok, [], Directive}
,
otherwise return a new context, that is {ok,
NewContext}
or {ok, Context Directive}. If {error,
Reason}
is returned the configuration directive is
assumed to be invalid.
Types:
DirectiveList = [{DirectiveKey, DirectiveValue}]
DirectiveKey = DirecitveValue = term()
Context = NewContext = DirectiveList = [Directive]
Directive = {Key , Value}
Reason = term()
When all rows in the configuration file is read the function
store/2
is called for each configuration
directive. This makes it possible for a directive to alter
other configuration directives. DirectiveList
is a
list of all configuration directives read in from load. If
a directive may update other configuration directives then
use this function.
Module:remove(ConfigDB)-> ok | {error, Reason}
Types:
ConfigDB = ets_table()
Reason = term()
When httpd shutdown it will try to execute remove/1
in each ewsapi module. The ewsapi programmer may use this to
close ets tables, save data, or close down background
processes.
parse_query(QueryString) -> ServerRet
Types:
QueryString = string()
ServerRet = [{Key,Value}]
Key = Value = string()
parse_query/1
parses incoming data to erl
and
eval
scripts (See mod_esi(3)) as defined in the standard
URL format, that is '+' becomes 'space' and decoding of
hexadecimal characters (%xx
).
start()
start(Config) -> ServerRet
start_link()
start_link(Config) -> ServerRet
Types:
Config = string() | HttpdOptions
ServerRet = {ok,Pid} | ignore | {error,EReason} | {stop,SReason}
Pid = pid()
EReason = {already_started, Pid} | term()
SReason = string()
HttpdOptions = {file,string()} , {debug,Debug}? , {accept_timeout,integer()}?
Debug = disable | [DebugOptions]
DebugOptions = {all_functions,Modules} | {exported_functions,Modules} | {disable,Modules}
Modules = [atom()]
start/1
and start_link/1
starts a server
as specified in the given ConfigFile
. The ConfigFile
supports a number of config directives specified below.
start/0
and start/0
starts a server as specified
in a hard-wired config file, that is
start("/var/tmp/server_root/conf/8888.conf")
. Before
utilizing start/0
or start_link/0
, copy the
example server
root (UNIX: $INETS_ROOT/examples/server_root/, Windows: %INETS_ROOT%\examples\server_root\
) to a specific installation directory (UNIX: /var/tmp/, Windows: X:\var\tmp\
)
and you have a server running in no time.
If you copy the example server root to the specific
installation directory it is furthermore easy to start an
SSL enabled server, that is
start("/var/tmp/server_root/conf/ssl.conf")
.
restart()
restart(Port) -> ok | {error,Reason}
restart(ConfigFile) -> ok | {error,Reason}
restart(Address,Port) -> ok | {error,Reason}
Types:
Port = integer()
Address = {A,B,C,D} | string() | undefined
ConfigFile = string()
Reason = term()
restart
restarts the server and reloads its config file.
The follwing directives cannot be changed: BindAddress, Port and SocketType. If these should be changed, then a new server should be started instead.
Before the |
stop()
stop(Port) -> ServerRet
stop(ConfigFile) -> ServerRet
stop(Address,Port) -> ServerRet
Types:
Port = integer()
Address = {A,B,C,D} | string() | undefined
ConfigFile = string()
ServerRet = ok | not_started
stop/2
stops the server which listens to the specified
Port
on Address
.
stop(integer())
stops a server which listens to a specific
Port
.
stop(string())
extracts BindAddress
and Port
from the config file and stops the server which listens to the
specified Port
on Address
.
stop/0
stops a server which listens to port 8888, that is
stop(8888)
.
block() -> ok | {error,Reason}
block(Port) -> ok | {error,Reason}
block(ConfigFile) -> ok | {error,Reason}
block(Address,Port) -> ok | {error,Reason}
block(Port,Mode) -> ok | {error,Reason}
block(ConfigFile,Mode) -> ok | {error,Reason}
block(Address,Port,Mode) -> ok | {error,Reason}
block(ConfigFile,Mode,Timeout) -> ok | {error,Reason}
block(Address,Port,Mode,Timeout) -> ok | {error,Reason}
Types:
Port = integer()
Address = {A,B,C,D} | string() | undefined
ConfigFile = string()
Mode = disturbing | non_disturbing
Timeout = integer()
Reason = term()
This function is used to block a server. The blocking can be done in two ways, disturbing or non-disturbing.
By performing a disturbing block, the server is blocked forcefully and all ongoing requests are terminated. No new connections are accepted. If a timeout time is given then on-going requests are given this much time to complete before the server is forcefully blocked. In this case no new connections is accepted.
A non-disturbing block is more gracefull. No new connections are accepted, but the ongoing requests are allowed to complete. If a timeout time is given, it waits this long before giving up (the block operation is aborted and the server state is once more not-blocked)
Default mode is disturbing.
Default port is 8888
unblock() -> ok | {error,Reason}
unblock(Port) -> ok | {error,Reason}
unblock(ConfigFile) -> ok | {error,Reason}
unblock(Address,Port) -> ok | {error,Reason}
Types:
Port = integer()
Address = {A,B,C,D} | string() | undefined
ConfigFile = string()
Reason = term()
Unblocks a server. If the server is already unblocked this is a no-op. If a block is ongoing, then it is aborted (this will have no effect on ongoing requests).