\*request\*.
And there's also these methods which dynamically bind \*request\*,
-although their name doesn't end in "star":
+although their name doesn't end in "star"[^2]:
-<a name="a" href="#a">[a]</a> [**authorization**][ht-a]:
+<a name="a" href="#a">[a]</a> [**authorization**][ht-a]: Reads the
+"authorization" header and tries to parse the user/password
+combination associated included, if they exist. Notice the magic
+number 5 used in this shitty piece of coad, because writing a proper
+parser for yet-another-set-of-ad-hoc-encoded-parameters is too much
+work.
<a name="rra" href="#rra">[rra]</a> [**real-remote-addr**][ht-rra]:
+Reads the "X-Forwarded-For" header and, if it exists, it parses the
+client and proxy address fields and returns them. Apparently there's
+no "official spec" to be found for this, apparently the whole thing's
+superseded by some other syntax specified in [some
+RFC][rfc-7239]. Hunchentoot doesn't parse this one, however,
+so... well!
-<a name="h" href="#h">[h]</a> [**host**][ht-h]:
+<a name="h" href="#h">[h]</a> [**host**][ht-h]: Reads the "Host"
+header.
-<a name="ua" href="#ua">[ua]</a> [**user-agent**][ht-ua]:
+<a name="ua" href="#ua">[ua]</a> [**user-agent**][ht-ua]: Reads the
+"User-Agent" header.
-<a name="ci" href="#ci">[ci]</a> [**cookie-in**][ht-ci]:
+<a name="ci" href="#ci">[ci]</a> [**cookie-in**][ht-ci]: Looks up the
+cookie with the given name in the [cookies][ht-ci-slot] slot.
-<a name="r" href="#r">[r]</a> [**referer**][ht-r]:
+<a name="r" href="#r">[r]</a> [**referer**][ht-r]: Reads the "Referer"
+header.
-<a name="gp" href="#gp">[gp]</a> [**get-parameter**][ht-gp]:
+<a name="gp" href="#gp">[gp]</a> [**get-parameter**][ht-gp]: Looks up
+a specific GET parameter in [get-parameters][ht-gp-slot].
<a name="pp2" href="#pp2">[pp2]</a> [**post-parameter**][ht-pp2]:
+Looks up a specific POST parameter in the
+[post-parameters][ht-pp-slot] slot.
-<a name="p" href="#p">[p]</a> [**parameter**][ht-p]:
+<a name="p" href="#p">[p]</a> [**parameter**][ht-p]: Looks up a GET
+parameter, and, if not found, a POST parameter with a specific name.
-<a name="hims" href="#hims">[hims]</a> [**handle-if-modified-since**][ht-hims]:
+<a name="hims"
+href="#hims">[hims]</a> [**handle-if-modified-since**][ht-hims]: Reads
+the "If-Modified-Since" header and compares it with a given time
+argument. If the two dates match, then a. set the reply as follows:
+a1. the content-length to nil; a2. remove the content-length header;
+a3. the return-code to http-not-modified; then
+b. [abort-request-handler][ht-arh].
<a name="rpd" href="#rpd">[rpd]</a> [**raw-post-data**][ht-rpd]:
+a\. First, try to set an external-format based on the values of
+arguments force-binary, external-format and force-text; if no
+external-format is set and force-binary is not set, then try getting
+one from [external-format-from-content-type][ht-effct], and if that
+fails, fall back to \*hunchentoot-default-external-format\*.
+
+b\. Get the [raw-post-data][ht-rpd-slot] slot; if not set, then get
+post data by calling [get-post-data][ht-gpd]. Given a local binding to
+raw-post-data, the return value is determined based, in order, on the
+following conditions: b1. if raw-post-data is a stream, then return
+it; else b2. if raw-post-data is t or nil, return nil; else b3. if
+external-format was set, [octets-to-string][flex-ots] on raw-post-data
+and return the result; otherwise b4. return raw-post-data as-is.
<a name="arv" href="#arv">[arv]</a> [**aux-request-value**][ht-arv]:
+If the given request is non-nil, then look up a value in the alist
+given by the [aux-data][ht-ad-slot] slot. Return, as multiple values,
+both the value and the symbol-value pair itself.
-<a name="darv" href="#darv">[darv]</a> [**delete-aux-request-value**][ht-darv]:
+There's also a [defsetf][ht-arv2] defined for this function, which
+looks up the value and a. if it exists, sets the new value, and b. if
+it doesn't, pushes a new symbol-value pair to [aux-data][ht-ad-slot].
-<a name="rp" href="#rp">[rp]</a> [**request-pathname**][ht-rp]:
+<a name="darv"
+href="#darv">[darv]</a> [**delete-aux-request-value**][ht-darv]:
+Similarly to [aux-request-value](#arv), operates on
+[aux-data][ht-ad-slot]; this one deletes a symbol-value binding from
+the alist.
+
+<a name="rp" href="#rp">[rp]</a> [**request-pathname**][ht-rp]: Given
+a request, a. get its [script-name][ht-sn-slot]; and
+b. [parse-path](#pp3). If drop-prefix is set to a string representing
+a path prefix, then the pathname is returned sans said prefix.
<a name="pp3" href="#pp3">[pp3]</a> [**parse-path**][ht-pp3]:
+Sanitization function used by [request-pathname](#rp) to bring a
+path-string to the proper abstraction level, i.e. a Common Lisp
+pathname. After a. parsing the namestring using either
+[parse-namestring][clhs-parse-namestring] or some
+implementation-specific function, e.g. SBCL's
+[parse-native-namestring][sbcl-nf], run the following checks:
+
+b\. the host field of the pathname is nil, or it equals that of
+\*default-pathname-defaults\*; c\. the device field of the pathname is
+nil, or it equals that of \*default-pathname-defaults\*; d\. the
+directory component is nil, or it's a relative pathname without :up
+and :wild; e\. the pathname name and type fields are either nil or
+strings; f\. the namestring isn't "..".
+
+g\. When (b)-(f) are satisfied, return the parsed pathname.
TODO: transition to process-request.
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].
+all [conditions][ht-wmc][^3]; a2ii. wraps this in an
+[unwind-protect][clhs-unwind-protect][^4]; a2iii. all this wrapped in
+a [catch][clhs-catch][^5].
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],
+[handle-request][ht-hr] wrapped in a catch for "handler-done"[^6],
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
Yeah, what can I say... I didn't write this language, okay?
-[^2]: with-mapped-conditions is actually a [usocket][usocket-wmc]
+[^2]: Not like this so-called convention is specified anywhere, so
+ we're stuck guessing why these are named this way while the others
+ are named the other. I could come up with some ideas, but why
+ bother.
+
+[^3]: 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?)
-[^3]: Which ensures that the code at the end of the function (TODO add
+[^4]: Which ensures that the code at the end of the function (TODO add
reference) gets executed no matter what conditions occur during
execution.
-[^4]: More precisely, the "request-processed" throw is caught here,
+[^5]: 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.
-[^5]: We get there via [abort-request-handler][ht-arh], basically.
+[^6]: 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-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-ci-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L68
[ht-arh]: /posts/y06/098-hunchentoot-iv.html#selection-762.0-762.5
+[ht-rpd-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L94
+[ht-gpd]: /posts/y06/09c-hunchentoot-via.html#gpd
+[ht-effct]: /posts/y06/09c-hunchentoot-via.html#effct
+[ht-ad-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L90
+[ht-sn-slot]: http://coad.thetarpit.org/hunchentoot/c-request.lisp.html#L79
+[clhs-parse-namestring]: http://clhs.lisp.se/Body/f_pars_1.htm
+[sbcl-nf]: http://www.sbcl.org/manual/#Native-Filenames
+[flex-ots]: http://edicl.github.io/flexi-streams/#octets-to-string
[cltl-special]: https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node58.html
+[rfc-7239]: https://tools.ietf.org/html/rfc7239#section-4
[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