Instaweb : Instant Web Publishing Tool
Instaweb : Instant Web Publishing Tool
======================================
By Noel Welsh (noelwelsh at gmail dot com)
This manual documents Instaweb version 2.1
Time-stamp: <2007-11-23 12:26:19 us>
Keywords: _instaweb_, _servlet_, _internet_, _web_
Introduction
============
Instaweb is a simple tool that makes it easier to run
servlets in the PLT web server.
It does the following:
- configures the web server to run a single servlet
- runs the web server in a handy interactive shell
Usage
=====
If your servlet is in a file called servlet.ss in the
current directory, you run your servlet in the web-server
running by simply requiring the Instaweb collection and
calling the instaweb function with no arguments:
(require (planet "instaweb.ss" ("schematics" "instaweb.plt" 2)))
(instaweb)
This will start the web server on port 8765 and listening
only to connections from the localhost (127.0.0.1). You can
view your servlet by visiting the URL:
http://127.0.0.1:8765/
You can override these defaults, and many others, by passing
keyword arguments to the instaweb function. For example, to
set the port:
(instaweb #:port 4567)
Or perhaps you want to use a different file name for your
servlet:
(instaweb #:servlet-path "my-servlet.ss")
If you give a relative path for the servlet, as above, it is
resolved relative to the value of the current-directory
parameter.
If you want to make your use of Instaweb unaffected by the
value of current-directory, use the instaweb-here macro,
which parameterizes current-directory to the directory of
the file containing the call:
(instaweb-here #:servlet-path "my-servlet.ss"
#:port 5678
#:listen-ip "127.0.0.1")
If you want to serve static files in addition to your
servlet you can put them in a directory called htdocs
(again, relative to the current-directory parameter) or
specify a different path to instaweb:
(instaweb #:htdocs-path '("public-html"))
Note that you give a list of paths, so you can specify
multiple directories. Files matching the path portion of
the request URL are searched for in these directories. If
no matching file is found control is passed to your servlet.
This means your servlet will receive all requests that do
not match a file.
If the instaweb function is not sufficient for your needs,
the component parts are exposed in the API on which you can
build your own abstractions.
API
===
> (instaweb [option] ...)
instaweb : [#:port integer]
[#:listen-ip (U string #f)]
[#:servlet-path (U path string)]
[#:htdocs-path (listof (U path string))]
[#:mime-types-path path]
[#:servlet-namespace (listof require-spec)]
->
void
All options are specified using keyword arguments and may be
given in any order. Paths are resolved relative to the
value of the current-directory parameter if they are not
absolute.
Port is an integer specifying the port the web server should
listen on. It defaults to 8765
Listen-ip is the IP address to listen on. A string
specifies a particular IP addresses, and #f indicates all
addresses. It defaults to 127.0.0.1
Servlet-path is the path to the file containing the servlet
code. It defaults to servlet.ss
Htdocs-path is a list of paths to the directories containing
static HTML, CSS, and other files. It defaults to the
single directory htdocs. The web-server is configured so
the htdocs paths are first searched first for files matching
the request URL before control is passed to your servlet.
Mime-types-path is the path to a file containing a mapping
from file extensions to MIME types. It defaults to an
Instaweb supplied file.
Servlet-namespace is a list of require expressions
specifying modules that should be copied into the servlet's
namespace. It defaults to any empty list. For example, the
following is a valid statement:
(instaweb #:servlet-namespace '((lib "etc.ss")))
This is principally useful for reducing memory usage and
sharing modules between servlets (future versions of
Instaweb will support running multiple servlets).
> (instaweb-here [option] ...)
Syntax
Arguments are as for instaweb above. All paths are resolved
relative to the directory of the file containing the
instaweb-here expression, otherwise this functions exactly
like the instaweb function.
> (make-dispatcher args)
make-dispatcher : (list [#:servlet-path (U path string)]
[#:htdocs-path (listof (U path string))]
[#:mime-types-path path]
[#:servlet-namespace (listof require-spec)])
-> dispatcher
Constructs a dispatcher given a list of arguments. The
meaning of the arguments is as for instaweb above.
> (run-server port listen-ip dispatcher-args)
run-server : integer (U string #f) (listof any) -> ( -> void)
Runs the web server using the given parameters. Returns a
thunk that, when called, shuts down the web server. The
dispatcher-args are passed to make-dispatcher above.
> (console-loop run-server)
console-loop : ( -> ( -> void)) -> void
Given a thunk that runs the web server (and returns a thunk
that shuts down said server) runs the Instaweb console to
control the web server.
Using the above procedures you can extend Instaweb in useful
ways. For example, if you want to run some code after the
web-server starts, you could write:
(define (my-run-server)
(begin0 (run-server port listen-ip dispatcher-args)
(do-my-stuff)))
(console-loop my-run-server)
Tips and Caveats
================
Note that unlike previous version of Instaweb your servlet
is not forced to reside under a URL beginning with
/servlets/<file-name>. If receives all requests that don't
match a file in the htdocs direcory.
Calling your servlet is the last step in the web-server
dispatching process. Your servlet should return a 404
response if it receives a URL it cannot process.
If you want to run a Instaweb launched servlet on a server
you probably don't want an interactive terminal. This is ok
-- Instaweb will detect when it doesn't have a terminal and
so avoid filling your logs with rubbish. Say run-servlet.ss
is the file that launches your servlet. The recommended way
to run such a setup on a server is:
mzscheme -qr run-servlet.ss
The important bit here is the 'r' flag, which runs MzScheme
without a REPL. You probably want to spawn a new process to
run MzScheme, and prevent signals from interferring with it,
a better line might be:
nohup mzscheme -qr run-servlet.ss &
Thanks
======
Matthew Flatt, Jens Axel Soegaard, and Dave Herman for
suggestions for dealing with a missing terminal, and
suspending the main thread
Eric Hanchow, for pointing out documentation typos
Dave Gurnell, for suggesting the switch to a dispatcher
framework and providing example code.