#<WSERVER port 2001 @ #x72511c72>

The server is now running in your Lisp. It's possible you'll get an error that says something about 'port already in use' when you try to start the server. This means port 2001 is already in use by some other server on your machine. In that case, the simplest fix is to use a different port, supplying a different argument to start and then using that value instead of 2001 in the URLs used throughout this chapter.

You can continue to interact with Lisp via the REPL because AllegroServe starts its own threads to handle requests from browsers. This means, among other things, that you can use the REPL to get a view into the guts of your server while it's running, which makes debugging and testing a lot easier than if the server is a complete black box.

Assuming you're running Lisp on the same machine as your browser, you can check that the server is up and running by pointing your browser at http://localhost:2001/. At this point you should get a page- not-found error message in the browser since you haven't published anything yet. But the error message will be from AllegroServe; it'll say so at the bottom of the page. On the other hand, if the browser displays an error dialog that says something like 'The connection was refused when attempting to contact localhost:2001,' it means either that the server isn't running or that you started it with a different port than 2001.

Now you can publish some files. Suppose you have a file hello.html in the directory /tmp/html with the following contents:

<html>

<head>

<title>Hello</title>

</head>

<body>

<p>Hello, world!</p>

</body>

</html>

You can publish it individually with the publish-file function.

WEB> (publish-file :path '/hello.html' :file '/tmp/html/hello.html')

#<NET.ASERVE::FILE-ENTITY @ #x725eddea>

The :path argument is the path that will appear in the URL requested by the browser, while the :file argument is the name of the file in the file system. After evaluating the publish- file expression, you can point your browser to http://localhost:2001/hello.html, and it should display a page something like Figure 26-2.

Figure 26-2. http://localhost:2001/hello.html

You could also publish a whole directory tree of files using the publish-directory function. First let's clear out the already published entity with the following call to publish-file:

WEB> (publish-file :path '/hello.html' :remove t)

NIL

Now you can publish the whole /tmp/html/ directory (and all its subdirectories) with the publish-directory function.

WEB> (publish-directory :prefix '/' :destination '/tmp/html/')

#<NET.ASERVE::DIRECTORY-ENTITY @ #x72625aa2>

In this case, the :prefix argument specifies the beginning of the path part of URLs that should be handled by this entity. Thus, if the server receives a request for http://localhost:2001/foo/bar.html, the path is /foo/bar.html, which starts with /. This path is then translated to a filename by replacing the prefix, /, with the destination, /tmp/html/. Thus, the URL http://localhost:2001/hello.html will still be translated into a request for the file /tmp/html/hello.html.

Generating Dynamic Content with AllegroServe

Publishing entities that generate dynamic content is nearly as simple as publishing static content. The functions publish and publish-prefix are the dynamic analogs of publish-file and publish-directory. The basic idea of these two functions is that you publish a function that will be called to generate the response to a request for either a specific URL or any URL with a given prefix. The function will be called with two arguments: an object representing the request and the published entity. Most of time you don't need to do anything with the entity object except to pass it along to a couple macros I'll discuss in a moment. On the other hand, you'll use the request object to obtain information submitted by the browser—query parameters included in the URL or data posted using an HTML form.

For a trivial example of using a function to generate dynamic content, let's write a function that generates a page with a different random number each time it's requested.

(defun random-number (request entity)

(with-http-response (request entity :content-type 'text/html')

(with-http-body (request entity)

(format

(request-reply-stream request)

'<html>~@

<head><title>Random</title></head>~@

<body>~@

<p>Random number: ~d</p>~@

</body>~@

</html>~@

'

(random 1000)))))

The macros with-http-response and with-http-body are part of AllegroServe. The former starts the process of generating an HTTP response and can be used, as here, to specify things such as the type of content that will be returned. It also handles various parts of HTTP such as dealing with If-Modified- Since requests. The with-http-body actually sends the HTTP response headers and then executes its body, which should contain code that generates the content of the reply. Within with-http- response but before the with-http-body, you can add or change HTTP headers to be sent in the reply. The function request-reply-stream is also part of AllegroServe and returns the stream to which you should write output intended to be sent to the browser.

As this function shows, you can just use FORMAT to print HTML to the stream returned by request-reply-stream. In the next section, I'll show you more convenient ways to programmatically generate HTML.[288]

Now you're ready to publish this function.

WEB> (publish :path '/random-number' :function 'random-number)

#<COMPUTED-ENTITY @ #x7262bab2>

As it does in the publish-file function, the :path argument specifies the path part of the URL that will result in this function being invoked. The :function argument specifies either the name or an actual function object. Using the name of a function, as shown here, allows you to redefine the function later without republishing and have AllegroServe use the new function definition. After evaluating the call to publish, you can point your browser at http:// localhost:2001/random- number to get a page with a random number on it, as shown in Figure 26-3.

Вы читаете Practical Common Lisp
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату