drop web-server/doc
svn: r8284
This commit is contained in:
parent
3b394bda4e
commit
a934de478f
|
@ -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].
|
||||
}
|
|
@ -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.
|
||||
}}
|
|
@ -1,6 +0,0 @@
|
|||
#lang scheme/base
|
||||
|
||||
(define start #f)
|
||||
|
||||
(provide (all-defined-out))
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#lang scheme/base
|
||||
|
||||
(define interface-version #f)
|
||||
(define timeout #f)
|
||||
(define start #f)
|
||||
(define manager #f)
|
||||
|
||||
(provide (all-defined-out))
|
||||
|
|
@ -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)].
|
|
@ -1,3 +0,0 @@
|
|||
(module info setup/infotab
|
||||
(define name "Web Server documentation"))
|
||||
|
|
@ -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].}
|
|
@ -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.
|
|
@ -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.
|
||||
}
|
|
@ -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.
|
||||
}
|
|
@ -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.
|
||||
}
|
|
@ -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"]
|
|
@ -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.
|
||||
}
|
|
@ -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.
|
||||
}
|
|
@ -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[]
|
|
@ -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)
|
|
@ -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"))
|
||||
|
|
Loading…
Reference in New Issue
Block a user