Generating HTML
In the Demo Page example we used a series of format statements to emit the HTML needed by our page.
In fact CL-HTTP provides a much more flexible solution. It includes routines to emit all the HTML you need to construct finished Web pages. Using these routines has several advantages over printing the HTML directly:
- The CL-HTTP routines are generally descriptive of their function, so you can compose Web pages without knowing HTML.
- They take care of nesting tags and end tags correctly.
- Where possible, they check the validity of the parameters.
- The same routines can be used to generate different types of markup; for example, XHTML.
Here are some examples:
Routine | Description |
with-html-document | Creates a <html> ... </html> block. |
with-document-preamble | Creates a <head> ... </head> block. |
declare-title | Creates a <title> ... </title> statement. |
with-document-body | Creates a <body> ... </body> block. |
with-section-heading | Creates a <h1> ... </h1> heading. |
with-paragraph | Creates a <p> ... </p> paragraph. |
The with- routines enclose a block of statements with a start tag and end tag, whereas the declare routines emit a single construct. Each routine takes a :stream keyword parameter to specify the output stream used by the Web server.
The Demo Page example rewritten to use these HTML generating routines is then as follows:
(defun write-demo-page2 (url stream) "The response function for a simple computed URL, using HTML generation." (declare (ignore url)) (with-successful-response (stream :html) (with-html-document (:stream stream) (with-document-preamble (:stream stream) (declare-title "Demo Page" :stream stream)) (with-document-body (:stream stream) (with-section-heading ("Demo Page" :stream stream) (with-paragraph (:stream stream) (format stream "Welcome to our site!"))))))) (export-url "http://localhost:8000/demo2.html" :computed :response-function 'write-demo-page2)
Creating a standard response function
For convenience we can wrap the generation of the head and body codes in a with-page macro. It takes as parameters the url, stream, and page title:
(defmacro with-page ((url stream title) &body body) "Provides the response function to emit a page body." `(with-successful-response (,stream :html) (with-html-document (:stream ,stream) (with-document-preamble (:stream ,stream) (declare-title ,title :stream ,stream)) (with-document-body (:stream ,stream) (with-section-heading (,title :stream ,stream) ,@body)))))
Our demo page can then be written as:
(defun write-demo-page3 (url stream) (declare (ignore url)) (with-page (url stream "Demo Page") (with-paragraph (:stream stream) (format stream "Welcome to our site!"))))
This is exported with:
(export-url "http://localhost:8000/demo3.html" :computed :response-function 'write-demo-page3)
blog comments powered by Disqus