From: Lucian Mogosanu Date: Fri, 26 Jul 2019 11:33:21 +0000 (+0300) Subject: drafts, hunchentoot-iii: Proofread X-Git-Tag: v0.11~23 X-Git-Url: https://git.mogosanu.ro/?a=commitdiff_plain;h=26ddf7311edb45847ca3387d592b155c0f7c6593;p=thetarpit.git drafts, hunchentoot-iii: Proofread --- diff --git a/drafts/000-hunchentoot-iii.markdown b/drafts/000-hunchentoot-iii.markdown index 603e5d3..d4c61aa 100644 --- a/drafts/000-hunchentoot-iii.markdown +++ b/drafts/000-hunchentoot-iii.markdown @@ -34,9 +34,9 @@ found inside the big ones represent methods specializing on a given class. The green boxes are user actionable or defineable methods, so this is where you should start looking; while the arrows denote the "X calls Y" relation, with the exception of the dashed green arrow, that -denotes that header-out is in fact a setf-able object used from -somewhere within the context of acceptor-dispatch-request, e.g. a -dispatcher function. +tells us that header-out is in fact a setf-able accessor used from +somewhere within the context of acceptor-dispatch-request (e.g. from a +request handler) to read and modify the header of a reply. Now from this airplane view, Hunchentoot's organization looks quite digestible, which should give us a very good idea of how to start @@ -56,7 +56,7 @@ I'm using The Tar Pit as my playground, but you can use whatever you fancy. Looking at [acceptor-dispatch-request][ht-acceptor-dispatch-request], we notice that it calls [handle-static-file][ht-handle-static-file] with the -[document-root][ht-document-root] as a parameter. So let's set that, +[document-root][ht-document-root] as an argument. So let's set that, and additionally the error template directory, to our site: ~~~~ {.commonlisp} @@ -66,7 +66,7 @@ and additionally the error template directory, to our site: "/home/spyked/thetarpit/site/") ~~~~ -and now `curl http://localhost:8052` should serve our site. +and now `curl http://localhost:8052` should serve its contents. But let's say we want to go one step further and serve some content (server-side) dynamically. The original Hunchentoot @@ -89,8 +89,8 @@ server to respond with "Hey, spyked!". We have a few possible ways of doing this. We could for example edit the current implementation of [acceptor-dispatch-request][ht-acceptor-dispatch-request], which is -also the ugliest possible approach. On the other hand, Hunchentoot -makes us of Common Lisp's Object System mechanism (CLOS), which allows +also the ugliest possible approach. On the other hand, Hunchentoot is +built using Common Lisp's Object System mechanism (CLOS), which allows us to subclass the acceptor to a user-defined class and specialize the method above for our class. Let's try this out: @@ -119,30 +119,30 @@ method: In human words: this is an implementation of acceptor-dispatch-request specialized on myacceptor, that, upon encountering the URL -(script-name) "/yo", takes the value of the "name" parameter and -returns it as plain text. Otherwise it transfers control to the "next -most specific method"[^4], implicitly passing to it the existing -parameters. +(script-name) "/yo", takes the value of the GET parameter known as +"name" and returns a response string (possibly containing this "name") +as plain text. Otherwise it transfers control to the "next most +specific method"[^4], implicitly passing to it the existing arguments. We could stop here, but we won't, as there's a short discussion to be had, mainly related to the extensibility of our approach, i.e. what -happens when we add other "/yo"s to this recipe? The naive result will -look ugly and will be a pain to maintain and debug; while the more -elaborate approach, involving putting every "/yo" into its own +happens when we add other custom URLs to this recipe? The naive result +will look ugly and will be a pain to maintain and debug; while the +more elaborate approach, involving putting every "/yo" into its own function, will initially fill our implementation with cond/case conditions, eventually leading to a more civilized dispatch mechanism, -involving a lookup table from URLs to handler functions. +in the form of a lookup table from URLs to handler functions. Well, it so happens that Hunchentoot already has an implementation for this type of thing, going under the name of [easy-acceptor][ht-easy-acceptor]. easy-acceptor defines a dispatch -table whose only dispatcher is (initially, if the user desires) the -[dispatch-easy-handler][ht-dispatch-easy-handler] function, which -looks up URLs in a global handler list, thus making it possible to -e.g. share handlers between acceptors. As things usually go with these +table whose only dispatcher is (initially) the +[dispatch-easy-handlers][ht-dispatch-easy-handlers] function, which +looks up handlers for URLs in a global handler list, +\*easy-handler-alist\*. As things usually go with these [domain-specific languages][cl-who-ii-fn4], most of the handler -maintenance work is piled up in -[define-easy-handler][ht-define-easy-handler]. +maintenance work is piled up in the +[define-easy-handler][ht-define-easy-handler] macro. So, in order to illustrate this easy-stuff, first let's undo some of our previous work and redo the very basics: @@ -157,7 +157,7 @@ our previous work and redo the very basics: (hunchentoot:start *myaccept*) ~~~~ -Notice how now we're sublassing easy-acceptor. Now we can define an +Notice how now we're instancing easy-acceptor. Now we can define an equivalent "easy handler" for our previous "/yo" work: ~~~~ {.commonlisp} @@ -166,13 +166,13 @@ equivalent "easy handler" for our previous "/yo" work: (format nil "Hey~@[, ~A~]!" name)) ~~~~ -which about sums up our exercise. Initially I had wanted this to -contain an example doing some fancy prefix/"smart" URL lookup à la +which about sums up our exercise. Initially I had wanted to show an +example doing some fancy prefix/"smart" URL lookup à la [MP-WP][mp-wp], but by now this post is so large that it can't be eaten in one sitting. Alas, I will have to leave all my fancy examples for another episode. Thus, until next time... -[^1]: Contrary to popular belief and expectations, the things that +[^1]: Contrary to popular beliefs and expectations, the things that some particular X can do that are known to (some particular) me are not to be confused with the total set of things that said X can possibly do, nor with the set of things that it *can't* @@ -189,7 +189,7 @@ for another episode. Thus, until next time... expectations; and by the time I publish a [signed][io] genesis for this Hunchentoot thing -- good, bad, with or without warts or however we have it -- I will be entirely able to say what it does - and doesn't do, which is exactly what I'm doing here right now. + and doesn't do, which is exactly what I'm working on here and now. And now to be an asshole and leave this otherwise properly rounded footnote hanging: what about, say, [usocket][usocket]? and then @@ -212,9 +212,9 @@ for another episode. Thus, until next time... is that graph generation involves an automated step, i.e. node layout generation and edge routing, that can easily prove to be a pain in the ass for the user: not only do I want this diagram - generated, but I also want the diagram generated like *so*, and - not like *that*, because I want the viewer to be able to look at - the components of the graph in some particular order. + generated, but I also want it to be arranged like *so*, and not + like *that*, because I want the viewer to be able to look at the + components of the graph in some particular order. To add insult to injury, this automated step is almost entirely opaque to the user: in order to have that square near that one, I @@ -227,30 +227,30 @@ for another episode. Thus, until next time... if I'm in the wrong. Now that I have a representation, I need to embed it in the blog - post. One would expect that's also straightforward, wouldn't they? - Well, no! You see, I got the idea that putting clickable links in - the generated SVG files is cool, only this doesn't work in the - slightest when inserting the .svg using img tags, because - completely counter-intuitively, the browser displays *an image*, + post. One would expect that's also straightforward, wouldn't he? + Well, no! You see, I got the idea that placing clickable links in + generated SVG files is cool, only this doesn't work in the + slightest when inserting the "<img>" tag, because completely + counter-intuitively for a SVG, the browser displays *an image*, not a DOM sub-tree. So then I look at how Phf did it with his [patch viewer][btcbase-patches], and it looks like he's inserting a HTML image-map in the HTML document, which kinda beats the purpose of having links in the SVG in the first place. I really, - *really* don't want to copy-paste the whole SVG file into the - post, so what the fuck am I gonna do, use <object> tags?! + *really* don't want to copy-paste the whole diagram into the post, + so what the fuck am I gonna do, use <object> tags?! So if by now you were curious enough to look at the page source, - you'll notice that what I did was to insert an inline svg that - then imports the content of my .svg file using the + you'll notice that what I did was to insert an inline <svg> + that then imports the content of my .svg file using the [<use>][svg-use] tag, which works exactly the way I want it. And no, you won't find this anywhere on Google either, because Google [doesn't fucking work][btcbase-1922361]. To sum this up: IMHO the result looks pretty cool, with the - mention that I'm most likely going to draw the SVG "by hand" next - time I'm doing anything non-trivial. At least then no magic tool - will lie to me that it saves hours of my work, when it instead - adds to it. + mention that I'm most likely going to write the SVG diagram "by + hand" next time I'm doing anything non-trivial. At least then no + magic tool will lie to me that it saves hours of my work, when it + instead adds to it. [^3]: Since I'm trying out the practice of documenting things, let's also put this here; although now that I think about it, I'm pretty @@ -261,13 +261,13 @@ for another episode. Thus, until next time... for CL, with centralized repositories and all that jazz. I've never used it, incidentally; and it's not that I'm denying its quickness or usefulness, but that process of automatically - fetching dependencies from some site obscures my understanding of - the programs that I'm running and their real mass. Instead, I - prefer going through the laborious job of writing down the entire - dependency tree of the program that I'm trying to run, then - grabbing a copy of each dependency from the author's site\*, - putting them all in a directory and defining the path to that in - my CLtron instance. Here's how this looks for Hunchentoot: + fetching dependencies from some arbitrary site obscures my + understanding of the programs that I'm running and their real + mass. Instead, I prefer going through the laborious job of writing + down the entire dependency tree, then grabbing a copy of each + dependency from the author's site\*, putting them all in a + directory and defining the path to that in my CLtron + instance. Here's how this looks for Hunchentoot: ~~~~ {.commonlisp} (defvar *ext-dep-base* "/home/spyked/lisp-stolen/") @@ -277,7 +277,7 @@ for another episode. Thus, until next time... "trivial-backtrace/" "usocket/")) ~~~~ - then I'll define a variable denoting the path to my + then I'll define a variable holding the path to my work-in-progress Hunchentoot code base: ~~~~ {.commonlisp} @@ -292,8 +292,10 @@ for another episode. Thus, until next time... (pushnew :hunchentoot-no-ssl *features*) ~~~~ - and now I have to instruct ASDF to look for "systems", i.e. Common - Lisp programs in each of the directories in the paths above: + and now I have to instruct [ASDF][asdf] to look for "systems", + i.e. Common Lisp programs, in each of the directories in the paths + above. Apparently we're not quite at the point where we can get + rid of this particular piece, so: ~~~~ {.commonlisp} (loop for path in *ext-deps* do @@ -310,9 +312,9 @@ for another episode. Thus, until next time... 12 ~~~~ - which are *all* the dependencies\*\* needed to run Hunchentoot - given a Linux-and-SBCL installation. At this point we can call - ASDF with Hunchentoot as a parameter: + which are *all* the dependencies needed to run Hunchentoot given a + Linux-and-SBCL installation. At this point we can tell ASDF to + load our Hunchentoot: ~~~~ {.commonlisp} (asdf:load-system :hunchentoot) @@ -329,22 +331,14 @@ for another episode. Thus, until next time... the first footnote: since I'm already using that shit although I haven't actually read the code, why haven't I published it already? The man [makes a good point][btcbase-1924190], I *am* - using it. - \*\*: Now tell me, are these so-called - "[dependencies][dependencies]" part of Hunchentoot, or ar they - separate programs imported by it or what? This seemingly innocent - basement-philosophical question begs for an answer, because the - answer informs my work; and if the answer is "yes, they're part of - Hunchentoot", then I need to include [at the very least] them in - the genesis [but in all honesty, I would need to also include a - SBCL, a Linux and schematics for the computer they're running on], - which means I'd be quite happy to publish a year from now. But - well, one thing at a time. + using it. So how do I address the gray area of "I've been using + this piece of code for a while because my program requires it, but + I don't trust it enough to sign it just yet"? [^4]: My CLOS-fu is somewhat lacking, but this "next most specific - method" refers in principle to the method implementation of the - direct superclass, i.e. in our case the acceptor - implementation. This means that if our call to "/yo" doesn't + method" refers in principle to the method implementation of what + other languages call "the direct superclass", i.e. in our case the + acceptor class. This means that if our call to "/yo" doesn't match, the server will fall back to the default mechanism of serving static files from the document root. @@ -362,6 +356,7 @@ for another episode. Thus, until next time... [svg-use]: http://archive.is/JfGyb [btcbase-1922361]: http://btcbase.org/log/2019-07-12#1922361 [quicklisp]: http://archive.is/Bk8Rm +[asdf]: http://archive.is/oPKRp [btcbase-1924190]: http://btcbase.org/log/2019-07-22#1924190 [dependencies]: /posts/y03/04e-the-myth-of-software-engineering-iii.html#selection-85.0-87.0 [ht-acceptor-dispatch-request]: http://coad.thetarpit.org/hunchentoot/c-acceptor.lisp.html#L628 @@ -369,7 +364,7 @@ for another episode. Thus, until next time... [ht-document-root]: http://coad.thetarpit.org/hunchentoot/c-acceptor.lisp.html#L169 [ht-docs]: http://archive.is/MP2bT [ht-easy-acceptor]: http://coad.thetarpit.org/hunchentoot/c-easy-handlers.lisp.html#L330 -[ht-dispatch-easy-handler]: http://coad.thetarpit.org/hunchentoot/c-easy-handlers.lisp.html#L319 +[ht-dispatch-easy-handlers]: http://coad.thetarpit.org/hunchentoot/c-easy-handlers.lisp.html#L319 [cl-who-ii-fn4]: /posts/y05/095-cl-who-ii.html#fn4 [ht-define-easy-handler]: http://coad.thetarpit.org/hunchentoot/c-easy-handlers.lisp.html#L164 [mp-wp]: http://btcbase.org/log-search?q=mp-wp