The Erlang Scripting Interface (ESI) provides a tight and
efficient interface to the execution of Erlang functions. Erlang
functions can be executed with two alternative schemes,
eval
and erl
. Both of these schemes can utilize
the functionality in an Erlang node efficiently.
Even though the server supports CGI-1.1 the use of the Erlang Scripting Interface (ESI) is encouraged for reasons of efficiency. CGI is resource intensive because of it's design. CGI requires the server to fork a new OS process for each executable it needs to start.
An Erlang function can be written and executed as a CGI script
by using erl_call(3)
in the erl_interface library, for
example. The cost is a forked OS process, as described
above. This is a waste of resources, at least when the Web
server itself is written in Erlang (as in this case).
The following config directives are described:
The erl
scheme is designed to mimic plain CGI, but
without the extra overhead. An URL which calls an Erlang
erl
function has the following syntax (regular
expression):
http://your.server.org/***/Mod[:/]Func(?QueryString|/PathInfo)
The module (Mod
) referred to must be found in the code
path, and it must define a function (Func
) with an arity
of two or three i.e. Func(Env,Input)
or Func(SessionID,Env,Input). Env
contains
information about the connecting client (see below), and
Input
the QueryString
or PathInfo
as
defined in the
CGI specification.
SessionID is a identifier that is used to send parts
of the web page back to the user through the function mod_esi:deliver/2
***
above depends on how the
ErlScriptAlias config
directive has been used. Data returned from the function with arity of two must
furthermore take the form as specified in the
CGI specification.
It is preferable to use the callback function with an arity of three, since the function can send the data back to the clients in parts instead of generating the whole page before it is sent. The Web server sends the data back to HTTP/1.1 compliant clients with chunked encoding this means that the Content-Length header field is not necessary, and should indeed be avoided.
mod_esi assumes that if the first chunk of data delivered to the client through the function
mod_esi:deliver/2
contains all HTTP-header fields the script will generate. I the first
chunk does not contain the string "\r\n\r\n"c
mod_esi assumes that the script not will
generate any header data.
Take a look at httpd_example.erl
in the
code release (UNIX: $INETS/src, Windows: %INETS\src
) for
a clarifying example. Start an example server as described in
httpd:start/0 and test the
following from a browser (The server name for your example
server will differ!):
http://your.server.org:8888/cgi-bin/erl/httpd_example/newformat
httpd_example:newformat/3
Something like this will promptly be shown in the browser:
This new format is nice. This new format is nice. This new format is nice.
http://your.server.org:8888/cgi-bin/erl/httpd_example/get
httpd_example:get/2
and two input fields and a Submit button will promptly be
shown in the browser. Enter text into the input fields and
click on the Submit button. Something like this will promptly
be shown in the browser:
Environment: [{query_string,"input1=blaha&input2=blaha"}, {server_software,"eddie/2.2"}, {server_name,"localhost"}, {gateway_interface,"CGI/1.1"}, {server_protocol,"HTTP/1.0"}, {server_port,8080}, {request_method,"GET"}, {remote_addr,"127.0.0.1"}, {script_name,"/cgi-bin/erl/httpd_example:get?input1=blaha& input2=blaha"}, {http_accept_charset,"iso-8859-1,*,utf-8"}, {http_accept_language,"en"}, {http_accept,"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*"}, {http_host,"localhost:8080"}, {http_user_agent, "Mozilla/4.03 [en] (X11; I; Linux 2.0.30 i586)"}, {http_connection,"Keep-Alive"}, {http_referer, "http://localhost:8080/cgi-bin/erl/ httpd_example/get"}] Input: input1=blaha&input2=blaha Parsed Input: [{"input1","blaha"},{"input2","blaha"}]
http://your.server.org:8888/cgi-bin/erl/httpd_example:post
httpd_example:post/2
. The
same thing will happen as in the example above but the HTTP POST
method will be used instead of the HTTP GET method.
http://your.server.org:8888/cgi-bin/erl/httpd_example:yahoo
httpd_example:yahoo/2
and the Yahoo! site will
promptly be shown in your browser.
httpd:parse_query/1 is
used to generate the If a client closes the connection prematurely a message will
be sent to the function, that is either |
The http://your.server.org/eval?httpd_example: print(atom_to_list(apply(erlang,halt,[]))) which effectively will close down the Erlang node, that is
use the Today there are no good way of solving this problem and therefore Eval Scheme may be removed in future release-s of Inets. |
The eval
scheme is straight-forward and does not
mimic the behavior of plain CGI. An URL which calls an Erlang
eval
function has the following syntax:
http://your.server.org/***/Mod:Func(Arg1,...,ArgN)
The module (Mod
) referred to must be found in the code
path, and data returned by the function (Func
) is passed
back to the client. ***
depends on how the EvalScriptAlias config directive
has been used. Data returned from the function must furthermore
take the form as specified in the
CGI specification.
Take a look at httpd_example.erl
in the
code release (UNIX: $INETS/src, Windows: %INETS\src
) for
an example. Start an example server as described in
httpd:start/0 and test the
following from a browser (The server name for your example
server will differ!):
http://your.server.org:8888/eval?httpd_example:print("Hi!")
httpd_example:print/1
and "Hi!" will promptly be shown in your browser.
Syntax: ErlScriptAlias
url-path allowed-module allowed-module ...
Default: - None -
Module: mod_esi(3)
ErlScriptAlias
marks all URLs matching url-path
as erl scheme scripts. A matching
URL is mapped into a specific module and function. The module
must be one of the allowed-module
:s. For example:
ErlScriptAlias /cgi-bin/hit_me httpd_example md4
and a request to
http://your.server.org/cgi-bin/hit_me/httpd_example:yahoo
would refer to httpd_example:yahoo/2
. Refer to the
Erl Scheme description above.
Syntax: ErlScriptNoCache
true | false
Default: false
Module: mod_esi(3)
If ErlScriptNoCache
is set to true the server will add
http header fields that prevents proxies from caching the page.
This is generally a good idea for dynamic content, since the
content often vary between each request.
ErlScriptNoCache true
Syntax: ErlScriptTimeout
seconds
Default: 15
Module: mod_esi(3)
If ErlScriptTimeout
sets the time in seconds the server
will wait between each chunk of data is delivered through mod_esi:deliver/2
when the new Erl Scheme format, that takes three argument is used.
ErlScriptTimeout 15
Syntax: EvalScriptAlias
url-path allowed-module allowed-module ...
Default: - None -
Module: mod_esi(3)
EvalScriptAlias
marks all URLs matching url-path
as eval scheme scripts. A matching
URL is mapped into a specific module and function. The module
must be one of the allowed-module
:s. For example:
EvalScriptAlias /cgi-bin/hit_me_to httpd_example md5
and a request to
http://your.server.org/cgi-bin/hit_me_to/httpd_example:print("Hi!")
would refer to httpd_example:print/1
. Refer to the
Eval Scheme description above.
Uses the following EWSAPI interaction data, if available:
{remote_user,RemoteUser}
Exports the following EWSAPI interaction data, if possible:
{mime_type,MimeType}
MimeType
as defined in the
Mime Type Settings
section of httpd_core(3)
.
Uses the following EWSAPI functions:
deliver(SessionID, Data) -> ok | {error,Reason}
Types:
SessionID = term()
Data = string()
Reason = term()
This function is only intended to be used from functions called by the Erl Scheme interface to deliver parts of the content to the user.
Sends data from a Erl Scheme script back to the client. Note that if any HTTP-header fields will be sent back to the client they must be in the first call to deliver/2. Do not assume anything about the data type of SessionID, the SessionID must be the SessionID from the Erl Scheme call.
Module:Function(Env, Input)-> Response
Types:
Env = [EnvironmentDirectives] ++ ParsedHeader
EnvironmentDirectives = {Key,Value}
Key = query_string | content_length, server_software, gateway_interface,
server_protocol, server_port, request_method, remote_addr, script_name.
<v>Input = Response = string()
The Module
must be found in the code path and export Function
with an arity
of two. An erlScriptAlias must also be set up in the configuration file for the Web server.
If the HTTP request is a post request and a body is sended then content_length will be the length of the posted data. If get is used query string will be the data after ? in the url.
ParsedHeader is the HTTP request as a key value tuple list. The keys in parsed header will be the in lower case.
This callback format consumes quite much memory since the whole response must be generated before it is sent to the user. Therefore it is better to use the callback function with an arity of three.
Module:Function(SessionID, Env, Input)-> void
Types:
SessionID = term()
Env = [EnvironmentDirectives] ++ ParsedHeader
EnvironmentDirectives = {Key,Value}
Key = query_string | content_length, server_software, gateway_interface,
server_protocol, server_port, request_method, remote_addr, script_name.
<v>Input = Response = string()
For information about Environment and Input see Module:Function/2
above. SessionID is a
identifier the server use when deliver/2
is called, do not assume any-thing about the datatype.
Use this callback function to dynamicly generate dynamic web content. when a part of the page is
generated send the data back to the client through deliver/2
. Note that the first chunk of data
sent to the client must at least contain all HTTP header fields that the response will generate. If the
first chunk not contains End of HTTP header that is "\r\n\r\n"
the server will assume that
no HTTP header fields will be generated.