tags: tech, tmsr
---
-<a name="pr" href="#pr">[pr]</a> [**process-request**][ht-pr]: This
-function is on the main request processing/handling path, and is
-called by [process-connection][ht-pc] whenever a new HTTP request is
-available. It does a bunch of more or less related things, let's take
-'em one by one.
+This post is part of a series on [Common Lisp WWWism][cl-www], more
+specifically a continuation of "[Hunchentoot: requests and
+replies][hunchentoot-via]". In this second part of "requests and
+replies" we will dissect "replies" and what remains of "requests", in
+precisely the reverse order.
-a\. the first part of the function a1. defines and binds some special
-variables, e.g. the current \*request\* being processed, and a2. wraps
-everything into some condition handling code, namely: a2i. it "maps"
-all [conditions][ht-wmc][^1]; a2ii. wraps this in an
-[unwind-protect][clhs-unwind-protect][^2]; a2iii. all this wrapped in
-a [catch][clhs-catch][^3].
+We ended [last time][hunchentoot-via] with a look at code that parses
+GET and POST requests. This time we will look (in the following order)
+at: a set of "interface methods" aimed to be employed by the user when
+implementing request handlers; the [process-request](#pr) method; and,
+last but not least, at the methods exposed by the "reply" component in
+this orchestra.
-b\. the code at (a) wraps a b1. local procedure definition,
-report-error-to-client, which [logs][ht-lms] an error and returns a
-http-internal-error, i.e. [start-output][ht-so] on the result of an
-[acceptor-status-message][ht-asm]; and b2. a call to
-[handle-request][ht-hr] wrapped in a catch for "handler-done"[^4],
-with the return values for handle-request bound to "contents", "error"
-and "backtrace"; b3. if "error", then report-error-to-client; b4. if
-headers are not yet sent, [start-output][ht-so] with the return code
-of \*reply\* and whatever contents we have; b4. if no contents are
-set, then get a default page from [acceptor-status-message][ht-asm];
-b5. if an error occurs during (b4), then call report-error-to-client.
+First, we notice that most request accessors come with wrapper methods
+whose names end in a "star", which, by some arbitrary convention,
+means that they implicitly bind their current "request" parameter to
+the special variable \*request\*[^1]. Let's take a look at a few of
+these:
-c\. this occurs on the "cleanup-form" part of the unwind-protect at
-(a2ii): if there are any temporary files that were set up during the
-function, delete them.
+<a name="sns" href="#sns">[sns]</a> [**script-name\***][ht-sns]
-This function is all over the fucking place, owing mainly to the
-pretense of "modularity" and separation between requests and replies
--- I did say they're part of the same logical unit, didn't I? Just
-look at it: "request processing" calls "start output" -- which by the
-way, is part of "headers", right? but this same "start output" is the
-one which actually delivers a response to the client, which response
-delivery oughta be part of "reply"!! So to conclude: this whole shit
-is in dire need of refactoring and ultimately a complete
-rewrite. No-no, this time I'm pretty damn sure it's not the protocol's
-fault for this abomination.
+<a name="qss" href="#qss">[qss]</a> [**query-string\***][ht-qss]
-<a name="wrp" href="#wrp">[wrp]</a> [**within-request-p**][ht-wrp]:
+<a name="gps" href="#gps">[gps]</a> [**get-parameters\***][ht-gps]
-<a name="rrp" href="#rrp">[rrp]</a>
-[**recompute-request-parameters**][ht-rrp]:
+<a name="his" href="#his">[his]</a> [**headers-in\***][ht-his]
-<a name="sns" href="#sns">[sns]</a> [**script-name\***][ht-sns]:
+<a name="cis" href="#cis">[cis]</a> [**cookies-in\***][ht-cis]
-<a name="qss" href="#qss">[qss]</a> [**query-string\***][ht-qss]:
+<a name="ras" href="#ras">[ras]</a> [**remote-addr\***][ht-ras]
-<a name="gps" href="#gps">[gps]</a> [**get-parameters\***][ht-gps]:
+<a name="rps" href="#rps">[rps]</a> [**remote-port\***][ht-rps]
-<a name="pp" href="#pp">[pp]</a> [**post-parameters**][ht-pp]:
+<a name="las" href="#las">[las]</a> [**local-addr\***][ht-las]
-<a name="pps" href="#pps">[pps]</a> [**post-parameters\***][ht-pps]:
+<a name="lps" href="#lps">[lps]</a> [**local-port\***][ht-lps]
-<a name="his" href="#his">[his]</a> [**headers-in\***][ht-his]:
+<a name="rus" href="#rus">[rus]</a> [**request-uri\***][ht-rus]
-<a name="cis" href="#cis">[cis]</a> [**cookies-in\***][ht-cis]:
+<a name="rms" href="#rms">[rms]</a> [**request-method\***][ht-rms]
-<a name="hi" href="#hi">[hi]</a> [**header-in**][ht-hi]:
+<a name="sps" href="#sps">[sps]</a> [**server-protocol\***][ht-sps]
-<a name="his2" href="#his2">[his2]</a> [**header-in\***][ht-his2]:
+The implementation of these functions is, as can be readily observed,
+trivial, and the meaning should be easily deducible from the name;
+thus I won't bother the reader with redundant details. However,
+there's also:
-<a name="a" href="#a">[a]</a> [**authorization**][ht-a]:
+<a name="pps" href="#pps">[pps]</a> [**post-parameters\***][ht-pps]:
+This one calls [post-parameters](#pp), which:
-<a name="ras" href="#ras">[ras]</a> [**remote-addr\***][ht-ras]:
+<a name="pp" href="#pp">[pp]</a> [**post-parameters**][ht-pp]: Running
+":before" more specific implementations of this method are called;
+given a request, it calls [maybe-read-post-parameters][ht-mrpp]. If
+the post-parameters [slot][ht-pp-slot] is nil, then set the force
+parameter to true.
-<a name="rps" href="#rps">[rps]</a> [**remote-port\***][ht-rps]:
+Similarly:
-<a name="las" href="#las">[las]</a> [**local-addr\***][ht-las]:
+<a name="rrp" href="#rrp">[rrp]</a>
+[**recompute-request-parameters**][ht-rrp]: Calls
+[maybe-read-post-parameters][ht-mrpp] with the force argument always
+set to true. Also, set the [get-parameters][ht-gp-slot] to the
+[re-parsed][ht-fuelta] value of [query-string][ht-qs-slot].
-<a name="lps" href="#lps">[lps]</a> [**local-port\***][ht-lps]:
+However, we also have:
-<a name="rra" href="#rra">[rra]</a> [**real-remote-addr**][ht-rra]:
+<a name="hi" href="#hi">[hi]</a> [**header-in**][ht-hi]: Gets a
+specific header from the [headers-in][ht-hi-slot] slot.
-<a name="h" href="#h">[h]</a> [**host**][ht-h]:
+<a name="his2" href="#his2">[his2]</a> [**header-in\***][ht-his2]: The
+same as [header-in](#hi), with the request parameter bound to
+\*request\*.
-<a name="rus" href="#rus">[rus]</a> [**request-uri\***][ht-rus]:
+And there's also these methods which dynamically bind \*request\*,
+although their name doesn't end in "star":
-<a name="rms" href="#rms">[rms]</a> [**request-method\***][ht-rms]:
+<a name="a" href="#a">[a]</a> [**authorization**][ht-a]:
-<a name="sps" href="#sps">[sps]</a> [**server-protocol\***][ht-sps]:
+<a name="rra" href="#rra">[rra]</a> [**real-remote-addr**][ht-rra]:
+
+<a name="h" href="#h">[h]</a> [**host**][ht-h]:
<a name="ua" href="#ua">[ua]</a> [**user-agent**][ht-ua]:
<a name="darv" href="#darv">[darv]</a> [**delete-aux-request-value**][ht-darv]:
+<a name="rp" href="#rp">[rp]</a> [**request-pathname**][ht-rp]:
+
<a name="pp3" href="#pp3">[pp3]</a> [**parse-path**][ht-pp3]:
-<a name="rp" href="#rp">[rp]</a> [**request-pathname**][ht-rp]:
+TODO: transition to process-request.
+
+<a name="wrp" href="#wrp">[wrp]</a> [**within-request-p**][ht-wrp]:
+
+TODO: another transition to process-request.
+
+<a name="pr" href="#pr">[pr]</a> [**process-request**][ht-pr]: This
+function is on the main request processing/handling path, and is
+called by [process-connection][ht-pc] whenever a new HTTP request is
+available. It does a bunch of more or less related things, let's take
+'em one by one.
+
+a\. the first part of the function a1. defines and binds some special
+variables, e.g. the current \*request\* being processed, and a2. wraps
+everything into some condition handling code, namely: a2i. it "maps"
+all [conditions][ht-wmc][^2]; a2ii. wraps this in an
+[unwind-protect][clhs-unwind-protect][^3]; a2iii. all this wrapped in
+a [catch][clhs-catch][^4].
+
+b\. the code at (a) wraps a b1. local procedure definition,
+report-error-to-client, which [logs][ht-lms] an error and returns a
+http-internal-error, i.e. [start-output][ht-so] on the result of an
+[acceptor-status-message][ht-asm]; and b2. a call to
+[handle-request][ht-hr] wrapped in a catch for "handler-done"[^5],
+with the return values for handle-request bound to "contents", "error"
+and "backtrace"; b3. if "error", then report-error-to-client; b4. if
+headers are not yet sent, [start-output][ht-so] with the return code
+of \*reply\* and whatever contents we have; b4. if no contents are
+set, then get a default page from [acceptor-status-message][ht-asm];
+b5. if an error occurs during (b4), then call report-error-to-client.
+
+c\. this occurs on the "cleanup-form" part of the unwind-protect at
+(a2ii): if there are any temporary files that were set up during the
+function, delete them.
+
+This function is all over the fucking place, owing mainly to the
+pretense of "modularity" and separation between requests and replies
+-- I did say they're part of the same logical unit, didn't I? Just
+look at it: "request processing" calls "start output" -- which by the
+way, is part of "headers", right? but this same "start output" is the
+one which actually delivers a response to the client, which response
+delivery oughta be part of "reply"!! So to conclude: this whole shit
+is in dire need of refactoring and ultimately a complete
+rewrite. No-no, this time I'm pretty damn sure it's not the protocol's
+fault for this abomination.
-[^1]: with-mapped-conditions is actually a [usocket][usocket-wmc]
+[^1]: Special variables have a [special meaning][cltl-special] in
+ Common Lisp -- see what I did there? Namely, a special variable
+ may be declared globally and "bound dynamically", i.e. its value
+ may depend on its current execution context, such as, say, the
+ function or the thread where execution takes place, if it's been
+ bound this way using e.g. a let -- the naive me, who started his
+ adventure in Lisp programming in Scheme, thought let can only be
+ used for lexical bindings, and yet... look! Now, *if* there is no
+ such "dynamic binding" for that variable, then the variable's
+ *global* binding is used, which binding is shared between
+ execution contexts.
+
+ Yeah, what can I say... I didn't write this language, okay?
+
+[^2]: with-mapped-conditions is actually a [usocket][usocket-wmc]
macro which, annoyingly enough, is not documented. Long story
short, it can be used to define a context in which all usocket
conditions are safely handled. (TODO: add reference to usocket
coad?)
-[^2]: Which ensures that the code at the end of the function (TODO add
+[^3]: Which ensures that the code at the end of the function (TODO add
reference) gets executed no matter what conditions occur during
execution.
-[^3]: More precisely, the "request-processed" throw is caught here,
+[^4]: More precisely, the "request-processed" throw is caught here,
which, as the comment describes, is thrown by
[start-output][ht-so] after responding to a HEAD
request. Basically, what this does is exit process-request once
More details about this later.
-[^4]: We get there via [abort-request-handler][ht-arh], basically.
+[^5]: We get there via [abort-request-handler][ht-arh], basically.
[ht-pr]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L219
[ht-wrp]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L262
[ht-darv]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L576
[ht-pp3]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L585
[ht-rp]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L613
+[ht-mrpp]: /posts/y06/09c-hunchentoot-via.html#mrpp
[ht-pc]: http://thetarpit.org/posts/y06/098-hunchentoot-iv.html#pc
[ht-wmc]: http://coad.thetarpit.org/hunchentoot/c-util.lisp.html#L353
[ht-so]: http://coad.thetarpit.org/hunchentoot/c-headers.lisp.html#L67
-[ht-lms]: http://thetarpit.org/posts/y06/098-hunchentoot-iv.html#lms
-[ht-asm]: http://thetarpit.org/posts/y06/098-hunchentoot-iv.html#asm
-[ht-hr]: http://thetarpit.org/posts/y06/098-hunchentoot-iv.html#hr
+[ht-lms]: /posts/y06/098-hunchentoot-iv.html#lms
+[ht-asm]: /posts/y06/098-hunchentoot-iv.html#asm
+[ht-hr]: /posts/y06/098-hunchentoot-iv.html#hr
+[ht-pp-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L75
+[ht-gp-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L71
+[ht-qs-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L83
+[ht-fuelta]: /posts/y06/09c-hunchentoot-via.html#fn5
+[ht-hi-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L36
[ht-arh]: /posts/y06/098-hunchentoot-iv.html#selection-762.0-762.5
+[cltl-special]: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node58.html
[usocket-wmc]: https://quickref.common-lisp.net/usocket.html#go-to-the-USOCKET_003ccolon_003e_003ccolon_003eWITH_002dMAPPED_002dCONDITIONS-macro
[clhs-catch]: http://www.lispworks.com/documentation/HyperSpec/Body/s_catch.htm
[clhs-unwind-protect]: http://www.lispworks.com/documentation/HyperSpec/Body/s_unwind.htm