From: Lucian Mogosanu Date: Mon, 26 Aug 2019 15:58:46 +0000 (+0300) Subject: drafts, hunchentoot-vib: Discuss most interface methods X-Git-Url: https://git.mogosanu.ro/?a=commitdiff_plain;h=85caf1fc640584361e91396749df6030d77f971e;p=thetarpit.git drafts, hunchentoot-vib: Discuss most interface methods --- diff --git a/drafts/000-hunchentoot-vib.markdown b/drafts/000-hunchentoot-vib.markdown index f7a390a..d7733fb 100644 --- a/drafts/000-hunchentoot-vib.markdown +++ b/drafts/000-hunchentoot-vib.markdown @@ -6,88 +6,88 @@ author: Lucian Mogoșanu tags: tech, tmsr --- -[pr] [**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. +[sns] [**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. +[qss] [**query-string\***][ht-qss] -[wrp] [**within-request-p**][ht-wrp]: +[gps] [**get-parameters\***][ht-gps] -[rrp] -[**recompute-request-parameters**][ht-rrp]: +[his] [**headers-in\***][ht-his] -[sns] [**script-name\***][ht-sns]: +[cis] [**cookies-in\***][ht-cis] -[qss] [**query-string\***][ht-qss]: +[ras] [**remote-addr\***][ht-ras] -[gps] [**get-parameters\***][ht-gps]: +[rps] [**remote-port\***][ht-rps] -[pp] [**post-parameters**][ht-pp]: +[las] [**local-addr\***][ht-las] -[pps] [**post-parameters\***][ht-pps]: +[lps] [**local-port\***][ht-lps] -[his] [**headers-in\***][ht-his]: +[rus] [**request-uri\***][ht-rus] -[cis] [**cookies-in\***][ht-cis]: +[rms] [**request-method\***][ht-rms] -[hi] [**header-in**][ht-hi]: +[sps] [**server-protocol\***][ht-sps] -[his2] [**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] [**authorization**][ht-a]: +[pps] [**post-parameters\***][ht-pps]: +This one calls [post-parameters](#pp), which: -[ras] [**remote-addr\***][ht-ras]: +[pp] [**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. -[rps] [**remote-port\***][ht-rps]: +Similarly: -[las] [**local-addr\***][ht-las]: +[rrp] +[**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]. -[lps] [**local-port\***][ht-lps]: +However, we also have: -[rra] [**real-remote-addr**][ht-rra]: +[hi] [**header-in**][ht-hi]: Gets a +specific header from the [headers-in][ht-hi-slot] slot. -[h] [**host**][ht-h]: +[his2] [**header-in\***][ht-his2]: The +same as [header-in](#hi), with the request parameter bound to +\*request\*. -[rus] [**request-uri\***][ht-rus]: +And there's also these methods which dynamically bind \*request\*, +although their name doesn't end in "star": -[rms] [**request-method\***][ht-rms]: +[a] [**authorization**][ht-a]: -[sps] [**server-protocol\***][ht-sps]: +[rra] [**real-remote-addr**][ht-rra]: + +[h] [**host**][ht-h]: [ua] [**user-agent**][ht-ua]: @@ -109,21 +109,81 @@ fault for this abomination. [darv] [**delete-aux-request-value**][ht-darv]: +[rp] [**request-pathname**][ht-rp]: + [pp3] [**parse-path**][ht-pp3]: -[rp] [**request-pathname**][ht-rp]: +TODO: transition to process-request. + +[wrp] [**within-request-p**][ht-wrp]: + +TODO: another transition to process-request. + +[pr] [**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 @@ -132,7 +192,7 @@ fault for this abomination. 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 @@ -169,13 +229,20 @@ fault for this abomination. [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