\section{Playing WEB (HTTP) server} \label{sec:httpd} Web presentation has attractive features. It is well accepted, standardised (if you stick to the basics) and network-transparent. Many people think you need a web-server like \href{http://www.apache.org}{Apache} with some sort of server-scripting (\idx{CGI}) to realise a server. This is not true. Any application capable of elementary TCP/IP communication can easily act as a web-server. Using \product{} for this task may be attractive for a number of reasons. \begin{itemlist} \item [Prototyping] As the \productpl{} running on your desktop is the server you can use the full debugging capabilities of Prolog to debug your server application. \item [Including graphics] \product{} can generate GIF and JPEG images for your web-pages on the fly. You can include \product{} \class{graphical} objects directly in the output and have the server library handle the required transformations. \item [Remote presentation] \product{} can be used as \idx{groupware} server, presenting state of the applications and allowing remote users to interact using their web-browser% \footnote{Using the Unix/X11 version \product{} can manage windows on multiple desktops. For MS-Windows users this is not supported.} \item [Report generation] Applications may to use HTML as framework for report generation. Though rather weak in its expressiveness, the advantage is the wide support on presentation and distribution applications. \end{itemlist} We start with a small demo, illustrating frames and text. \postscriptfig[width=0.9\linewidth]{httpd}{Mozilla showing \product{} generated figure} \input{httpd-ex} \subsection{Class \class{httpd}} The library \pllib{http/httpd} defines the class \class{httpd}. This subclass of \class{socket} deals with most of the HTTP protocol details, breaking down HTTP requests and encapsulating responses with the proper headers. The class itself is an \jargon{abstract} class, a subclass needs to be created and some of the \jargon{virtual methods} needs to be refined to arrive at a useful application. \begin{description} \sendmethod{httpd}{initialise}{Port:[int]} Create a server and bind it to \arg{Port}. If \arg{Port} is omitted a free port is chosen. With a specified port, 8080 is a commonly used alternative to the standard 80 used by web-servers. If you have a web-server running on the same machine you may can generate a page on your website redirecting a page to this server. The URI of this server is \mbox{\tt http:///}. \sendmethod{httpd}{accepted}{} This is sent after a connection has been accepted. The system implementation logs the new connection if debugging is enabled. You can refine or redefine this method, asking for the `socket<-peer_name' and sending ->free to the socket if you want to restrict access. \sendmethod{httpd}{request}{Data:sheet} This is sent from ->input after a complete request-header is received. ->input decodes the header-fields, places them in \arg{Data} and then calls ->request. The attribute-names in the sheet are downcase versions of the case-insensitive request fields of the HTTP header. In addition, the following fields are defined: \begin{center} \begin{tabular}{|l|p{0.7\linewidth}|} \hline \multicolumn{2}{|c|}{\bf Fields that are always present} \\ \hline request & \const{GET}, \const{POST}, etc. I.e.\ the first word of the request-header. In most cases this will be \const{GET}. \\ path & The `path' part of the request. This is normally used to decide on the response. If the path contains a ? (question mark) this and the remaining data are removed and decoded to the `form' attribute. \\ form & If the request is a \const{GET} request with form-data, the form attribute contains another sheet holding the decoded form-data. Otherwise <-form holds @nil. \\ http_version & Version of the HTTP protocol used by the client. Normally \const{1.0} or \const{1.1}. \\ \hline \multicolumn{2}{|c|}{\bf Other fields} \\ \hline user & If authorisation data is present, this contains the user-name. If this field is present, the password field is present too. \\ password & Contains the decoded password supplied by the user. \\ \hline \end{tabular} \end{center} After decoding the request, the user should compose a response and use ->reply or ->reply_html to return the response to the client. \sendmethod{httpd}{reply}{% Data:string|source_sink|pixmap, Type:[name], Status:[name], Header:[sheet]} Send a reply. This method or ->reply_html is normally activated at the end of the user's ->request implementation. Data is one of: \begin{itemlist} \item[A string or source_sink] If the reply is a \class{string}, \class{text_buffer}, \class{resource} or \class{file}, the data in this object will be returned. Unless otherwise specified ->reply assumes the data has \idx{mime-type} \const{text/plain}. \item[A pixmap] If the reply is a \class{pixmap} (or can be converted automatically, for example any \class{graphical}), this image is encoded as GIF or JPEG and sent with the corresponding \idx{image/gif} or \idx{image/jpeg} mime-type. For more information on image save-types, see `image->save_in'. \end{itemlist} \arg{Type} is the mimi-type returned and tells the browser what to do with the data. This should correspond with the content of \arg{Data}. For example, you can return a PNG picture from a file using \begin{code} send(HTTPD, reply, file('pict.png'), 'image/png'), \end{code} \arg{Status} is used to tell the client in a formal way how the request was processed. The default is \const{200 OK}. See the methods below for returning other values. \arg{Header} is a \class{sheet} holding additional name-value pairs. If present, they are simply added to the end of the reply-header. For example if you want to prevent the browser caching the result you can use \begin{code} send(HTTPD, reply, ..., sheet(attribute('Cache-Control', 'no-cache'))), \end{code} \sendmethod{httpd}{reply_html}{% Term:prolog, Status:[name], Header:[sheet]} Uses the \pllib{http/html_write} library to translate \arg{Term} into HTML text using DCG rules and then invokes ->reply using the \arg{Type} \const{text/html}. \arg{Status} and \arg{Header} are passed unmodified to ->reply. \end{description} In addition to the principal methods above, a number of methods are defined for dealing with abnormal replies such as denying permission, etc. \begin{description} \sendmethod{httpd}{forbidden}{What:[name]} Replies with a \const{403 Forbidden} message. \arg{What} may be provided to indicate what is forbidden. Default is the path from the current <-request. \sendmethod{httpd}{authorization_required}{% Method:[\{Basic\}], Realm:[name]} Challenges the user to provide a name and password. The only method provided is \const{Basic}. \arg{Realm} tells the user for which service permission is requested. On all subsequence contacts from this client to this server the ->request data contains the \const{user} and \const{password} fields. The demo implementation of ->request in \class{httpd} contains the following example code: \begin{pcecode} request(S, Header:sheet) :-> "Process a request. The argument is the header":: ( get(Header, path, '/no') -> send(S, forbidden, '/no') ; get(Header, path, '/maybe') -> ( get(Header, value, user, jan), get(Header, value, password, test) -> send(S, reply, 'You hacked me') ; send(S, authorization_required) ) ; send(S, reply, 'Nice try') ). \end{pcecode} \sendmethod{httpd}{not_found}{What:[char_array]} Reply with a \const{404 Not Found} message, using the request-path as default for \arg{What}. \sendmethod{httpd}{moved}{Where:char_array} Reply with a \const{301 Moved Permanently}. Normally the client will retry the request using the URL returned in \arg{Where}. \sendmethod{httpd}{server_error}{What:[char_array]} Reply with a \const{500 Internal Server} using `\arg{What} as additional information to the user. This is the default reply if ->request fails or raised an exception. \end{description}