
The Functional Web Yaws: Yet Another Web Server Steve Vinoski • Verivue he modestly named Yaws — “Yet Another bytecode files and other parts of the Yaws sys- Web Server” — is an open source Erlang Web tem installed elsewhere under /usr/local. T server known for its reliability, stability, Command-line options for the generated config- and scalability. It started roughly a decade ago as ure script let you choose alternative installation the brainchild of legendary Erlang programmer locations. This approach is suitable for running Claes “Klacke” Wikström, who also invented sev- Yaws as a stand-alone Web server. Alternatively, eral important Erlang features, including Erlang you can build Yaws using rebar: term storage (ets), Distributed Erlang, the Mnesia database, and the Erlang bit syntax. Yaws is a rebar compile general-purpose HTTP 1.1 Web server consisting of a relatively simple core surrounded by imple- The result of this approach, which builds mentations of various features, such as response Yaws and installs it within its own build area, streaming, AJAX support, websockets support, can also run stand-alone but is best-suited for Common Gateway Interface (CGI) and Fast CGI applications that embed Yaws as an internal (FCGI) support, and application embedding. Web server. While it’s perfectly capable of performing regu- lar file serving, Yaws is most useful for applica- Runtime Configuration tions that generate and serve dynamic content. Yaws configuration controls details such as where it looks for files being served, what ports Configure, Make, Install it listens on, and what applications it loads to To get started with Yaws, you can either obtain handle requests. Two configuration portions an official release from its primary website, exist. Server configurations apply to individual http://yaws.hyber.org, or you can retrieve the virtual servers. A single Yaws instance can latest sources from the Yaws github.com source host multiple virtual servers on the same or repository: different IP addresses. Server configuration controls features such as on which port and IP git clone git://github.com/klacke/yaws.git address the server listens for requests, the root path in the filesystem from which Yaws serves You can build Yaws in two different ways: files, the types of scripts the server can execute, either using GNU autotools and make, or via the and the application modules, or appmods, that rebar Erlang build tool (see https://github.com/ are assigned to various URI paths. Appmods are basho/rebar). To use the autotools approach: very useful for dynamic Yaws Web applications, so I’ll present more details about them later. autoconf Global configuration applies to the running ./configure Yaws instance as a whole. It specifies directo- make && sudo make install ries where logs are deposited, from which Erlang bytecode is loaded, and from which include files This will build Yaws and by default install are retrieved for use in dynamically compiled it into /usr/local/bin/yaws, with Erlang beam application code. It also sets size and timeout 90 Published by the IEEE Computer Society 1089-7801/11/$26.00 © 2011 IEEE IEEE INTERNET COMPUTING IC-15-04-funw.indd 90 6/7/11 3:08 PM Yaws: Yet Another Web Server <html> limits for the Yaws internal file <erl> cache. out(Arg) -> The default configuration, which {ok, Title} = yaws_api:queryvar(Arg, "title"), Yaws reads from a file at startup, sets {ok, Name} = yaws_api:queryvar(Arg, "name"), up a regular HTTP server listening {ehtml, on port 8000 and a Secure Sockets [{head, [], Layer (SSL) server listening on port [{title, [], Title}]}, 4443. No changes to the default {body, [], configuration are needed to have a [{p, [], ["Hello, ", Name]}]}]}. working system, but of course you’re </erl> free to edit the configuration to your </html> liking. Extensive documentation is available for all global and server Figure 1. The example.yaws file. This file shows a Yaws out/1 Erlang function configuration settings. embedded between <erl> and </erl> tags. When a client requests the Internally, Yaws represents global example.yaws page, Yaws invokes the out/1 function, compiling it first if configuration using an Erlang record necessary, and substitutes its return value in place of the <erl> and </erl> named gconf and server configura- tags and everything between them. Yaws then returns the resulting HTML tions using Erlang sconf records. page to the client. These records are defined in a public include file for use by Yaws appli- Once it appears there, it will be gen- comprising a tag, a list of attributes, cations, especially those that start erally available to all Erlang Web and a body list. The head tag shown Yaws as an embedded Web server. servers and other applications. here, for example, has an empty Embedded applications can’t rely on attribute list and a body list consist- Yaws reading its configuration from Dynamic Applications ing of the title 3-tuple, which itself a file and must instead feed a valid Because Yaws primarily targets also has an empty attribute list and configuration via gconf and sconf dynamic applications, it provides sev- a body list which is the title string record instances to Yaws when start- eral useful features for them. One such (in Erlang, strings are just lists of ing it as an embedded server. feature is “ehtml,” which is regular characters). Applications can create HTML represented as Erlang terms. ehtml constructs more easily than File Serving For example, here’s some simple strings of HTML, and ehtml is less Yaws primarily targets applications HTML: error-prone because the Erlang com- that generate dynamic content, but piler enforces syntactical correct- we couldn’t consider it a general- <head><title>Hello World ness of the tuples and lists. purpose Web server if it couldn’t </title></head> A related dynamic application serve files. Each server configura- <body><p>Hello, World!</p> feature is the ability to embed Erlang tion tells Yaws where to find the doc- </body> code within HTML. When a request ument root for that server, and Yaws arrives for a file with a “.yaws” suf- then uses request URI paths to find And here is the same content repre- fix, Yaws processes any Erlang code requested files relative to that root. sented in ehtml: it finds within the file between <erl> There’s nothing special about Yaws’s and </erl> tags, replacing the tags file serving capabilities except that {ehtml, and the code between them with the it’s alone among Erlang Web serv- [{head, [], result of executing the code. Such ers in using the sendfile operating [{title, [], "Hello World"}]}, code, which is expected to reside system system call where available {body, [], within a function named out/1 to make file delivery as efficient as [{p, [], "Hello, World!"}]}]} (where the “/1” indicates the function possible. However, it likely won’t hold arity, or number of arguments), is this distinction forever, given that at As the example shows, ehtml compiled and also cached for future the time of this writing, the send- constructs are quite similar to their invocations. file capability was being extracted HTML counterparts but, assuming For example, consider the some- from Yaws and refactored for inclu- familiarity with Erlang syntax, are what contrived example.yaws file in sion in a future release of Erlang easier to read. Each HTML tag is Figure 1. If a client requests this and its accompanying Open Telecom represented as an Erlang atom, and resource from the Yaws server, the Platform (OTP) utility framework. each construct is generally a 3-tuple actual document served depends on JULY/AUGUST 2011 91 IC-15-04-funw.indd 91 6/7/11 3:08 PM The Functional Web out(Arg) -> Uri = yaws_api:request_url(Arg), means that it will receive all requests NewId = create_new_id(), sent to that server. Segs = [Uri#url.path, NewId], The result of the out/1 function NewPath = string:join(Segs, "/"), typically supplies the status, head- NewUri = Uri#url{path = NewPath}, ers, and body for the client response. NewLoc = yaws_api:format_url(NewUri), For example, the appmod in Figure 2 Json = json2:encode( returns a response suitable for a POST {struct, [{"location", NewLoc}]}), request creating a new resource. [{status, 201}, This out/1 function creates a new {header, {"Location", NewLoc}}, resource and a URI to identify it. It {content, "application/json", Json}]. first extracts the target URI from the request Arg, which returns a Yaws Figure 2. Application module. This appmod out/1 function returns a response url record instance. It then calls the suitable for a POST request creating a new resource. It first obtains the target create_new_id/0 function to gener- URI and augments a copy of it with an identifier for the new resource. It then ate a new identifier to use in the new creates a JSON object with a “location” key to store the new resource URI, URI (the details of create_new_id/0 and also returns the new URI as the value of the response Location header. are unimportant here). It then copies The result specifies HTTP status and the Location header, and includes the the target URI record but sets its path JSON object string as the response body. component to that of the new URI path string. To create the response values of the query parameters “title” • various sections of the path por- body, it uses the Yaws json2 module and “name” appearing within the URI tion of the request URI, to create a JSON object whose “loca- used to access the resource. Within • the request body (such as for tion” key contains the URI string for the code, the two calls to the yaws_ HTTP POST, PUT, and PATCH), if the new resource.
Details
-
File Typepdf
-
Upload Time-
-
Content LanguagesEnglish
-
Upload UserAnonymous/Not logged-in
-
File Pages5 Page
-
File Size-