From: Lucian Mogosanu Date: Tue, 27 Aug 2019 13:00:29 +0000 (+0300) Subject: drafts, hunchentoot-vib: Update X-Git-Url: https://git.mogosanu.ro/?a=commitdiff_plain;h=0c7c5dca16708aa01d1e9a60324d0506aa89aade;p=thetarpit.git drafts, hunchentoot-vib: Update --- diff --git a/drafts/000-hunchentoot-vib.markdown b/drafts/000-hunchentoot-vib.markdown index d7733fb..70b752b 100644 --- a/drafts/000-hunchentoot-vib.markdown +++ b/drafts/000-hunchentoot-vib.markdown @@ -81,37 +81,104 @@ same as [header-in](#hi), with the request parameter bound to \*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] [**authorization**][ht-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. [rra] [**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! -[h] [**host**][ht-h]: +[h] [**host**][ht-h]: Reads the "Host" +header. -[ua] [**user-agent**][ht-ua]: +[ua] [**user-agent**][ht-ua]: Reads the +"User-Agent" header. -[ci] [**cookie-in**][ht-ci]: +[ci] [**cookie-in**][ht-ci]: Looks up the +cookie with the given name in the [cookies][ht-ci-slot] slot. -[r] [**referer**][ht-r]: +[r] [**referer**][ht-r]: Reads the "Referer" +header. -[gp] [**get-parameter**][ht-gp]: +[gp] [**get-parameter**][ht-gp]: Looks up +a specific GET parameter in [get-parameters][ht-gp-slot]. [pp2] [**post-parameter**][ht-pp2]: +Looks up a specific POST parameter in the +[post-parameters][ht-pp-slot] slot. -[p] [**parameter**][ht-p]: +[p] [**parameter**][ht-p]: Looks up a GET +parameter, and, if not found, a POST parameter with a specific name. -[hims] [**handle-if-modified-since**][ht-hims]: +[hims] [**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]. [rpd] [**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. [arv] [**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. -[darv] [**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]. -[rp] [**request-pathname**][ht-rp]: +[darv] [**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. + +[rp] [**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. [pp3] [**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. @@ -128,15 +195,15 @@ available. It does a bunch of more or less related things, let's take 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 @@ -173,17 +240,22 @@ fault for this abomination. 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 @@ -192,7 +264,7 @@ fault for this abomination. 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 @@ -241,8 +313,18 @@ fault for this abomination. [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