Ocsigen, a Web Programming Framework
Total Page:16
File Type:pdf, Size:1020Kb
Experience Report: Ocsigen, a Web Programming Framework Vincent Balat Jer´ omeˆ Vouillon Boris Yakobowski Laboratoire Preuves, Programmes et Systemes` Universite´ Paris Diderot (Paris 7), CNRS Paris, France fvincent.balat, jerome.vouillon, [email protected] Abstract Web programming is highly constrained by technology (pro- The evolution of Web sites towards very dynamic applications tocols, standards and browsers implementations). Commonly used makes it necessary to reconsider current Web programming tech- Web programming tools remain very close to this technology. We nologies. We believe that Web development would benefit greatly believe that Web development would benefit a lot from higher level from more abstract paradigms and that a more semantical approach paradigms and that a more semantical approach would result in would result in huge gains in expressiveness. In particular, func- huge gains in expressiveness. tional programming provides a really elegant solution to some im- It is now widely known in our community that functional pro- portant Web interaction problems, but few frameworks take advan- gramming is a really elegant solution to some important Web in- tage of it. teraction problems, as it offers a solution to the statelessness of the The Ocsigen project is an attempt to provide global solutions HTTP protocol (Queinnec 2000; Graham 2001; Hughes 2000). But this wisdom has not spread in the Web programming community. to these needs. We present our experience in designing this general 1 framework for Web programming, written in Objective Caml. It Almost no major Web framework is taking advantage of it. We provides a fully featured Web server and a framework for program- believe the reason is that functional programming has never been ming Web applications, with the aim of improving expressiveness fully exploited and that one must be very careful about the way it is and safety. This is done by taking advantage of functional program- integrated in a complete framework in order to match precisely the ming and static typing as much as possible. needs of Web developers. The Ocsigen project is trying to find global solutions to these Categories and Subject Descriptors D.1.1 [PROGRAMMING needs. In this paper, we present our experience in designing Ocsi- TECHNIQUES]: Applicative (Functional) Programming; H.3.5 gen, a general framework for Web programming in Objective Caml [INFORMATION STORAGE AND RETRIEVAL]: Online Informa- (Leroy et al. 2008). It provides a full featured Web server and a tion Services—Web-based services framework for programming Web applications, with the aim of im- proving expressiveness and safety. This is done by taking advantage General Terms Design, Languages, Reliability, Security of functional programming and static typing as much as possible Keywords Ocsigen, Web, Networking, Programming, Implemen- (Balat 2006). tation, Objective Caml, ML, Services, Typing, Xhtml This paper is a wide and quick overview of our experience regarding this implementation. In section 2, we describe our use 1. Introduction of functional programming. In section 3, we show how some very strong correctness properties can be encoded using Ocaml’s type In the last few years, the Web has evolved from a data-centric plat- system. Finally, in section 4, we describe the implementation of a form into a much more dynamic one. We tend now to speak more concrete Web application using our solutions. and more of Web application, rather than Web sites, which hints that the interaction between the user and the server is becoming much more complex than it used to be. 2. Functional Programming for the Web What is striking is that this evolution has not been induced, nor even followed, by a corresponding evolution of the underlying The Ocsigen project provides a Web server written in Objective technology. The RFC specifying the version of the HTTP protocol Caml. This server offers all the features one would expect from a currently in use dates back to 1999 and current HTML looks very general purpose Web server, starting with a comprehensive support much like the one we were using ten years ago. The main change of the HTTP 1.1 protocol (Fielding et al. 1999) (including range is probably the increasing use of JavaScript, mainly due to imple- requests and pipelining). Data compression, access control and mentation improvements, which made possible the advent of a new authentication are all supported. The server is configured through kind of Web applications. flexible XML-based configuration files. The server is designed in a modular way. It can therefore be extended very easily just by writing new modules in Ocaml. Among the modules currently available are a module for running CGI scripts, a reverse proxy (which makes it easy to use Ocsigen with Permission to make digital or hard copies of all or part of this work for personal or another Web server), a filter to compress contents, etc. classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation In the remainder of this section, we highlight the concurrency on the first page. To copy otherwise, to republish, to post on servers or to redistribute model used for the Web server implementation, and then our main to lists, requires prior specific permission and/or a fee. ICFP’09, August 31–September 2, 2009, Edinburgh, Scotland, UK. Copyright c 2009 ACM 978-1-60558-332-7/09/08. $5.00 1 A notable exception being Seaside (Ducasse et al. 2004). 311 extension to the server, that is, Eliom, a framework for writing Web let srv = register_new_service applications in Ocaml. ~path:["bar"] ~get_params:unit 2.1 Cooperative Threads f A Web server is inherently a highly concurrent application. It must The first argument (labelled ~path), corresponds to the path in the be able to handle simultaneously a large number of requests. Fur- URL to which the service will be bound. The second argument thermore, composing a page may take some time, for instance when (labelled ~get_params) describes URL parameters (here none, as several database queries are involved. The server should not to be this service does not expect any parameter). The function f is used stalled in the meantime. We have chosen to use cooperative multi- to produce the corresponding page. threading to address this issue. Indeed, cooperative threads make Inside Eliom, one can generate an anchor linking to this service it possible to write multi-threaded code while avoiding most race by applying the HTML anchor constructor a to the service srv, conditions, as context switches only occur at well-specified points. the current service context sp (which contains in particular the Between these points, all operations are executed atomically. In current URL, and is used to construct relative links), the text of the particular, it is easy to use safely shared mutable datastructures, anchor anchor_contents and the unit value () corresponding to such as hash tables, without using any lock. the absence of parameters. We use the Lwt thread library (Vouillon 2008), which provides a srv sp anchor contents () a monadic API for threads. With this library, a function creating a Web page asynchronously will typically have type: Note that the service URL can be changed just by modifying the path at a single location in the source code, and all links will remain unit ! html Lwt.t: correct as they are computed automatically. It returns immediately a promise (sometimes also called future) of Several services can share the same URL, for instance when type html Lwt.t, that is, a value that acts as a proxy for the value they expect different parameters. This means that a service will of type html eventually computed by the function. Promises are a not respond if some of its arguments are missing or ill-typed, monad. The return operator of the monad has type: avoiding a whole class of hard-to-detect errors.2 More generally, 'a ! 'a Lwt.t: a full range of service kinds is provided, allowing to describe precisely how services are attached to URLs. This makes it possible It creates an immediately fulfilled promise. The bind operator has to describe very flexible and precise Web interactions in just a few type: lines of code. A service can be associated to a path (and possibly parameters), to the value of a special parameter, or to both or them. 'a Lwt.t ! ('a ! 'b Lwt.t) ! 'b Lwt.t: The choice of the right service to invoke is performed automatically by Eliom. It takes as arguments a promise and a function to be applied to Services can be dynamically created in response to previous the value of the promise when it becomes available. The promise interactions with the user. Their behavior may depend for instance returned by the operator gives access to the value eventually com- on the contents of previous forms submitted by the user or the puted by the function. This operator can be used for sequencing result of previous computations. This is implemented by recording asynchronous operations, as well as for synchronization (for wait- the behavior associated to the service as a function closure in a ing for the completion of some operation before performing further table on the server. This is an instance of continuation-based Web operations). programming (Queinnec 2000; Hughes 2000; Graham 2001), This In order to make it possible to use third-party non-cooperative is known to be a really clean solution to the so-called back button libraries, Lwt also allows to detach some computations to preemp- problem, but is provided by very few Web frameworks. tive threads. It is also possible to classify services with respect to the type of the value they return.