#lang scribble/doc @(require scribble/manual) @(require (for-label web-server/http "../instaservlet.ss")) @title{Instaservlet} by Noel Welsh and Dave Gurnell @tt{{noel, dave} at @link["http://www.untyped.com"]{@tt{untyped}}} @italic{Instaservlet has been deprecated as of PLT 4.1.3. See the @secref{deprecation-notice} for more information.} Instaservlet is an extremely fast way to run a web application in the PLT Web Server. You provide a function that accepts a @scheme[request] argument and returns a @scheme[response]. Instaservlet sets up the web server with sensible defaults, and runs your servlet in a wrapper that handles the details of instance and continuation expiry for you. @section[#:tag "deprecation-notice"]{Deprecation notice} As of version 4.1.3, the PLT Web Server contains a quick-start procdure called @scheme[serve/servlet]. This procedure makes Instaservlet largely unnecessary: the package has consequently been deprecated and no future updates are planned. Instaservlet users are advised to rewrite Instaweb applications using @scheme[serve/servlet]. This is made considerably easier using the @link["http://planet.plt-scheme.org/display.ss?package=dispatch.plt&owner=untyped"]{Dispatch} package from Untyped. The next section describes how to migrate from Instaweb to @scheme[serve/servlet] if you are @italic{not} using Dispatch; the following section describes the transition if you @italic{are} using Dispatch. @subsection[#:tag "serve/servlet"]{Migrating to @scheme[serve/servlet] without using Dispatch} Instaservlet and @scheme[serve/servlet] use @italic{filesystem} and @italic{servlet dispatcher} procedures to handle requests. The dispatchers are chained together such that if one cannot handle a request the other is invoked. However, the order of dispatch is different: @itemize{ @item{ Instaservlet calls filesystem dispatcher first. If no matching file is found, it calls the servlet dispatcher instead.} @item{ @scheme[serve/servlet] checks to see if the URL matches a user-specified @scheme[#:servlet-regexp]: if it does, the procedure calls the servlet dispatcher. If the URL doesn't match, or if the servlet can't handle the request, the procedure calls the filesystem dispatcher instead. As of PLT 4.1.3, a servlet can signal that it cannot handle a request by calling the @scheme[next-dispatcher] procedure from the @scheme[web-server/dispatchers/dispatch] module.}} To recreate Instaservlet-style behaviour using @scheme[serve/servlet], use code like the following: @schemeblock[ (require net/url web-server/http web-server/servlet-env web-server/dispatchers/dispatch) (code:comment "Helper procedures --------------------------------") (code:comment "url -> boolean") (define (static-file-url? url) (let ([str (url->string url)]) (cond [(regexp-match #rx"^/stylesheets/" str) #t] [(regexp-match #rx"^/javascript/" str) #t] (code:comment "and so on...") [else #f]))) (code:comment "request -> response") (define (make-not-found-response request) (code:comment "create a pretty 404 response...")) (code:comment "Servlet procedure --------------------------------") (code:comment "request -> response") (define (start request) (when (static-file-url? (request-uri request)) (next-dispatcher)) (code:comment "continue handling the request...")) (code:comment "Main program body -------------------------------") (serve/servlet start (code:comment "blank regexp passes all requests to the servlet:") #:servlet-regexp #rx"" (code:comment "initial URL to send to the browser:") #:servlet-path "/" (code:comment "default port is different:") #:port 8765 (code:comment "prettify 404 messages (optional):") #:file-not-found-responder make-not-found-response)] @subsection[#:tag "dispatch"]{Migrating to @scheme[serve/servlet] using Dispatch} As of version 1.6, Dispatch interoperates with @scheme[serve/servlet] as you might expect. Rather than displaying a 404 page when none of the site URLs match, it calls @scheme[next-dispatcher]. To recreate Instaservlet-style behaviour using @scheme[serve/servlet] and Dispatch, use code like the following: @schemeblock[ (require web-server/http web-server/servlet-env web-server/dispatchers/dispatch (planet untyped/dispatch) (planet untyped/dispatch/response)) (code:comment "Site definition ----------------------------------") (code:comment "The site is normally written in a different module...") (code:comment "see the Dispatch documentation for more information.") (define-site my-site ([(url "/") home] (code:comment "and so on..."))) (code:comment "Servlet procedure --------------------------------") (code:comment "request -> response") (define (start request) (code:comment "Dispatch will handle the static file case:") (dispatch my-site request)) (code:comment "Main program body -------------------------------") (serve/servlet start (code:comment "blank regexp passes all requests to the servlet:") #:servlet-regexp #rx"" (code:comment "initial URL to send to the browser:") #:servlet-path "/" (code:comment "default port is different:") #:port 8765 (code:comment "pretty 404 messages provided by Dispatch:") #:file-not-found-responder make-not-found-response)] @section{Using Instaserlvet} Using Instaservlet is as simple as requiring the Instaservlet module and calling @scheme[go!] with your servlet function. For example, the following is a complete servlet that uses Instaservlet to handle all web-server configuration: @schemeblock[ (require (planet untyped/instaservlet/instaservlet)) (define (servlet request) '(html (head (title "It's working!")) (body (h1 "Instaservlet is in the house!")))) (go! servlet)] That is basically all there is to Instaservlet. By default the web-server listens on port 8765 to connections from the localhost only. You can change this by passing optional arguments to @scheme{go!}. See the @secref{api} for details. @section[#:tag "api"]{Instaservlet API} @defmodule[(planet untyped/instaservlet/instaservlet)]{ The main function is @scheme[go!]: @defproc[(go! (servlet (-> request any)) (#:port port integer/c 8765) (#:listen-ip listen-ip string? "127.0.0.1") (#:htdocs-path htdocs-path (listof (or/c path? string?)) default-htdocs-path) (#:mime-types-path mime-types-path path? default-mime-types-path) (#:servlet-namespace servlet-namespace (listof require-spec) default-servlet-namespace) (#:servlet-exn-handler servlet-exn-handler (-> url? exn? response) default-servlet-exn-handler)) void?]{Runs the given servlet in a web-server that has been setup (using Instaweb) with the given parameters (all of which are optional). By default the web server runs on port 8765 and listens only to connections from the localhost. Refer to the Instaweb documentation for more details.} } @;{end defmodule} @subsection{How The Servlet Is Run} Instaweb takes care of some important servlet configuration details for you: @itemize[ @item{The servlet uses the web-server's version 2 API} @item{Memory is managed with the LRU manager, which is much more robust than the timeout manager. The memory limit is set to 64MB. Continuations start with 24 life points. Life points are deducted at the rate of one every 10 minutes, or one every 5 seconds when the memory limit is exceeded. Hence the maximum life time for a continuation is 4 hours, and the minimum is 2 minutes.} @item{A default @tt{instance-expiration-handler} is installed, so users see a sensible error message on continuation expiry.} ] These settings will be made customisable in future releases on Instaservlet.