262 lines
10 KiB
TeX
262 lines
10 KiB
TeX
\documentclass{article}
|
|
|
|
\usepackage[plainpages=false,colorlinks]{hyperref}
|
|
\usepackage{alltt}
|
|
\usepackage{times}
|
|
\usepackage{tabularx}
|
|
\usepackage{epsfig}
|
|
\usepackage{amssymb}
|
|
\usepackage{epstopdf}
|
|
%\usepackage{fancyref}
|
|
|
|
\pagestyle{headings}
|
|
|
|
\setcounter{tocdepth}{3}
|
|
\setcounter{secnumdepth}{3}
|
|
|
|
\setlength\parskip{\medskipamount}
|
|
\setlength\parindent{0pt}
|
|
|
|
\newcommand{\bs}{\char'134}
|
|
\newcommand{\dq}{\char'42}
|
|
\newcommand{\tto}{\symbol{123}}
|
|
\newcommand{\ttc}{\symbol{125}}
|
|
\newcommand{\pound}{\char'43}
|
|
\newcommand{\hhat}{\symbol{94}}
|
|
|
|
\newcommand{\ttindex}[1]{\texttt{#1}\index{\texttt{#1}}}
|
|
|
|
\newcommand{\vocabulary}[1]{\emph{Vocabulary:} \texttt{#1}&\\}
|
|
|
|
\newcommand{\parsingword}[2]{\index{\texttt{#1}}\emph{Parsing word:} \texttt{#2}&\\}
|
|
|
|
\newcommand{\ordinaryword}[2]{\index{\texttt{#1}}\emph{Word:} \texttt{#2}&\\}
|
|
|
|
\newcommand{\symbolword}[1]{\index{\texttt{#1}}\emph{Symbol:} \texttt{#1}&\\}
|
|
|
|
\newcommand{\classword}[1]{\index{\texttt{#1}}\emph{Class:} \texttt{#1}&\\}
|
|
|
|
\newcommand{\genericword}[2]{\index{\texttt{#1}}\emph{Generic word:} \texttt{#2}&\\}
|
|
|
|
\newcommand{\predword}[1]{\ordinaryword{#1}{#1~( object -- ?~)}}
|
|
|
|
\setlength{\tabcolsep}{1mm}
|
|
|
|
\newcommand{\wordtable}[1]{
|
|
|
|
%HEVEA\renewcommand{\index}[1]{}
|
|
%HEVEA\renewcommand{\glossary}[1]{}
|
|
|
|
\begin{tabularx}{12cm}{lX}
|
|
\hline
|
|
#1
|
|
\hline
|
|
\end{tabularx}
|
|
|
|
}
|
|
|
|
\makeatletter
|
|
|
|
\makeatother
|
|
|
|
\makeindex
|
|
|
|
\begin{document}
|
|
|
|
\title{Factor Web Framework}
|
|
|
|
\author{Slava Pestov}
|
|
|
|
\maketitle
|
|
\tableofcontents{}
|
|
|
|
Factor includes facilities for interoperating with web-based services. This includes an HTTP client, and an HTTP server with a continuation-based web application framework.
|
|
|
|
\section{HTTP client}
|
|
|
|
\wordtable{
|
|
\vocabulary{http-client}
|
|
\ordinaryword{http-get}{http-get ( url -- code headers stream )}
|
|
}
|
|
Connects to the server specified in the URL, and makes a \verb|GET| request to retreive that resource.
|
|
|
|
\wordtable{
|
|
\vocabulary{http-client}
|
|
\ordinaryword{http-post}{http-post ( type content url -- code headers stream )}
|
|
}
|
|
Attempts to connect to the server specified in the URL, and makes a \verb|POST| request with the specified content type and content. The content is automatically URL-encoded for you.
|
|
|
|
With both words, the output values are as follows:
|
|
\begin{description}
|
|
\item[\texttt{code}] an integer with the HTTP response code; for example, 404 denotes ``file not found'' whereas 200 means ``success''.
|
|
\item[\texttt{headers}] an association list of returned headers.
|
|
\item[\texttt{stream}] a stream for reading the resource.
|
|
\end{description}
|
|
|
|
The following pair of words convert a string to and from its URL-encoded form.
|
|
|
|
\wordtable{
|
|
\vocabulary{http}
|
|
\ordinaryword{url-encode}{url-encode ( string -- string )}
|
|
\ordinaryword{url-decode}{url-decode ( string -- string )}
|
|
}
|
|
These words are called automatically by much of the web framework, however they are sometimes useful to call directly.
|
|
|
|
\section{HTTP server}\label{httpd}
|
|
|
|
The HTTP server listens for requests on a port and hands them off to responders. A responder takes action based on the type of request.
|
|
|
|
\wordtable{
|
|
\vocabulary{httpd}
|
|
\ordinaryword{httpd}{httpd ( port -- )}
|
|
}
|
|
Starts listening for HTTP requests on \verb|port|.
|
|
|
|
The HTTP server is usually started with a phrase like the following:
|
|
\begin{alltt}
|
|
USING: httpd threads ;
|
|
[ 8888 httpd ] in-thread
|
|
\end{alltt}
|
|
|
|
\wordtable{
|
|
\vocabulary{httpd}
|
|
\ordinaryword{stop-httpd}{stop-httpd ( -- )}
|
|
}
|
|
Stops the HTTP server.
|
|
|
|
A useful application of the HTTP server is the built-in vocabulary browser. You can use it simply by starting the HTTP server then visiting the following location:
|
|
|
|
\begin{verbatim}
|
|
http://localhost:8888/responder/browser/
|
|
\end{verbatim}
|
|
|
|
\subsection{Serving static content}
|
|
|
|
Static content may be served by setting the \verb|"doc-root"| variable to a directory holding the content. This variable may be set in the global namespace, or indeed, individually on each virtual host.
|
|
\begin{verbatim}
|
|
"/var/www/" "doc-root" set
|
|
\end{verbatim}
|
|
|
|
If a directory holds an \verb|index.html| file, the file is served when the directory is requested, otherwise a directory listing is produced.
|
|
|
|
A facility for ad-hoc server-side scripting exists. If a file with the \verb|.factsp| filename extension is requested, the file is run with \verb|run-file| and any output it sends to the default stream is sent to the client. These ``Factor server pages'' are slower and less powerful than responders, so it is recommended that responders be used instead.
|
|
|
|
A different static site can be associated with each virtual host by setting the \verb|"doc-root"| variable in each virtual host (\ref{vhosts}).
|
|
|
|
\subsection{Responders}
|
|
|
|
The HTTP server listens on a port number for HTTP requests and issues requests to \emph{responders}. The following form of request is understood specially by the HTTP server:
|
|
\begin{verbatim}
|
|
http://myhost/responder/foo/bar
|
|
\end{verbatim}
|
|
Such a request results in the \verb|foo| responder being invoked with the \verb|bar| argument. Requesting a path that does not begin with \verb|/responder| simply invokes the file responder with that path, as documented in the previous section.
|
|
|
|
\subsubsection{Managing responders}
|
|
|
|
\wordtable{
|
|
\vocabulary{httpd}
|
|
\symbolword{responders}
|
|
}
|
|
Responders are located in a hashtable stored in the \verb|responders| variable. This variable must be in scope when the \verb|httpd| word is invoked. This is usually the case, as the global namespace includes a default value filled out with all responders that are included as part of the library.
|
|
|
|
The following words manage the set of installed responders:
|
|
|
|
\wordtable{
|
|
\vocabulary{httpd}
|
|
\ordinaryword{set-default-responder}{set-default-responder ( name -- )}
|
|
}
|
|
Sets the default responder, that is, the one handling requests not prefixed by \verb|/responder|, to the responder \verb|name|. The initial value for the default responder is \verb|"file"|, identifying the file responder.
|
|
\wordtable{
|
|
\vocabulary{httpd}
|
|
\ordinaryword{add-responder}{add-responder ( responder -- )}
|
|
}
|
|
Adds a responder to the hashtable stored in the \verb|responders| variable that is in scope.
|
|
|
|
\subsubsection{Developing a responder}
|
|
|
|
A responder is a hashtable where the following keys must be set:
|
|
|
|
\begin{description}
|
|
\item[\texttt{"responder"}] The name of the responder
|
|
\item[\texttt{"get"}] A quotation with stack effect \verb|( resource -- )|, invoked when a client requests the path \texttt{/responder/\emph{name}/\emph{resource}} using the \texttt{GET} method
|
|
\item[\texttt{"post"}] A quotation with stack effect \verb|( resource -- )|, invoked when a client requests the path using the \texttt{POST} method
|
|
\item[\texttt{"head"}] A quotation with stack effect \verb|( resource -- )|, invoked when a client requests the path using the \texttt{HEAD} method
|
|
\end{description}
|
|
|
|
The quotations are called by the HTTP server in the dynamic scope of the responder, with the following additional variables set:
|
|
|
|
\begin{description}
|
|
\item[\texttt{"method"}] The HTTP method requested by the client; one of \texttt{"get"}, \texttt{"post"} or \texttt{"head"}
|
|
\item[\texttt{"request"}] The full URL requested by the client, sans any query parameters trailing a \verb|?| character
|
|
\item[\texttt{"query"}] An association list of URL-decoded string pairs, obtained by splitting the query string, if any
|
|
\item[\texttt{"raw-query"}] The raw query string. Usually not used
|
|
\item[\texttt{"header"}] An association list of URL-decoded string pairs, obtained from the headers sent by the client
|
|
\item[\texttt{"response"}] Only set in the \verb|POST| method, an association list of string pairs, obtained from the response sent by the client
|
|
\end{description}
|
|
|
|
\subsection{Virtual hosts}\label{vhosts}
|
|
|
|
Factor's HTTP server supports virtual hosting. This is done with an additional layer of indirection, where each virtual host has its own set of responders. Virtual hosting is optional; by default, all virtual hosts share the same set of responders.
|
|
|
|
\wordtable{
|
|
\vocabulary{httpd}
|
|
\symbolword{vhosts}
|
|
}
|
|
|
|
Virtual hosts are defined in a hashtable mapping virtual host names to hashtables of responders. An initial value for this variable is defined in the global namespace; it provides an empty default virtual host. The default virtual host is the value associated with the \verb|"default"| key.
|
|
|
|
When a client makes a request, the HTTP server first searches for a responder in the requested virtual host; if no responder is found there, the default virtual host is checked. If this also fails, the global \verb|responders| variable is tested.
|
|
|
|
As an example, suppose the machine running the HTTP server has two DNS aliases, \verb|porky.ham.net| and \verb|spam.ham.net|. The following setup will serve two different static web sites from each virtual host, whereas all other responders are taken from the global table, and are shared between the two hosts:
|
|
|
|
\begin{verbatim}
|
|
vhosts get [
|
|
"porky.ham.net" {{
|
|
[[ "doc-root" "/var/www/porky/" ]]
|
|
}} set
|
|
"spam.ham.net" {{
|
|
[[ "doc-root" "/var/www/spam/" ]]
|
|
}} set
|
|
] bind
|
|
\end{verbatim}
|
|
|
|
\section{HTML streams}\label{html}
|
|
|
|
An HTML stream wraps an existing stream. Strings written to the HTML stream have their special characters converted to HTML entities via the \verb|chars>entities| word documented below. In addition, the \texttt{attrs} parameter to the \texttt{stream-format} word is inspected for style attributes that direct the stream to wrap the output in various HTML tags.
|
|
|
|
\wordtable{
|
|
\vocabulary{html}
|
|
\ordinaryword{with-html-stream}{with-html-stream ( quot -- )}
|
|
}
|
|
Calls the quotation in a new dynamic scope. The \texttt{stdio} variable is set to an HTML stream wrapping the previous value of \texttt{stdio}, so calls to \texttt{write}, \texttt{format} and \texttt{print} go through the HTML stream.
|
|
|
|
\wordtable{
|
|
\vocabulary{html}
|
|
\ordinaryword{html-document}{html-document ( title quot -- )}
|
|
}
|
|
Builds on \texttt{with-html-stream} to emit the basic structure of an HTML document, consisting of \texttt{<html>}, \texttt{<head>} and \texttt{<body>} tags. The title is output in two places; a \texttt{<title>} tag and \texttt{<h1>} tag.
|
|
|
|
\wordtable{
|
|
\vocabulary{html}
|
|
\ordinaryword{simple-html-document}{simple-html-document ( title quot -- )}
|
|
}
|
|
Like \texttt{html-document}, except the output is wrapped inside a \texttt{<pre>} tag.
|
|
|
|
\wordtable{
|
|
\vocabulary{html}
|
|
\ordinaryword{chars>entities}{chars>entities ( string -- string )}
|
|
}
|
|
Converts various special characters in the input string (or any sequence of characters) into corresponding HTML entities. The following characters are converted:
|
|
|
|
\begin{tabular}{l|l}
|
|
Character&Entity\\
|
|
\hline
|
|
\verb|<| &\verb|<|\\
|
|
\verb|>| &\verb|>|\\
|
|
\verb|&| &\verb|&|\\
|
|
\verb|'| &\verb|'|\\
|
|
\verb|"| &\verb|"|
|
|
\end{tabular}
|
|
|
|
\end{document}
|