drop web-server/doc

svn: r8284
This commit is contained in:
Matthew Flatt 2008-01-10 20:43:28 +00:00
parent 3b394bda4e
commit a934de478f
17 changed files with 1 additions and 2271 deletions

View File

@ -1,260 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "configuration"
#:style 'toc]{Configuration}
There are a number of libraries and utilities useful for
configuring the @web-server .
@local-table-of-contents[]
@; ------------------------------------------------------------
@section[#:tag "configuration-table-structs.ss"]{Configuration Table Structure}
@require[(for-label web-server/configuration/configuration-table-structs)]
@defmodule[web-server/configuration/configuration-table-structs]
@filepath{configuration/configuration-table-structs.ss} provides the following structures that
represent a standard configuration (see @secref["web-server-unit.ss"]) of the @web-server .
The contracts on this structure influence the valid types of values in
the configuration table S-expression file format described in
@secref["configuration-table.ss"].
@defstruct[configuration-table
([port port-number?]
[max-waiting natural-number/c]
[initial-connection-timeout natural-number/c]
[default-host host-table?]
[virtual-hosts (listof (cons/c string? host-table?))])]
@defstruct[host-table
([indices (listof string?)]
[log-format symbol?]
[messages messages?]
[timeouts timeouts?]
[paths paths?])]
@defstruct[host
([indices (listof string?)]
[log-format symbol?]
[log-path (or/c false/c path-string?)]
[passwords (or/c false/c path-string?)]
[responders responders?]
[timeouts timeouts?]
[paths paths?])]
@defstruct[responders
([servlet (url? any/c . -> . response?)]
[servlet-loading (url? any/c . -> . response?)]
[authentication (url? (cons/c symbol? string?) . -> . response?)]
[servlets-refreshed (-> response?)]
[passwords-refreshed (-> response?)]
[file-not-found (request? . -> . response?)]
[protocol (url? . -> . response?)]
[collect-garbage (-> response?)])]
@defstruct[messages
([servlet string?]
[authentication string?]
[servlets-refreshed string?]
[passwords-refreshed string?]
[file-not-found string?]
[protocol string?]
[collect-garbage string?])]
@defstruct[timeouts
([default-servlet number?]
[password number?]
[servlet-connection number?]
[file-per-byte number?]
[file-base number?])]
@defstruct[paths
([conf (or/c false/c path-string?)]
[host-base (or/c false/c path-string?)]
[log (or/c false/c path-string?)]
[htdocs (or/c false/c path-string?)]
[servlet (or/c false/c path-string?)]
[mime-types (or/c false/c path-string?)]
[passwords (or/c false/c path-string?)])]
@; ------------------------------------------------------------
@section[#:tag "configuration-table.ss"]{Configuration Table}
@require[(for-label web-server/configuration/configuration-table)]
@defmodule[web-server/configuration/configuration-table]
@filepath{configuration/configuration-table.ss} provides functions for
reading, writing, parsing, and printing @scheme[configuration-table]
structures.
@defthing[default-configuration-table-path path?]{The default configuration table S-expression file.}
@defproc[(sexpr->configuration-table (sexpr list?))
configuration-table?]{
This function converts a @scheme[configuration-table] from an S-expression.
}
@defproc[(configuration-table->sexpr (ctable configuration-table?))
list?]{
This function converts a @scheme[configuration-table] to an S-expression.
}
@schemeblock[
`((port ,integer?)
(max-waiting ,integer?)
(initial-connection-timeout ,integer?)
(default-host-table
,host-table-sexpr?)
(virtual-host-table
(list ,symbol? ,host-table-sexpr?)
...))]
where a @scheme[host-table-sexpr] is:
@; XXX Allowable log-formats?
@; XXX Where the paths are resolved relative to
@schemeblock[
`(host-table
(default-indices ,string? ...)
(log-format ,symbol?)
(messages
(servlet-message ,path-string?)
(authentication-message ,path-string?)
(servlets-refreshed ,path-string?)
(passwords-refreshed ,path-string?)
(file-not-found-message ,path-string?)
(protocol-message ,path-string?)
(collect-garbage ,path-string?))
(timeouts
(default-servlet-timeout ,integer?)
(password-connection-timeout ,integer?)
(servlet-connection-timeout ,integer?)
(file-per-byte-connection-timeout ,integer?)
(file-base-connection-timeout ,integer))
(paths
(configuration-root ,path-string?)
(host-root ,path-string?)
(log-file-path ,path-string?)
(file-root ,path-string?)
(servlet-root ,path-string?)
(mime-types ,path-string?)
(password-authentication ,path-string?)))]
@defproc[(read-configuration-table (path path-string?))
configuration-table?]{
This function reads a @scheme[configuration-table] from @scheme[path].
}
@defproc[(write-configuration-table (ctable configuration-table?) (path path-string?))
void]{
This function writes a @scheme[configuration-table] to @scheme[path].
}
@; ------------------------------------------------------------
@section[#:tag "namespace.ss"]{Servlet Namespaces}
@require[(for-label web-server/configuration/namespace)]
@defmodule[web-server/configuration/namespace]
@filepath{configuration/namespace.ss} provides a function to help create the
@scheme[make-servlet-namespace] procedure needed by the @scheme[make] functions
of @filepath{dispatchers/dispatch-servlets.ss} and @filepath{dispatchers/dispatch-lang.ss}.
@; XXX Define make-servlet-namespace?
@; XXX Use actual keyword argument syntax
@defproc[(make-make-servlet-namespace (#:to-be-copied-module-specs to-be-copied-module-specs (listof module-spec?)))
(key-> ([additional-specs (listof module-spec?)])
namespace?)]{
This function creates a function that when called will construct a new @scheme[namespace] that
has all the modules from @scheme[to-be-copied-module-specs] and @scheme[additional-specs], as well
as @scheme[mzscheme] and @scheme[(lib "mred.ss" "mred")], provided they are already attached
to the @scheme[(current-namespace)] of the call-site.
Example:
@schemeblock[
(make-make-servlet-namespace
#:to-be-copied-module-specs `((lib "database.ss" "my-module")))
]
}
@subsection{Why this is useful}
A different namespace is needed for each servlet, so that if servlet A and servlet B both use
a stateful module C, they will be isolated from one another. We see the @web-server as
an operating system for servlets, so we inherit the isolation requirement on operating systems.
However, there are some modules which must be shared. If they were not, then structures cannot
be passed from the @web-server to the servlets, due to a subtlety in the way MzScheme
implements structures.
Since, on occasion, a user will actually wanted servlets A and B to interact through module C.
A custom @scheme[make-servlet-namespace] can be created, through this procedure, that attaches
module C to all servlet namespaces. Through other means (see @secref["dispatchers"]) different sets
of servlets can share different sets of modules.
@; ------------------------------------------------------------
@section[#:tag "responders.ss"]{Standard Responders}
@require[(for-label web-server/configuration/responders)]
@defmodule[web-server/configuration/responders]
@filepath{configuration/responders.ss} provides some functions that help constructing HTTP responders.
These functions are used by the default dispatcher constructor (see @secref["web-server-unit.ss"]) to
turn the paths given in the @scheme[configuration-table] into responders for the associated circumstance.
@defproc[(file-response (http-code natural-number/c) (short-version string?) (text-file string?) (header header?) ...)
response?]{
Generates a @scheme[response/full] with the given @scheme[http-code] and @scheme[short-version]
as the corresponding fields; with the content of the @scheme[text-file] as the body; and, with
the @scheme[header]s as, you guessed it, headers.
}
@defproc[(servlet-loading-responder (url url?) (exn any/c))
response?]{
Prints the @scheme[exn] to standard output and responds with a "Servlet didn't load."
message.
}
@defproc[(gen-servlet-not-found (file path-string?))
((url url?) . -> . response?)]{
Returns a function that generates a standard "Servlet not found." error with content from @scheme[file].
}
@defproc[(gen-servlet-responder (file path-string?))
((url url?) (exn any/c) . -> . response?)]{
Prints the @scheme[exn] to standard output and responds with a "Servlet error." message with content from @scheme[file].
}
@defproc[(gen-servlets-refreshed (file path-string?))
(-> response?)]{
Returns a function that generates a standard "Servlet cache refreshed." message with content from @scheme[file].
}
@defproc[(gen-passwords-refreshed (file path-string?))
(-> response?)]{
Returns a function that generates a standard "Passwords refreshed." message with content from @scheme[file].
}
@defproc[(gen-authentication-responder (file path-string?))
((url url?) (header header?) . -> . response?)]{
Returns a function that generates an authentication failure error with content from @scheme[file] and
@scheme[header] as the HTTP header.
}
@defproc[(gen-protocol-responder (file path-string?))
((url url?) . -> . response?)]{
Returns a function that generates a "Malformed request" error with content from @scheme[file].
}
@defproc[(gen-file-not-found-responder (file path-string?))
((req request?) . -> . response?)]{
Returns a function that generates a standard "File not found" error with content from @scheme[file].
}
@defproc[(gen-collect-garbage-responder (file path-string?))
(-> response?)]{
Returns a function that generates a standard "Garbage collection run" message with content from @scheme[file].
}

View File

@ -1,376 +0,0 @@
#lang scribble/doc
@(require "web-server.ss"
(for-syntax scheme/base))
@(define-syntax (a-dispatcher stx)
(syntax-case stx ()
[(_ lib-name lib-desc . rest)
;; This macro plays a standard trick for limiting the scope of
;; `require'd bindings: it puts the require and the scope of the
;; require into a macro, which introduces both together
#'(begin
(define-syntax-rule (intro)
((... ...)
(begin
(require (for-label lib-name))
(defmodule lib-name
"The " (schememodname lib-name) " module " lib-desc)
. rest)))
(intro))]))
@title[#:tag "dispatchers"
#:style 'toc]{Dispatchers}
The @web-server is really just a particular configuration of a
dispatching server. There are a number of dispatchers that are defined
to support the @web-server . Other dispatching servers, or variants
of the @web-server , may find these useful. In particular, if you want
a peculiar processing pipeline for your @web-server installation, this
documentation will be useful.
@local-table-of-contents[]
@; ------------------------------------------------------------
@section[#:tag "dispatch.ss"]{General}
@require[(for-label web-server/dispatchers/dispatch)]
@defmodule[web-server/dispatchers/dispatch]
@filepath{dispatchers/dispatch.ss} provides a few functions for dispatchers in general.
@defthing[dispatcher? contract?]{
Equivalent to @scheme[(connection? request? . -> . void)].
}
@defproc[(dispatcher-interface-version? (any any/c)) boolean?]{
Returns @scheme[#t] if @scheme[any] is @scheme['v1]. Returns @scheme[#f] otherwise.
}
@defstruct[exn:dispatcher ()]{
An exception thrown to indicate that a dispatcher does not apply to a particular
request.
}
@defproc[(next-dispatcher) void]{
Raises a @scheme[exn:dispatcher]
}
As the @scheme[dispatcher?] contract suggests, a dispatcher is a function that takes a connection
and request object and does something to them. Mostly likely it will generate
some response and output it on the connection, but it may do something
different. For example, it may apply some test to the request object, perhaps
checking for a valid source IP address, and error if the test is not passed, and call @scheme[next-dispatcher]
otherwise.
Consider the following example dispatcher, that captures the essence of URL rewriting:
@schemeblock[
(code:comment "(url? -> url?) dispatcher? -> dispatcher?")
(lambda (rule inner)
(lambda (conn req)
(code:comment "Call the inner dispatcher...")
(inner conn
(code:comment "with a new request object...")
(copy-struct request req
(code:comment "with a new URL!")
[request-uri (rule (request-uri req))]))))
]
@; ------------------------------------------------------------
@section[#:tag "filesystem-map.ss"]{Mapping URLs to Paths}
@require[(for-label web-server/dispatchers/filesystem-map)]
@defmodule[web-server/dispatchers/filesystem-map]
@filepath{dispatchers/filesystem-map.ss} provides a means of mapping
URLs to paths on the filesystem.
@defthing[url-path? contract?]{
This contract is equivalent to @scheme[((url?) . ->* . (path? (listof path-element?)))].
The returned @scheme[path?] is the path on disk. The list is the list of
path elements that correspond to the path of the URL.}
@defproc[(make-url->path (base path?))
url-path?]{
The @scheme[url-path?] returned by this procedure considers the root
URL to be @scheme[base]. It ensures that @scheme[".."]s in the URL
do not escape the @scheme[base] and removes them silently otherwise.}
@defproc[(make-url->valid-path (url->path url->path?))
url->path?]{
Runs the underlying @scheme[url->path], but only returns if the path
refers to a file that actually exists. If it is does not, then the suffix
elements of the URL are removed until a file is found. If this never occurs,
then an error is thrown.
This is primarily useful for dispatchers that allow path information after
the name of a service to be used for data, but where the service is represented
by a file. The most prominent example is obviously servlets.}
@; ------------------------------------------------------------
@section[#:tag "dispatch-sequencer.ss"]{Sequencing}
@a-dispatcher[web-server/dispatchers/dispatch-sequencer
@elem{defines a dispatcher constructor
that invokes a sequence of dispatchers until one applies.}]{
@defproc[(make (dispatcher dispatcher?) ...)
dispatcher?]{
Invokes each @scheme[dispatcher], invoking the next if the first
calls @scheme[next-dispatcher]. If no @scheme[dispatcher] applies,
then it calls @scheme[next-dispatcher] itself.
}}
@; XXX Kind of timeout that is proportional to bindings
@; ------------------------------------------------------------
@section[#:tag "dispatch-timeout.ss"]{Timeouts}
@a-dispatcher[web-server/dispatchers/dispatch-timeout
@elem{defines a dispatcher constructor
that changes the timeout on the connection and calls the next
dispatcher.}]{
@defproc[(make [new-timeout integer?])
dispatcher?]{
Changes the timeout on the connection with @scheme[adjust-connection-timeout!]
called with @scheme[new-timeout].
}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-lift.ss"]{Lifting Procedures}
@a-dispatcher[web-server/dispatchers/dispatch-lift
@elem{defines a dispatcher constructor.}]{
@defproc[(make (proc (request? . -> . response?)))
dispatcher?]{
Constructs a dispatcher that calls @scheme[proc] on the request
object, and outputs the response to the connection.
}}
@; XXX Change filtering to take predicate, rather than regexp
@; ------------------------------------------------------------
@section[#:tag "dispatch-filter.ss"]{Filtering Requests}
@a-dispatcher[web-server/dispatchers/dispatch-filter
@elem{defines a dispatcher constructor
that calls an underlying dispatcher
with all requests that pass a predicate.}]{
@defproc[(make (regex regexp?) (inner dispatcher?))
dispatcher?]{
Calls @scheme[inner] if the URL path of the request, converted to
a string, matches @scheme[regex]. Otherwise, calls @scheme[next-dispatcher].
}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-pathprocedure.ss"]{Procedure Invocation upon Request}
@a-dispatcher[web-server/dispatchers/dispatch-pathprocedure
@elem{defines a dispatcher constructor
for invoking a particular procedure when a request is given to a particular
URL path.}]{
@defproc[(make (path string?) (proc (request? . -> . response?)))
dispatcher?]{
Checks if the request URL path as a string is equal to @scheme[path]
and if so, calls @scheme[proc] for a response.
}
This is used in the standard @web-server pipeline to provide
a URL that refreshes the password file, servlet cache, etc.}
@; ------------------------------------------------------------
@section[#:tag "dispatch-log.ss"]{Logging}
@a-dispatcher[web-server/dispatchers/dispatch-log
@elem{defines a dispatcher constructor
for transparent logging of requests.}]{
@defthing[format-req/c contract?]{
Equivalent to @scheme[(request? . -> . string?)].
}
@defthing[paren-format format-req/c]{
Formats a request by:
@schemeblock[
(format "~s~n"
(list 'from (request-client-ip req)
'to (request-host-ip req)
'for (url->string (request-uri req)) 'at
(date->string (seconds->date (current-seconds)) #t)))
]}
@defthing[extended-format format-req/c]{
Formats a request by:
@schemeblock[
(format "~s~n"
`((client-ip ,(request-client-ip req))
(host-ip ,(request-host-ip req))
(referer ,(let ([R (headers-assq* #"Referer" (request-headers/raw req))])
(if R
(header-value R)
#f)))
(uri ,(url->string (request-uri req)))
(time ,(current-seconds))))
]}
@defthing[apache-default-format format-req/c]{
Formats a request like Apache's default.
}
@defproc[(log-format->format [id symbol?])
format-req/c]{
Maps @scheme['parenthesized-default] to @scheme[paren-format],
@scheme['extended] to @scheme[extended-format], and
@scheme['apache-default] to @scheme[apache-default-format].
}
@defproc[(make [#:format format format-req/c paren-format]
[#:log-path log-path path-string? "log"])
dispatcher?]{
Logs requests to @scheme[log-path] by using @scheme[format] to format the requests.
Then invokes @scheme[next-dispatcher].
}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-passwords.ss"]{Password Protection}
@a-dispatcher[web-server/dispatchers/dispatch-passwords
@elem{defines a dispatcher constructor
that performs HTTP Basic authentication filtering.}]{
@defproc[(make [#:password-file password-file path-string? "passwords"]
[#:authentication-responder
authentication-responder
((url url?) (header (cons/c symbol? string?)) . -> . response?)
(gen-authentication-responder "forbidden.html")])
(values (-> void)
dispatcher?)]{
The first returned value is a procedure that refreshes the password
file used by the dispatcher.
The dispatcher that is returned does the following:
Checks if the request contains Basic authentication credentials, and that
they are included in @scheme[password-file]. If they are not,
@scheme[authentication-responder] is called with a @scheme[header] that
requests credentials. If they are, then @scheme[next-dispatcher] is
invoked.
@; XXX Separate out password-file work
@scheme[password-file] is parsed as:
@schemeblock[(list ([domain : string?]
[path : string-regexp?]
(list [user : symbol?]
[pass : string?])
...)
...)]
For example:
@schemeblock['(("secret stuff" "/secret(/.*)?" (bubba "bbq") (|Billy| "BoB")))]
}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-host.ss"]{Virtual Hosts}
@a-dispatcher[web-server/dispatchers/dispatch-host
@elem{defines a dispatcher constructor
that calls a different dispatcher based upon the host requested.}]{
@defproc[(make (lookup-dispatcher (symbol? . -> . dispatcher?)))
dispatcher?]{
Extracts a host from the URL requested, or the Host HTTP header,
calls @scheme[lookup-dispatcher] with the host, and invokes the
returned dispatcher. If no host can be extracted, then @scheme['none]
is used.
}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-files.ss"]{Serving Files}
@a-dispatcher[web-server/dispatchers/dispatch-files
@elem{allows files to be served.
It defines a dispatcher construction procedure.}]{
@defproc[(make [#:url->path url->path url->path?]
[#:path->mime-type path->mime-type (path? . -> . bytes?) (lambda (path) TEXT/HTML-MIME-TYPE)]
[#:indices indices (listof string?) (list "index.html" "index.htm")])
dispatcher?]{
Uses @scheme[url->path] to extract a path from the URL in the request
object. If this path does not exist, then the dispatcher does not apply.
If the path is a directory, then the @scheme[indices] are checked in order
for an index file to serve. In that case, or in the case of a path that is
a file already, @scheme[path->mime-type] is consulted for the MIME
Type of the path. The file is then
streamed out the connection object.
This dispatcher supports HTTP Range GET requests and HEAD requests.}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-servlets.ss"]{Serving Scheme Servlets}
@a-dispatcher[web-server/dispatchers/dispatch-servlets
@elem{defines a dispatcher constructor
that runs servlets written in Scheme.}]{
@; XXX Remove config:scripts
@defproc[(make [config:scripts (box/c cache-table?)]
[#:url->path url->path url->path?]
[#:make-servlet-namespace
make-servlet-namespace
make-servlet-namespace?
(make-make-servlet-namespace)]
[#:responders-servlet-loading
responders-servlet-loading
((url url?) (exn any/c) . -> . response?)
servlet-loading-responder]
[#:responders-servlet
responders-servlet
((url url?) (exn any/c) . -> . response?)
(gen-servlet-responder "servlet-error.html")]
[#:timeouts-default-servlet
timeouts-default-servlet
integer?
30])
(values (-> void)
dispatcher?)]{
The first returned value is a procedure that refreshes the servlet
code cache.
The dispatcher does the following:
If the request URL contains a continuation reference, then it is invoked with the
request. Otherwise, @scheme[url->path] is used to resolve the URL to a path.
The path is evaluated as a module, in a namespace constructed by @scheme[make-servlet-namespace].
If this fails then @scheme[responders-servlet-loading] is used to format a response
with the exception. If it succeeds, then @scheme[start] export of the module is invoked.
If there is an error when a servlet is invoked, then @scheme[responders-servlet] is
used to format a response with the exception.
Servlets that do not specify timeouts are given timeouts according to @scheme[timeouts-default-servlet].
}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-lang.ss"]{Serving Web Language Servlets}
@a-dispatcher[web-server/dispatchers/dispatch-lang
@elem{defines a dispatcher constructor
that runs servlets written in the Web Language.}]{
@defproc[(make [#:url->path url->path url->path?]
[#:make-servlet-namespace make-servlet-namespace
make-servlet-namespace?
(make-make-servlet-namespace)]
[#:responders-servlet-loading responders-servlet-loading servlet-loading-responder]
[#:responders-servlet responders-servlet (gen-servlet-responder "servlet-error.html")])
dispatcher?]{
If the request URL contains a serialized continuation, then it is invoked with the
request. Otherwise, @scheme[url->path] is used to resolve the URL to a path.
The path is evaluated as a module, in a namespace constructed by @scheme[make-servlet-namespace].
If this fails then @scheme[responders-servlet-loading] is used to format a response
with the exception. If it succeeds, then @scheme[start] export of the module is invoked.
If there is an error when a servlet is invoked, then @scheme[responders-servlet] is
used to format a response with the exception.
}}
@; ------------------------------------------------------------
@section[#:tag "dispatch-stat.ss"]{Statistics}
@a-dispatcher[web-server/dispatchers/dispatch-stat
@elem{provides services related to performance
statistics.}]{
@defproc[(make-gc-thread [time integer?])
thread?]{
Starts a thread that calls @scheme[(collect-garbage)] every @scheme[time] seconds.
}
@defproc[(make)
dispatcher?]{
Returns a dispatcher that prints memory usage on every request.
}}

View File

@ -1,6 +0,0 @@
#lang scheme/base
(define start #f)
(provide (all-defined-out))

View File

@ -1,9 +0,0 @@
#lang scheme/base
(define interface-version #f)
(define timeout #f)
(define start #f)
(define manager #f)
(provide (all-defined-out))

View File

@ -1,13 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title{Troubleshooting}
@section{General}
@subsection{IE ignores my CSS or behaves strange in other ways}
In quirks mode, IE does not parse your page as XML, in particular it will not recognize many instances of
"empty tag shorthand", e.g. "<img src='...' />", whereas the @web-server uses @scheme[(lib "xml.ss" "xml")]
to format XML, which uses empty tag shorthand by default. You can change the default with the @scheme[empty-tag-shorthand]
parameter: @scheme[(empty-tag-shorthand 'never)].

View File

@ -1,3 +0,0 @@
(module info setup/infotab
(define name "Web Server documentation"))

View File

@ -1,292 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "lang"
#:style 'toc]{Web Language Servlets}
The @web-server allows servlets to be written in a special Web
language that is nearly identical to Scheme. Herein we discuss how it
is different and what API is provided.
@local-table-of-contents[]
@; ------------------------------------------------------------
@section[#:tag "lang-servlets"]{Definition}
@require[(for-label "dummy-language-servlet.ss")] ; to give a binding context
@declare-exporting[web-server/doc/dummy-language-servlet]
A @defterm{Web language servlet} is a module written in the
@scheme[(lib "lang.ss" "web-server")] module language. It should provide
the following identifier:
@defproc[(start [initial-request request?])
response?]{
This function is called when this servlet is invoked.
The argument is the HTTP request that initiated the servlet.
}
@; ------------------------------------------------------------
@section[#:tag "considerations"]{Usage Considerations}
A servlet has the following process performed on it automatically:
@itemize[
@item{All uses of @scheme[letrec] are removed and replaced with equivalent uses of
@scheme[let] and imperative features. (@filepath{lang/elim-letrec.ss})}
@item{The program is converted into ANF (Administrative Normal Form),
making all continuations explicit. (@filepath{lang/anormal.ss})}
@item{All continuations (and other continuations marks) are recorded in the
continuation marks of the expression
they are the continuation of. (@filepath{lang/elim-callcc.ss})}
@item{All calls to external modules are identified and marked.
(@filepath{lang/elim-callcc.ss})}
@item{All uses of @scheme[call/cc] are removed and replaced with
equivalent gathering of the continuations through the continuation-marks.
(@filepath{lang/elim-callcc.ss})}
@item{The program is defunctionalized with a serializable data-structure for each
anonymous lambda. (@filepath{lang/defun.ss})}
]
This process allows the continuations captured by your servlet to be serialized.
This means they may be stored on the client's browser or the server's disk.
Thus, your servlet has no cost to the server other than execution. This is
very attractive if you've used Scheme servlets and had memory problems.
This process IS defined on all of PLT Scheme and occurs AFTER macro-expansion,
so you are free to use all interesting features of PLT Scheme. However, there
are some considerations you must make.
First, this process drastically changes the structure of your program. It
will create an immense number of lambdas and structures your program
did not normally contain. The performance implication of this has not been
studied with PLT Scheme. However, it is theoretically a benefit. The main
implications would be due to optimizations MzScheme attempts to perform
that will no longer apply. Ideally, your program should be optimized first.
Second, the defunctionalization process is sensitive to the syntactic structure
of your program. Therefore, if you change your program in a trivial way, for example,
changing a constant, then all serialized continuations will be obsolete and will
error when deserialization is attempted. This is a feature, not a bug!
Third, the values in the lexical scope of your continuations must be serializable
for the continuations itself to be serializable. This means that you must use
@scheme[define-serializable-struct] rather than @scheme[define-struct], and take
care to use modules that do the same. Similarly, you may not use @scheme[parameterize],
because parameterizations are not serializable.
Fourth, and related, this process only runs on your code, not on the code you
@scheme[require]. Thus, your continuations---to be capturable---must not
be in the context of another module. For example, the following will not work:
@schemeblock[
(define requests
(map (lambda (rg) (send/suspend/url rg))
response-generators))
]
because @scheme[map] is not transformed by the process. However, if you defined
your own @scheme[map] function, there would be no problem.
Fifth, the store is NOT serialized. If you rely on the store you will
be taking huge risks. You will be assuming that the serialized continuation
is invoked before the server is restarted or the memory is garbage collected.
This process is derived from the paper
@href-link["http://www.cs.brown.edu/~sk/Publications/Papers/Published/pcmkf-cont-from-gen-stack-insp/" "\"Continuations from Generalized Stack Inspection\""].
We thank Greg Pettyjohn for his initial implementation of this algorithm.
@; ------------------------------------------------------------
@section[#:tag "reprovided"]{Reprovided API}
The APIs from @scheme[(lib "url.ss" "net")], @secref["request-structs.ss"],
@secref["response-structs.ss"], and @secref["helpers.ss"] are reprovided
by the Web language API.
@; ------------------------------------------------------------
@section[#:tag "lang/web.ss"]{Web}
@require[(for-label web-server/lang/web)]
@defmodule[web-server/lang/web]
@filepath{lang/web.ss} provides the most basic Web functionality.
@defproc[(send/suspend/url [response-generator (url? . -> . response?)])
request?]{
Captures the current continuation. Serializes it and stuffs it into
a URL. Calls @scheme[response-generator] with this URL and delivers
the response to the client. If the URL is invoked
the request is returned to this continuation.
}
@defproc[(send/suspend/hidden [response-generator (url? xexpr? . -> . response?)])
request?]{
Captures the current continuation. Serializes it and generates an INPUT
form that includes the serialization as a hidden form.
Calls @scheme[response-generator] with this URL and form field and delivers
the response to the client. If the URL is invoked with form data containing
the hidden form,
the request is returned to this continuation.
Note: The continuation is NOT stuffed.
}
@defproc[(embed-proc/url [k-url url?]
[proc (request? . -> . any/c)])
url?]{
Serializes and stuffs @scheme[proc] into @scheme[k-url]. For use with
@scheme[extract-proc/url].
}
@defproc[(extract-proc/url [req request?])
any/c]{
Inspects the URL of @scheme[req] and attempts to extract the procedure
embedded with @scheme[embed-proc/url]. If successful, it is invoked with
@scheme[req] as an argument.
}
@; ------------------------------------------------------------
@section[#:tag "lang/stuff-url.ss"]{Stuff URL}
@require[(for-label web-server/lang/stuff-url)]
@defmodule[web-server/lang/stuff-url]
@filepath{lang/stuff-url.ss} provides an interface for "stuffing"
serializable values into URLs. Currently there is a particular
hard-coded behavior, but we hope to make it more flexible in
the future.
@defproc[(stuff-url [v serializable?]
[u url?])
url?]{
Serializes @scheme[v] and computes the MD5 of the serialized
representation. The serialization of @scheme[v] is written to
@filepath{$HOME/.urls/M} where `M' is the MD5. `M' is then
placed in @scheme[u] as a URL param.
}
@defproc[(stuffed-url? [u url?])
boolean?]{
Checks if @scheme[u] appears to be produced by @scheme[stuff-url].
}
@defproc[(unstuff-url [u url?])
serializable?]{
Extracts the value previously serialized into @scheme[u] by @scheme[stuff-url].
}
In the future, we will offer the facilities to:
@itemize[
@item{Optionally use the content-addressed storage.}
@item{Use different hashing algorithms for the CAS.}
@item{Encrypt the serialized value.}
@item{Only use the CAS if the URL would be too long. (URLs may only be 1024 characters.)}
]
@; ------------------------------------------------------------
@section[#:tag "lang/web-extras.ss"]{Web Extras}
@require[(for-label web-server/lang/web-extras)]
@defmodule[web-server/lang/web-extras]{The
@schememodname[web-server/lang/web-extras] library provides
@scheme[send/suspend/dispatch] and @scheme[redirect/get] as
@schememodname[web-server/servlet/web], except they use
@scheme[embed-proc/url] plus @scheme[extract-proc/url] and
@scheme[send/suspend/url], respectively.}
@deftogether[(
@defform[(send/suspend/dispatch response-proc-expr)]
@defproc[(redirect/get) request?]
)]{
See @schememodname[web-server/servlet/web].}
@; ------------------------------------------------------------
@section[#:tag "lang/file-box.ss"]{File Boxes}
@require[(for-label web-server/lang/file-box)]
@defmodule[web-server/lang/file-box]
As mentioned earlier, it is dangerous to rely on the store in
Web Language servlets, due to the deployment scenarios available
to them. @filepath{lang/file-box.ss} provides a simple API to replace
boxes in a safe way.
@defproc[(file-box? [v any/c])
boolean?]{Checks if @scheme[v] is a file-box.}
@defproc[(file-box [p path?]
[v serializable?])
file-box?]{
Creates a file-box that is stored at @scheme[p], with the default
contents of @scheme[v].
}
@defproc[(file-unbox [fb file-box?])
serializable?]{
Returns the value inside @scheme[fb]
}
@defproc[(file-box-set? [fb file-box?])
boolean?]{
Returns @scheme[#t] if @scheme[fb] contains a value.
}
@defproc[(file-box-set! [fb file-box?]
[v serializable?])
void]{
Saves @scheme[v] in the file represented by @scheme[fb].
}
@warning{If you plan on using a load-balancer, make sure your file-boxes
are on a shared medium.}
@; ------------------------------------------------------------
@section[#:tag "lang/web-param.ss"]{Web Parameters}
@require[(for-label web-server/lang/web-param)]
@defmodule[web-server/lang/web-param]
As mentioned earlier, it is not easy to use @scheme[parameterize] in the
Web Language. @filepath{lang/web-param.ss} provides (roughly) the same
functionality in a way that is serializable. Like other serializable
things in the Web Language, they are sensitive to source code modification.
@defform[(make-web-parameter default)]{
Expands to the definition of a web-parameter with
@scheme[default] as the default value. A web-parameter is
a procedure that, when called with zero arguments, returns @scheme[default]
or the last value @scheme[web-parameterize]d in the dynamic context
of the call.
}
@defproc[(web-parameter? [v any/c])
boolean?]{
Checks if @scheme[v] appears to be a web-parameter.
}
@defform[(web-parameterize ([web-parameter-expr value-expr] ...) expr ...)]{
Runs @scheme[(begin expr ...)] such that the web-parameters that
the @scheme[web-parameter-expr]s evaluate to are bound to the @scheme[value-expr]s.
From the perspective of the @scheme[value-expr]s, this is like @scheme[let].
}
@; ------------------------------------------------------------
@section[#:tag "lang/web-cells.ss"]{Web Cells}
@require[(for-label web-server/lang/web-cells)]
@defmodule[web-server/lang/web-cells]{The
@schememodname[web-server/lang/web-cells] library provides the same
API as @schememodname[web-server/servlet/web-cells], but in a way
compatible with the Web Language. The one difference is that
@scheme[make-web-cell] is syntax, rather than a function.}
@deftogether[(
@defproc[(web-cell? [v any/c])
boolean?]
@defform[(make-web-cell default-expr)]
@defproc[(web-cell-ref [wc web-cell?])
any/c]
@defproc[(web-cell-shadow [wc web-cell?]
[v any/c])
void]
)]{
See @schememodname[web-server/servlet/web-cells].}

View File

@ -1,160 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "managers"
#:style 'toc]{Continuation Managers}
Since Scheme servlets store their continuations on the server, they take
up memory on the server. Furthermore, garbage collection can not be used
to free this memory, because there are roots outside the system: users'
browsers, bookmarks, brains, and notebooks. Therefore, some other strategy
must be used if memory usage is to be controlled. This functionality is
pluggable through the manager interface.
@local-table-of-contents[]
@; ------------------------------------------------------------
@section[#:tag "manager.ss"]{General}
@require[(for-label web-server/managers/manager)]
@defmodule[web-server/managers/manager]
@filepath{managers/manager.ss} defines the manager interface. It is required by
the users and implementers of managers.
@defstruct[manager ([create-instance ((-> void) . -> . number?)]
[adjust-timeout! (number? number? . -> . void)]
[clear-continuations! (number? . -> . void)]
[continuation-store! (number? any/c expiration-handler? . -> . (list/c number? number?))]
[continuation-lookup (number? number? number? . -> . any/c)])]{
@scheme[create-instance] is called to initialize a instance, to hold the
continuations of one servlet session. It is passed
a function to call when the instance is expired. It runs the id of the
instance.
@scheme[adjust-timeout!] is a to-be-deprecated function that takes an
instance-id and a number. It is specific to the timeout-based manager
and will be removed.
@scheme[clear-continuations!] expires all the continuations of an instance.
@scheme[continuation-store!] is given an instance-id, a continuation value,
and a function to include in the exception thrown if the continuation is
looked up and has been expired. The two numbers returned are a
continuation-id and a nonce.
@scheme[continuation-lookup] finds the continuation value associated with
the instance-id, continuation-id, and nonce triple it is given.
}
@defstruct[(exn:fail:servlet-manager:no-instance exn:fail)
([expiration-handler expiration-handler?])]{
This exception should be thrown by a manager when an instance is looked
up that does not exist.
}
@defstruct[(exn:fail:servlet-manager:no-continuation exn:fail)
([expiration-handler expiration-handler?])]{
This exception should be thrown by a manager when a continuation is
looked up that does not exist.
}
@; ------------------------------------------------------------
@section[#:tag "none.ss"]{No Continuations}
@require[(for-label web-server/managers/none)]
@defmodule[web-server/managers/none]
@filepath{managers/none.ss} defines a manager constructor:
@defproc[(create-none-manager (instance-expiration-handler expiration-handler?))
manager?]{
This manager does not actually store any continuation or instance data.
You could use it if you know your servlet does not use the continuation
capturing functions and want the server to not allocate meta-data
structures for each instance.
}
If you are considering using this manager, also consider using the
Web Language. (See @secref["lang"].)
@; ------------------------------------------------------------
@section[#:tag "timeouts.ss"]{Timeouts}
@require[(for-label web-server/managers/timeouts)]
@defmodule[web-server/managers/timeouts]
@filepath{managers/timeouts.ss} defines a manager constructor:
@defproc[(create-timeout-manager [instance-exp-handler expiration-handler?]
[instance-timeout number?]
[continuation-timeout number?])
manager?]{
Instances managed by this manager will be expired @scheme[instance-timeout]
seconds after the last time it is accessed. If an expired instance is
looked up, the @scheme[exn:fail:servlet-manager:no-instance] exception
is thrown with @scheme[instance-exp-handler] as the expiration handler.
Continuations managed by this manager will be expired @scheme[continuation-timeout]
seconds after the last time it is accessed. If an expired continuation is looked
up, the @scheme[exn:fail:servlet-manager:no-continuation] exception
is thrown with @scheme[instance-exp-handler] as the expiration handler, if
no expiration-handler was passed to @scheme[continuation-store!].
@scheme[adjust-timeout!] corresponds to @scheme[reset-timer!] on the timer
responsible for the servlet instance.
}
This manager has been found to be... problematic... in large-scale
deployments of the @web-server .
@; ------------------------------------------------------------
@section[#:tag "lru.ss"]{LRU}
@require[(for-label web-server/managers/lru)]
@defmodule[web-server/managers/lru]
@filepath{managers/lru.ss} defines a manager constructor:
@defproc[(create-LRU-manager
[instance-expiration-handler expiration-handler?]
[check-interval integer?]
[collect-interval integer?]
[collect? (-> boolean?)]
[#:initial-count initial-count integer? 1]
[#:inform-p inform-p (integer? . -> . void) (lambda _ (void))])
manager?]{
Instances managed by this manager will be expired if there are no
continuations associated with them, after the instance is unlocked.
If an expired instance is looked up, the
@scheme[exn:fail:servlet-manager:no-instance] exception
is thrown with @scheme[instance-exp-handler] as the expiration handler.
Continuations managed by this manager are given a "Life Count" of
@scheme[initial-count] initially. If an expired continuation is looked
up, the @scheme[exn:fail:servlet-manager:no-continuation] exception
is thrown with @scheme[instance-exp-handler] as the expiration handler, if
no expiration-handler was passed to @scheme[continuation-store!].
Every @scheme[check-interval] seconds @scheme[collect?] is called to determine
if the collection routine should be run. Every @scheme[collect-interval] seconds
the collection routine is run.
Every time the collection routine runs, the "Life Count" of every
continuation is decremented by @scheme[1]. If a continuation's count
reaches @scheme[0], it is expired. The @scheme[inform-p] function
is called if any continuations are expired, with the number of
continuations expired.
}
The recommended use of this manager is to pass, as @scheme[collect?], a
function that checks the memory usage of the system, through
@scheme[current-memory-use]. Then, @scheme[collect-interval] should be sufficiently
large compared to @scheme[check-interval]. This way, if the load on the server
spikes---as indicated by memory usage---the server will quickly expire
continuations, until the memory is back under control. If the load
stays low, it will still efficiently expire old continuations.
With @href-link["http://continue.cs.brown.edu/" "Continue"], we went from needing to restart the server a few times
a week and having many complaints under load, to not having these complaints
and not needing to restart the server for performance reasons.

View File

@ -1,422 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "private"
#:style 'toc]{Internal}
The @web-server is a complicated piece of software and as a result,
defines a number of interesting and independently useful sub-components.
Some of these are documented here.
@local-table-of-contents[]
@; ------------------------------------------------------------
@section[#:tag "timer.ss"]{Timers}
@require[(for-label web-server/private/timer)]
@defmodule[web-server/private/timer]
@filepath{private/timer.ss} provides a functionality for running
procedures after a given amount of time, that may be extended.
@defstruct[timer ([evt evt?]
[expire-seconds number?]
[action (-> void)])]{
@scheme[evt] is an @scheme[alarm-evt] that is ready at @scheme[expire-seconds].
@scheme[action] should be called when this @scheme[evt] is ready.
}
@defproc[(start-timer-manager [cust custodian?])
void]{
Handles the execution and management of timers. Resources are charged to
@scheme[cust].
}
@defproc[(start-timer [s number?]
[action (-> void)])
timer?]{
Registers a timer that runs @scheme[action] after @scheme[s] seconds.
}
@defproc[(reset-timer! [t timer?]
[s number?])
void]{
Changes @scheme[t] so that it will fire after @scheme[s] seconds.
}
@defproc[(increment-timer! [t timer?]
[s number?])
void]{
Changes @scheme[t] so that it will fire after @scheme[s] seconds from when
it does now.
}
@defproc[(cancel-timer! [t timer?])
void]{
Cancels the firing of @scheme[t] ever and frees resources used by @scheme[t].
}
@; XXX Generalize
@; ------------------------------------------------------------
@section[#:tag "connection-manager.ss"]{Connection Manager}
@require[(for-label web-server/private/connection-manager)]
@defmodule[web-server/private/connection-manager]
@filepath{private/connection-manager.ss} provides functionality for managing pairs of
input and output ports. We have plans to allow a number of different strategies
for doing this.
@defstruct[connection
([timer timer?]
[i-port input-port?] [o-port output-port?] [custodian custodian?]
[close? boolean?])]{
A connection is a pair of ports (@scheme[i-port] and @scheme[o-port]) that is
ready to close after the current job if @scheme[close?] is @scheme[#t]. Resources
associated with the connection should be allocated under @scheme[custodian].
The connection will last until @scheme[timer] triggers.
}
@; XXX Don't pass in parent-cust
@defproc[(start-connection-manager [parent-cust custodian?])
void]{
Runs the connection manager (now just the timer manager) will @scheme[parent-cust]
as the custodian.
}
@defproc[(new-connection [timeout number?]
[i-port input-port?]
[o-port output-port?]
[cust custodian?]
[close? boolean?])
connection?]{
Constructs a connection with a timer with a trigger of @scheme[timeout] that calls
@scheme[kill-connection!].
}
@defproc[(kill-connection! [c connection?])
void]{
Closes the ports associated with @scheme[c], kills the timer, and shuts down
the custodian.
}
@defproc[(adjust-connection-timeout! [c connection?]
[t number?])
void]{
Calls @scheme[reset-timer!] with the timer behind @scheme[c] with @scheme[t].
}
@; ------------------------------------------------------------
@section[#:tag "dispatch-server-unit.ss"]{Dispatching Server}
@require[(for-label web-server/private/dispatch-server-unit)]
@require[(for-label web-server/private/dispatch-server-sig)]
@require[(for-label web-server/web-server-sig)]
The @web-server is just a configuration of a dispatching server.
This dispatching server component is useful on its own.
@subsection{Dispatching Server Signatures}
@defmodule[web-server/private/dispatch-server-sig]
The @schememodname[web-server/private/dispatch-server-sig] library
provides two signatures.
@defsignature[dispatch-server^ ()]{
The @scheme[dispatch-server^] signature is an alias for
@scheme[web-server^].
@defproc[(serve) (-> void)]{
Runs the server and returns a procedure that shuts down the server.
}
@defproc[(serve-ports [ip input-port?]
[op output-port?])
void]{
Serves a single connection represented by the ports @scheme[ip] and
@scheme[op].
}
}
@defsignature[dispatch-server-config^ ()]{
@defthing[port port?]{Specifies the port to serve on.}
@defthing[listen-ip string?]{Passed to @scheme[tcp-accept].}
@defthing[max-waiting integer?]{Passed to @scheme[tcp-accept].}
@defthing[initial-connection-timeout integer?]{Specifies the initial timeout given to a connection.}
@defproc[(read-request [c connection?]
[p port?]
[port-addresses port-addresses?])
any/c]{
Defines the way the server reads requests off connections to be passed
to @scheme[dispatch].
}
@defthing[dispatch dispatcher?]{How to handle requests.}
}
@subsection{Dispatching Server Unit}
@defmodule[web-server/private/dispatch-server-unit]
The @schememodname[web-server/private/dispatch-server-unit] module
provides the unit that actually implements a dispatching server.
@; XXX Talk about how threads and custodians are used.
@defthing[dispatch-server\@ (unit/c (tcp^ dispatch-server-config^)
(dispatch-server^))]{
Runs the dispatching server config in a very basic way, except that it uses
@secref["connection-manager.ss"] to manage connections.
}
@; ------------------------------------------------------------
@section[#:tag "closure.ss"]{Serializable Closures}
@require[(for-label web-server/private/closure)]
@require[(for-label web-server/private/define-closure)]
@defmodule[web-server/private/closure]
The defunctionalization process of the Web Language (see @secref["lang"])
requires an explicit representation of closures that is serializable.
@filepath{private/closure.ss} is this representation. It provides:
@defproc[(make-closure-definition-syntax [tag syntax?]
[fvars (listof identifier?)]
[proc syntax?])
syntax?]{
Outputs a syntax object that defines a serializable structure,
with @scheme[tag] as the tag, that represents a closure over
@scheme[fvars], that acts a procedure and when invoked calls
@scheme[proc], which is assumed to be syntax of @scheme[lambda]
or @scheme[case-lambda].
}
@defproc[(closure->deserialize-name [c closure?])
symbol?]{
Extracts the unique tag of a closure @scheme[c]
}
These are difficult to use directly, so @filepath{private/define-closure.ss}
defines a helper form:
@subsection[#:style 'hidden]{Define Closure}
@defmodule[web-server/private/define-closure]
@defform[(define-closure tag formals (free-vars ...) body)]{
Defines a closure, constructed with @scheme[make-tag] that accepts
@scheme[freevars ...], that when invoked with @scheme[formals]
executes @scheme[body].
}
@; XXX Example
@; ------------------------------------------------------------
@section[#:tag "cache-table.ss"]{Cache Table}
@require[(for-label web-server/private/cache-table)]
@defmodule[web-server/private/cache-table]
@filepath{private/cache-table.ss} provides a set of caching hash table
functions.
@defproc[(make-cache-table)
cache-table?]{
Constructs a cache-table.
}
@defproc[(cache-table-lookup! [ct cache-table?]
[id symbol?]
[mk (-> any/c)])
any/c]{
Looks up @scheme[id] in @scheme[ct]. If it is not present, then @scheme[mk] is
called to construct the value and add it to @scheme[ct].
}
@defproc[(cache-table-clear! [ct cache-table?])
void?]{
Clears all entries in @scheme[ct].
}
@defproc[(cache-table? [v any/c])
boolean?]{
Determines if @scheme[v] is a cache table.
}
@; ------------------------------------------------------------
@section[#:tag "mime-types.ss"]{MIME Types}
@require[(for-label web-server/private/mime-types)]
@defmodule[web-server/private/mime-types]
@filepath{private/mime-types.ss} provides function for dealing with @filepath{mime.types}
files.
@defproc[(read-mime-types [p path?])
(hash-table/c symbol? bytes?)]{
Reads the @filepath{mime.types} file from @scheme[p] and constructs a
hash table mapping extensions to MIME types.
}
@defproc[(make-path->mime-type [p path?])
(path? . -> . bytes?)]{
Uses a @scheme[read-mime-types] with @scheme[p] and constructs a
function from paths to their MIME type.
}
@; XXX Rename mod-map.ss
@; ------------------------------------------------------------
@section[#:tag "mod-map.ss"]{Serialization Utilities}
@require[(for-label web-server/private/mod-map)]
@defmodule[web-server/private/mod-map]
The @schememodname[scheme/serialize] library provides the
functionality of serializing values. @filepath{private/mod-map.ss}
compresses the serialized representation.
@defproc[(compress-serial [sv serialized-value?])
compressed-serialized-value?]{
Collapses multiple occurrences of the same module in the module
map of the serialized representation, @scheme[sv].
}
@defproc[(decompress-serial [csv compressed-serialized-value?])
serialized-value?]{
Expands multiple occurrences of the same module in the module
map of the compressed serialized representation, @scheme[csv].
}
@; ------------------------------------------------------------
@section[#:tag "url-param.ss"]{URL Param}
@require[(for-label web-server/private/url-param)]
@defmodule[web-server/private/url-param]
The @web-server needs to encode information in URLs. If this data
is stored in the query string, than it will be overridden by browsers that
make GET requests to those URLs with more query data. So, it must be encoded
in URL params. @filepath{private/url-param.ss} provides functions for helping
with this process.
@defproc[(insert-param [u url?]
[k string?]
[v string?])
url?]{
Associates @scheme[k] with @scheme[v] in the final URL param of @scheme[u],
overwritting any current binding for @scheme[k].
}
@defproc[(extract-param [u url?]
[k string?])
(or/c string? false/c)]{
Extracts the string associated with @scheme[k] in the final URL param of
@scheme[u], if there is one, returning @scheme[#f] otherwise.
}
@; ------------------------------------------------------------
@section[#:tag "util.ss"]{Miscellaneous Utilities}
@require[(for-label web-server/private/util)]
@defmodule[web-server/private/util]
There are a number of other miscellaneous utilities the @web-server
needs. They are provided by @filepath{private/util.ss}.
@subsection{Contracts}
@defthing[port-number? contract?]{Equivalent to @scheme[(between/c 1 65535)].}
@defthing[path-element? contract?]{Equivalent to @scheme[(or/c string? path? (symbols 'up 'same))].}
@subsection{Lists}
@defproc[(list-prefix? [l list?]
[r list?])
boolean?]{
True if @scheme[l] is a prefix of @scheme[r].
}
@subsection{URLs}
@defproc[(url-replace-path [proc ((listof path/param?) . -> . (listof path/param?))]
[u url?])
url?]{
Replaces the URL path of @scheme[u] with @scheme[proc] of the former path.
}
@; XXX Remove use or take url?
@defproc[(url-path->string [url-path (listof path/param?)])
string?]{
Formats @scheme[url-path] as a string with @scheme["/"] as a delimiter
and no params.
}
@subsection{Paths}
@defproc[(explode-path* [p path?])
(listof path-element?)]{
Like @scheme[normalize-path], but does not resolve symlinks.
}
@defproc[(path-without-base [base path?]
[p path?])
(listof path-element?)]{
Returns, as a list, the portion of @scheme[p] after @scheme[base],
assuming @scheme[base] is a prefix of @scheme[p].
}
@defproc[(directory-part [p path?])
path?]{
Returns the directory part of @scheme[p], returning @scheme[(current-directory)]
if it is relative.
}
@defproc[(build-path-unless-absolute [base path-string?]
[p path-string?])
path?]{
Prepends @scheme[base] to @scheme[p], unless @scheme[p] is absolute.
}
@defproc[(strip-prefix-ups [p (listof path-element?)])
(listof path-element?)]{
Removes all the prefix @scheme[".."]s from @scheme[p].
}
@subsection{Exceptions}
@defproc[(pretty-print-invalid-xexpr [exn exn:invalid-xexpr?]
[v any/c])
void]{
Prints @scheme[v] as if it were almost an X-expression highlighting the error
according to @scheme[exn].
}
@; XXX Remove
@defproc[(network-error [s symbol?]
[fmt string?]
[v any/c] ...)
void]{
Like @scheme[error], but throws a @scheme[exn:fail:network].
}
@defproc[(exn->string [exn (or/c exn? any/c)])
string?]{
Formats @scheme[exn] with @scheme[(error-display-handler)] as a string.
}
@subsection{Strings}
@defproc[(lowercase-symbol! [sb (or/c string? bytes?)])
symbol?]{
Returns @scheme[sb] as a lowercase symbol.
}
@defproc[(read/string [s string?])
serializable?]{
@scheme[read]s a value from @scheme[s] and returns it.
}
@defproc[(write/string [v serializable?])
string?]{
@scheme[write]s @scheme[v] to a string and returns it.
}

View File

@ -1,80 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "run.ss"
#:style 'toc]{Running the Web Server}
There are a number of ways to run the Web Server. The two primary ways
are through a command-line tool or through a function call.
@local-table-of-contents[]
@; ------------------------------------------------------------
@section[#:tag "command-line-tools"]{Command-line Tools}
One command-line utility is provided with the @|web-server|:
@commandline{plt-web-server [-f <file-name> -p <port> -a <ip-address>]}
The optional file-name argument specifies the path to a
@scheme[configuration-table] S-expression (see
@secref["configuration-table.ss"].) If this is not provided, the
default configuration shipped with the server is used. The optional
port and ip-address arguments override the corresponding portions of
the @scheme[configuration-table].
The @scheme[configuration-table] is given to @scheme[configuration-table->web-config\@]
and used to construct a @scheme[web-config^] unit,
and is linked with the @scheme[web-server\@] unit. The resulting unit is invoked, and
the server runs until the process is killed.
To run the web server with MrEd, use
@commandline{mred -l- web-server/gui [-f <file-name> -p <port> -a <ip-address>]}
@; ------------------------------------------------------------
@section[#:tag "web-server.ss"]{Functional}
@require[(for-label web-server/web-server)]
@defmodule[web-server/web-server]
@filepath{web-server.ss} provides a number of functions for easing embedding
of the @web-server in other applications, or loading a custom
dispatcher. See @filepath{run.ss} for an example of such a script.
@defproc[(serve [#:dispatch dispatch dispatcher?]
[#:tcp\@ tcp\@ tcp-unit^ raw:tcp\@]
[#:port port integer? 80]
[#:listen-ip listen-ip (or/c string? false/c) #f]
[#:max-waiting max-waiting integer? 40]
[#:initial-connection-timeout initial-connection-timeout integer? 60])
(-> void)]{
Constructs an appropriate @scheme[dispatch-config^], invokes the @scheme[dispatch-server\@],
and calls its @scheme[serve] function.
}
@defproc[(serve/ports [#:dispatch dispatch dispatcher?]
[#:tcp\@ tcp\@ tcp-unit^ raw:tcp\@]
[#:ports ports (listof integer?) (list 80)]
[#:listen-ip listen-ip (or/c string? false/c) #f]
[#:max-waiting max-waiting integer? 40]
[#:initial-connection-timeout initial-connection-timeout integer? 60])
(-> void)]{
Calls @scheme[serve] multiple times, once for each @scheme[port], and returns
a function that shuts down all of the server instances.
}
@defproc[(serve/ips+ports [#:dispatch dispatch dispatcher?]
[#:tcp\@ tcp\@ tcp-unit^ raw:tcp\@]
[#:ips+ports ips+ports (listof (cons/c (or/c string? false/c) (listof integer?))) (list (cons #f (list 80)))]
[#:max-waiting max-waiting integer? 40]
[#:initial-connection-timeout initial-connection-timeout integer? 60])
(-> void)]{
Calls @scheme[serve/ports] multiple times, once for each @scheme[ip], and returns
a function that shuts down all of the server instances.
}
@defproc[(do-not-return) void]{
This function does not return. If you are writing a script to load the @web-server
you are likely to want to call this functions at the end of your script.
}

View File

@ -1,31 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "servlet-env.ss"
#:style 'toc]{Environment}
@require[(for-label web-server/servlet-env)]
@defmodule[web-server/servlet-env]
The @web-server provides a means of running Scheme servlets
from within DrScheme, or any other REPL.
@filepath{servlet-env.ss} provides the servlet API from @filepath{servlet.ss}
as well as the following:
@defthing[send-url (parameter/c ([url string?] [separate-window? boolean?] . -> . void))]{
Should open @scheme[url]. In another window if @scheme[separate-window?] is true.
By default this is from @scheme[(lib "sendurl.ss" "net")].
}
@defform*[[(on-web servlet-expr)
(on-web port servlet-expr)]]{
The first form expands to @scheme[(on-web 8000 servlet-expr)].
Constructs a small servlet, where the body of the @scheme[start] procedure is
@scheme[servlet-expr], runs the @web-server on port @scheme[port], and calls
@scheme[send-url] with a URL for the constructed servlet. The call blocks until the
servlet finishes its computation, i.e. @scheme[servlet-expr] is evaluated, and
returns its result. @scheme[servlet-expr] may use the entire Scheme servlet API.
}

View File

@ -1,429 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "servlet"
#:style 'toc]{Scheme Servlets}
The @web-server allows servlets to be written in Scheme. It
provides the supporting API, described below, for the construction
of these servlets. This API is provided by @filepath{servlet.ss}.
@local-table-of-contents[]
@; ------------------------------------------------------------
@section[#:tag "module-servlets"]{Definition}
@require[(for-label "dummy-servlet.ss")] ; to give a binding context
@declare-exporting[web-server/doc/dummy-servlet]
A @defterm{servlet} is a module that provides the following:
@defthing[interface-version (one-of/c 'v1 'v2)]{
A symbol indicating the servlet interface the servlet conforms
to. This influences the other provided identifiers.
}
@defthing[timeout integer?]{
Only if @scheme[interface-version] is @scheme['v1].
This number is used as the @scheme[continuation-timeout] argument to
a timeout-based continuation manager used for this servlet. (See
@secref["timeouts.ss"].) (i.e., you do not have a choice of the manager
for this servlet and will be given a timeout-based manager.)
}
@defthing[manager manager?]{
Only if @scheme[interface-version] is @scheme['v2].
The manager for the continuations of this servlet.
}
@defproc[(start [initial-request request?])
response?]{
This function is called when an instance of this servlet is started.
The argument is the HTTP request that initiated the instance.
}
@; ------------------------------------------------------------
@section[#:tag "servlet-structs.ss"]{Contracts}
@require[(for-label web-server/servlet/servlet-structs)]
@defmodule[web-server/servlet/servlet-structs]
@filepath{servlet/servlet-structs.ss} provides a number of contracts
for use in servlets.
@defthing[k-url? contract?]{Equivalent to @scheme[string?].}
@defthing[response-generator? contract?]{Equivalent to @scheme[(k-url? . -> . response?)].}
@defthing[url-transform? contract?]{Equivalent to @scheme[(k-url? . -> . k-url?)].}
@defthing[expiration-handler? contract?]{Equivalent to @scheme[(or/c false/c (request? . -> . response?))].}
@defthing[embed/url? contract?]{Equivalent to @scheme[(((request? . -> . any/c)) (expiration-handler?) . opt-> . string?)].}
@; ------------------------------------------------------------
@section[#:tag "request-structs.ss"]{HTTP Requests}
@require[(for-label web-server/private/request-structs)]
@defmodule[web-server/private/request-structs]
@; XXX Create http sub-directory
@; XXX Have this include read-request and write-response
@filepath{private/request-structs.ss} provides a number of structures and functions
related to HTTP request data structures.
@defstruct[header ([field bytes?]
[value bytes?])]{
Represents a header of @scheme[field] to @scheme[value].
}
@defproc[(headers-assq [id bytes?] [heads (listof header?)])
(or/c false/c header?)]{
Returns the header with a field equal to @scheme[id] from @scheme[heads] or @scheme[#f].
}
@defproc[(headers-assq* [id bytes?] [heads (listof header?)])
(or/c false/c header?)]{
Returns the header with a field case-insensitively equal to @scheme[id] from @scheme[heads] or @scheme[#f].
}
@defstruct[binding ([id bytes?])]{Represents a binding of @scheme[id].}
@defstruct[(binding:form binding) ([value bytes?])]{
Represents a form binding of @scheme[id] to @scheme[value].
}
@defstruct[(binding:file binding) ([filename bytes?]
[content bytes?])]{
Represents the uploading of the file @scheme[filename] with the id @scheme[id]
and the content @scheme[content].
}
@defproc[(bindings-assq [binds (listof binding?)])
(or/c false/c binding?)]{
Returns the binding with an id equal to @scheme[id] from @scheme[binds] or @scheme[#f].
}
@defstruct[request ([method symbol?]
[uri url?]
[headers/raw (listof header?)]
[bindings/raw (listof binding?)]
[post-data/raw (or/c false/c bytes?)]
[host-ip string?]
[host-port number?]
[client-ip string?])]{
An HTTP @scheme[method] request to @scheme[uri] from @scheme[client-ip]
to the server at @scheme[host-ip]:@scheme[host-port] with @scheme[headers/raw]
headers, @scheme[bindings/raw] GET and POST queries and @scheme[post-data/raw]
POST data.
}
@; ------------------------------------------------------------
@section[#:tag "bindings.ss"]{Request Bindings}
@require[(for-label web-server/servlet/bindings)]
@defmodule[web-server/servlet/bindings]
@filepath{servlet/bindings.ss} provides a number of helper functions
for accessing request bindings.
@defproc[(request-bindings [req request?])
(listof (or/c (cons/c symbol? string?)
(cons/c symbol? bytes?)))]{
Translates the @scheme[request-bindings/raw] of @scheme[req] by
interpreting @scheme[bytes?] as @scheme[string?]s, except in the case
of @scheme[binding:file] bindings, which are left as is. Ids are then
translated into lowercase symbols.
}
@defproc[(request-headers [req request?])
(listof (cons/c symbol? string?))]{
Translates the @scheme[request-headers/raw] of @scheme[req] by
interpreting @scheme[bytes?] as @scheme[string?]s. Ids are then
translated into lowercase symbols.
}
@defproc[(extract-binding/single [id symbol?]
[binds (listof (cons/c symbol? string?))])
string?]{
Returns the single binding associated with @scheme[id] in the a-list @scheme[binds]
if there is exactly one binding. Otherwise raises @scheme[exn:fail].
}
@defproc[(extract-bindings [id symbol?]
[binds (listof (cons/c symbol? string?))])
(listof string?)]{
Returns a list of all the bindings of @scheme[id] in the a-list @scheme[binds].
}
@defproc[(exists-binding? [id symbol?]
[binds (listof (cons/c symbol? string))])
boolean?]{
Returns @scheme[#t] if @scheme[binds] contains a binding for @scheme[id].
Otherwise, @scheme[#f].
}
These functions, while convenient, could introduce subtle bugs into your
application. Examples: that they are case-insensitive could introduce
a bug; if the data submitted is not in UTF-8 format, then the conversion
to a string will fail; if an attacked submits a form field as if it were
a file, when it is not, then the @scheme[request-bindings] will hold a
@scheme[bytes?] object and your program will error; and, for file uploads
you lose the filename.
@; ------------------------------------------------------------
@section[#:tag "response-structs.ss"]{HTTP Responses}
@require[(for-label web-server/private/response-structs)]
@defmodule[web-server/private/response-structs]
@filepath{private/response-structs.ss} provides structures and functions related to
HTTP responses.
@; XXX Only use bytes
@defstruct[response/basic
([code number?]
[message string?]
[seconds number?]
[mime bytes?]
[headers (listof header?)])]{
A basic HTTP response containing no body. @scheme[code] is the response code,
@scheme[message] the message, @scheme[seconds] the generation time, @scheme[mime]
the MIME type of the file, and @scheme[extras] are the extra headers, in addition
to those produced by the server.
}
@; XXX Rename string? option
@defstruct[(response/full response/basic)
([body (listof (or/c string? bytes?))])]{
As with @scheme[response/basic], except with @scheme[body] as the response
body.
}
@defstruct[(response/incremental response/basic)
([generator ((() (listof (or/c bytes? string?)) . ->* . any) . -> . any)])]{
As with @scheme[response/basic], except with @scheme[generator] as a function that is
called to generate the response body, by being given an @scheme[output-response] function
that outputs the content it is called with.
}
@defproc[(response? [v any/c])
boolean?]{
Checks if @scheme[v] is a valid response. A response is either:
@itemize[
@item{A @scheme[response/basic] structure.}
@item{A value matching the contract @scheme[(cons/c (or/c bytes? string?) (listof (or/c bytes? string?)))].}
@item{A value matching @scheme[xexpr?].}
]
}
@defthing[TEXT/HTML-MIME-TYPE bytes?]{Equivalent to @scheme[#"text/html; charset=utf-8"].}
@warning{If you include a Content-Length header in a response that is inaccurate, there WILL be an error in
transmission that the server will not catch.}
@; ------------------------------------------------------------
@section[#:tag "web.ss"]{Web}
@require[(for-label web-server/servlet/web)]
@defmodule[web-server/servlet/web]{The
@schememodname[web-server/servlet/web] library provides the primary
functions of interest for the servlet developer.}
@defproc[(send/back [response response?])
void?]{
Sends @scheme[response] to the client.
}
@defthing[current-servlet-continuation-expiration-handler parameter?]{
Holds the @scheme[expiration-handler?] to be used when a continuation
captured in this context is expired, then looked up.
}
@defproc[(send/suspend [make-response response-generator?]
[exp expiration-handler? (current-servlet-continuation-expiration-handler)])
request?]{
Captures the current continuation, stores it with @scheme[exp] as the expiration
handler, and binds it to a URL. @scheme[make-response] is called with this URL and
is expected to generate a @scheme[response?], which is sent to the client. If the
continuation URL is invoked, the captured continuation is invoked and the request is
returned from this call to @scheme[send/suspend].
}
@defproc[(continuation-url? [u url?])
(or/c false/c (list/c number? number? number?))]{
Checks if @scheme[u] is a URL that refers to a continuation, if so
returns the instance id, continuation id, and nonce.
}
@; XXX Move
@defproc[(adjust-timeout! [t number?])
void?]{
Calls the servlet's manager's @scheme[adjust-timeout!] function.
}
@defproc[(clear-continuation-table!)
void?]{
Calls the servlet's manager's @scheme[clear-continuation-table!] function.
}
@defproc[(send/forward [make-response response-generator?]
[exp expiration-handler? (current-servlet-continuation-expiration-handler)])
request?]{
Calls @scheme[clear-continuation-table!], then @scheme[send/suspend].
}
@defproc[(send/finish [response response?])
void?]{
Calls @scheme[clear-continuation-table!], then @scheme[send/back].
}
@defproc[(send/suspend/dispatch [make-response (embed/url? . -> . response?)])
any/c]{
Calls @scheme[make-response] with a function that, when called with a procedure from
@scheme[request?] to @scheme[any/c] will generate a URL, that when invoked will call
the function with the @scheme[request?] object and return the result to the caller of
@scheme[send/suspend/dispatch].
}
@defproc[(redirect/get)
request?]{
Calls @scheme[send/suspend] with @scheme[redirect-to].
}
@defproc[(redirect/get/forget)
request?]{
Calls @scheme[send/forward] with @scheme[redirect-to].
}
@; XXX Remove
@defproc[(embed-ids [ids (list/c number? number? number?)]
[u url?])
string?]{
Creates a @scheme[continuation-url?].
}
@; XXX Remove
@defthing[current-url-transform parameter?]{
Holds a @scheme[url-transform?] function that is called by
@scheme[send/suspend] to transform the URLs it generates.
}
@; ------------------------------------------------------------
@section[#:tag "helpers.ss"]{Helpers}
@require[(for-label web-server/servlet/helpers)]
@defmodule[web-server/servlet/helpers]
@filepath{servlet/helpers.ss} provides functions built on
@filepath{servlet/web.ss} that are useful in many servlets.
@; XXX Move into http/response.ss
@defproc[(redirect-to [uri string?]
[perm/temp redirection-status? temporarily]
[#:headers headers (listof header?) (list)])
response?]{
Generates an HTTP response that redirects the browser to @scheme[uri],
while including the @scheme[headers] in the response.
}
@defproc[(redirection-status? [v any/c])
boolean?]{
Determines if @scheme[v] is one of the following values.
}
@defthing[permanently redirection-status?]{A @scheme[redirection-status?] for permanent redirections.}
@defthing[temporarily redirection-status?]{A @scheme[redirection-status?] for temporary redirections.}
@defthing[see-other redirection-status?]{A @scheme[redirection-status?] for "see-other" redirections.}
@defproc[(with-errors-to-browser [send/finish-or-back (response? . -> . void?)]
[thunk (-> any)])
any]{
Calls @scheme[thunk] with an exception handler that generates an HTML error page
and calls @scheme[send/finish-or-back].
}
@; XXX Depreciate
@; ------------------------------------------------------------
@section[#:tag "servlet-url.ss"]{Servlet URLs}
@require[(for-label web-server/servlet/servlet-url)]
@defmodule[web-server/servlet/servlet-url]
@filepath{servlet/servlet-url.ss} provides functions that might be useful to you.
They may eventually provided by another module.
@defproc[(request->servlet-url (req request?))
servlet-url?]{Generates a value to be passed to the next function.}
@defproc[(servlet-url->url-string/no-continuation [su servlet-url?])
string?]{
Returns a URL string without the continuation information in the URL
that went into @scheme[su]
}
@; XXX Support Digest
@; ------------------------------------------------------------
@section[#:tag "basic-auth.ss"]{Basic Authentication}
@require[(for-label web-server/servlet/basic-auth)]
@defmodule[web-server/servlet/basic-auth]
@filepath{servlet/basic-auth.ss} provides a function for helping with
implementation of HTTP Basic Authentication.
@defproc[(extract-user-pass [heads (listof header?)])
(or/c false/c (cons/c bytes? bytes?))]{
Returns a pair of the username and password from the authentication
header in @scheme[heads] if they are present, or @scheme[#f]
}
@; ------------------------------------------------------------
@section[#:tag "web-cells.ss"]{Web Cells}
@require[(for-label web-server/servlet/web-cells)]
@defmodule[web-server/servlet/web-cells]{The
@schememodname[web-server/servlet/web-cells] library provides the
interface to web cells.}
A web cell is a kind of state defined relative to the @defterm{frame tree}.
The frame-tree is a mirror of the user's browsing session. Every time a
continuation is invoked, a new frame (called the @defterm{current frame}) is
created as a child of the current frame when the continuation was captured.
You should use web cells if you want an effect to be encapsulated in all
interactions linked from (in a transitive sense) the HTTP response being
generated. For more information on their semantics, consult the paper
@href-link["http://www.cs.brown.edu/~sk/Publications/Papers/Published/mk-int-safe-state-web/"
"\"Interaction-Safe State for the Web\""].
@; XXX Document with-frame and with-frame-after?
@defproc[(web-cell? [v any/c])
boolean?]{
Determines if @scheme[v] is a web-cell.
}
@defproc[(make-web-cell [v any/c])
web-cell?]{
Creates a web-cell with a default value of @scheme[v].
}
@defproc[(web-cell-ref [wc web-cell?])
any/c]{
Looks up the value of @scheme[wc] found in the nearest
frame.
}
@defproc[(web-cell-shadow [wc web-cell?]
[v any/c])
void]{
Binds @scheme[wc] to @scheme[v] in the current frame, shadowing any
other bindings to @scheme[wc] in the current frame.
}
@include-section["servlet-env.scrbl"]

View File

@ -1,68 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "web-config-unit.ss"]{Web Config Unit}
@require[(for-label web-server/web-config-unit)]
@require[(for-label web-server/web-config-sig)]
The @web-server offers a unit-based approach to configuring the server.
@section{Configuration Signature}
@defmodule[web-server/web-config-sig]
@defsignature[web-config^ ()]{
@signature-desc{
Provides contains the following identifiers.
}
@defthing[max-waiting integer?]{
Passed to @scheme[tcp-accept].
}
@defthing[virtual-hosts (listof (cons/c string? host-table?))]{
Contains the configuration of individual virtual hosts.
}
@defthing[scripts (box/c (cache-table? path? servlet?))]{
Contains initially loaded servlets.
}
@defthing[initial-connection-timeout integer?]{
Specifies the initial timeout given to a connection.
}
@defthing[port port-number?]{
Specifies the port to serve HTTP on.
}
@defthing[listen-ip string?]{
Passed to @scheme[tcp-accept].
}
@defthing[make-servlet-namespace make-servlet-namespace?]{
Passed to @scheme[servlets:make].
}
}
@section{Configuration Units}
@defmodule[web-server/web-config-unit]
@defproc[(configuration-table->web-config\@ [path path?]
[#:port port (or/c false/c port-number?) #f]
[#:listen-ip listen-ip (or/c false/c string?) #f]
[#:make-servlet-namespace make-servlet-namespace make-servlet-namespace? (make-make-servlet-namespace)])
(unit? web-config^)]{
Reads the S-expression at @scheme[path] and calls @scheme[configuration-table-sexpr->web-config\@] appropriately.
}
@defproc[(configuration-table-sexpr->web-config\@ [sexpr list?]
[#:web-server-root web-server-root path? (directory-part default-configuration-table-path)]
[#:port port (or/c false/c port-number?) #f]
[#:listen-ip listen-ip (or/c false/c string?) #f]
[#:make-servlet-namespace make-servlet-namespace make-servlet-namespace? (make-make-servlet-namespace)])
(unit? web-config^)]{
Parses @scheme[sexpr] as a configuration-table and constructs a @scheme[web-config^] unit.
}

View File

@ -1,52 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "web-server-unit.ss"]{Web Server Unit}
@require[(for-label web-server/web-server-sig)]
@require[(for-label web-server/web-server-unit)]
The @web-server offers a unit-based approach to running the server.
@section{Signature}
@defmodule[web-server/web-server-sig]
@defsignature[web-server^ ()]{
@defproc[(serve) (-> void)]{
Runs the server and returns a procedure that shuts down the server.
}
@defproc[(serve-ports [ip input-port?]
[op output-port?])
void]{
Serves a single connection represented by the ports @scheme[ip] and
@scheme[op].
}
}
@section{Unit}
@defmodule[web-server/web-server-unit]
@defthing[web-server\@ (unit/c (web-config^ tcp^)
(web-server^))]{
Uses the @scheme[web-config^] to construct a @scheme[dispatcher?]
function that sets up one virtual host dispatcher, for each virtual
host in the @scheme[web-config^], that sequences the following
operations:
@itemize[
@item{Logs the incoming request with the given format to the given file}
@item{Performs HTTP Basic Authentication with the given password file}
@item{Allows the @scheme["/conf/refresh-passwords"] URL to refresh the password file.}
@item{Allows the @scheme["/conf/collect-garbage"] URL to call the garbage collector.}
@item{Allows the @scheme["/conf/refresh-servlets"] URL to refresh the servlets cache.}
@item{Execute servlets under the @scheme["/servlets/"] URL in the given servlet root directory.}
@item{Serves files under the @scheme["/"] URL in the given htdocs directory.}
]
Using this @scheme[dispatcher?], it loads a dispatching server that provides @scheme[serve]
and @scheme[serve-ports] functions that operate as expected.
}

View File

@ -1,38 +0,0 @@
#lang scribble/doc
@require["web-server.ss"]
@title[#:tag "web-server-ref"]{@bold{Web Server}: Reference Manual}
@author{Jay McCarthy (jay@"@"plt-scheme.org)}
The @web-server collection provides libraries that can be used to
develop Web applications in Scheme.
@table-of-contents[]
@include-section["running.scrbl"]
@include-section["servlet.scrbl"]
@include-section["lang.scrbl"]
@include-section["configuration.scrbl"]
@include-section["dispatchers.scrbl"]
@include-section["web-config-unit.scrbl"]
@include-section["web-server-unit.scrbl"]
@include-section["managers.scrbl"]
@include-section["private.scrbl"]
@include-section["faq.scrbl"]
@; ------------------------------------------------------------
@section[#:tag "ack"]{Acknowledgements}
We thank Matthew Flatt for his superlative work on MzScheme.
We thank the previous maintainers of the @web-server : Paul T. Graunke, Mike Burns, and Greg Pettyjohn
Numerous people have
provided invaluable feedback on the server, including Eli Barzilay, Ryan Culpepper, Robby
Findler, Dan Licata, Matt Jadud, Jacob Matthews, Matthias Radestock, Andrey Skylar,
Michael Sperber, Dave Tucker, Anton van Straaten, and Noel Welsh. We also thank the
many other PLT Scheme users who have exercised the server and offered critiques.
@index-section[]

View File

@ -1,31 +0,0 @@
#lang scheme/base
(require (lib "manual.ss" "scribble")
(lib "eval.ss" "scribble")
(for-label scheme/base
scheme/contract
scheme/unit))
(define web-server "Web Server")
; XXX Format better
(define (author x)
(elem (hspace 4)
(bold x)))
; XXX Format better
(define (warning . x)
(apply elem "Warning:" x))
; XXX Actually display link
(define (href-link url label)
(elem label " (" url ")"))
(provide (all-from-out (lib "manual.ss" "scribble"))
(all-from-out (lib "eval.ss" "scribble"))
(for-label (all-from-out scheme/base
scheme/contract
scheme/unit))
web-server
author
warning
href-link)

View File

@ -1,6 +1,6 @@
(module info setup/infotab
(define name "Web Server")
(define scribblings '(("doc/web-server.scrbl" (multi-page main-doc))))
(define scribblings '(("scribblings/web-server.scrbl" (multi-page main-doc))))
(define mzscheme-launcher-libraries
(list "main.ss"))