(:head (:title 'Simple Form'))

(:body

(:form :method 'POST' :action '/show-query-params'

(:table

(:tr (:td 'Foo')

(:td (:input :name 'foo' :size 20)))

(:tr (:td 'Password')

(:td (:input :name 'password' :type 'password' :size 20))))

(:p (:input :name 'submit' :type 'submit' :value 'Okay')

(:input ::type 'reset' :value 'Reset'))))))))))

(publish :path '/simple-form' :function 'simple-form)

Point your browser to http://localhost:2001/simple-form, and you should see a page like the one in Figure 26-5.

Figure 26-5. http://localhost:2001/simple- form

If you fill in the form with the 'abc' and 'def' values, clicking the Okay button should take you to a page like the one in Figure 26-6.

Figure 26-6. Result of submitting the simple form

However, most of the time you won't need to iterate over all the query parameters; you'll want to pick out individual parameters. For instance, you might want to modify random-number so the limit value you pass to RANDOM can be supplied via a query parameter. In that case, you use the function request-query-value, which takes the request object and the name of the parameter whose value you want and returns the value as a string or NIL if no such parameter has been supplied. A parameterizable version of random-number might look like this:

(defun random-number (request entity)

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

(with-http-body (request entity)

(let* ((*html-output* (request-reply-stream request))

(limit-string (or (request-query-value 'limit' request) ''))

(limit (or (parse-integer limit-string :junk-allowed t) 1000)))

(html

(:html

(:head (:title 'Random'))

(:body

(:p 'Random number: ' (:print (random limit))))))))))

Because request-query-value can return either NIL or an empty string, you have to deal with both those cases when parsing the parameter into a number to pass to RANDOM. You can deal with a NIL value when you bind limit-string, binding it to '' if there's no 'limit' query parameter. Then you can use the :junk-allowed argument to PARSE- INTEGER to ensure that it returns either NIL (if it can't parse an integer from the string given) or an integer. In the section 'A Small Application Framework,' you'll develop some macros to make it easier to deal with grabbing query parameters and converting them to various types.

Cookies

In AllegroServe you can send a Set-Cookie header that tells the browser to save a cookie and send it along with subsequent requests by calling the function set-cookie-header within the body of with-http-response but before the call to with-http-body. The first argument to the function is the request object, and the remaining arguments are keyword arguments used to set the various properties of the cookie. The only two you must pass are the :name and :value arguments, both of which should be strings. The other possible arguments that affect the cookie sent to the browser are :expires, :path, :domain, and :secure.

Of these, you need to worry only about :expires. It controls how long the browser should save the cookie. If :expires is NIL (the default), the browser will save the cookie only until it exits. Other possible values are :never, which means the cookie should be kept forever, or a universal time as returned by GET-UNIVERSAL- TIME or ENCODE-UNIVERSAL-TIME. An :expires of zero tells the client to immediately discard an existing cookie.[290]

After you've set a cookie, you can use the function get-cookie-values to get an alist containing one name/value pair for each cookie sent by the browser. From that alist, you can pick out individual cookie values using ASSOC and CDR.

The following function shows the names and values of all the cookies sent by the browser:

(defun show-cookies (request entity)

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

(with-http-body (request entity)

(with-html-output ((request-reply-stream request))

(html

(:standard-page

(:title 'Cookies')

(if (null (get-cookie-values request))

(html (:p 'No cookies.'))

(html

(:table

(loop for (key . value) in (get-cookie-values request)

do (html (:tr (:td key) (:td value)))))))))))))

(publish :path '/show-cookies' :function 'show-cookies)

The first time you load the page http://localhost:2001/show-cookies it should say 'No cookies' as shown in Figure 26-7 since you haven't set any yet.

Figure 26-7. http://localhost:2001/show- cookies with no cookies

To set a cookie, you need another function, such as the following:

(defun set-cookie (request entity)

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

(set-cookie-header request :name 'MyCookie' :value 'A cookie value')

(with-http-body (request entity)

(with-html-output ((request-reply-stream request))

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

0

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

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