Re: A hypermodern web server Amirouche Boubekki 18 Sep 2020 15:37 UTC

Le ven. 18 sept. 2020 à 02:07, John Cowan <xxxxxx@ccil.org> a écrit :
>
> This is a proposed interface to a really trivial, but useful, web server.  The only requests it can handle are loading files and invoking procedures that expect/return a JSON object.  This is about all that a single-page browser application actually needs.
>
> (server-apply! proc prefix)
>
> Tells the server that if the original path begins with prefix, proc will be involved with the following arguments:  the HTTP verb (as a symbol, downcased), the rest of the path, the parameters as a dictionary, the body decoded from JSON into the corresponding Scheme object per SRFI 180.  Two values are returned, the HTTP status code and a Scheme object that can be encoded as JSON.
>
> (server-rewrite-path! regex replacement)
>
> Tells the server to match each URL path against regex, and if it matches, replace the path with replacement.  If replacement contains "$n" as a substring, the nth parenthesized submatch is used to replace it.
>
> (server-media-type! suffix mime-type)
>
> Tells the server to translate a file name ending in ".prefix" into the corresponding media type.  A few such suffixes like .js, .html, .jpeg, .gif, ... are built in.
>
> (start-server portnum webroot <other args>)
>
> Starts the server listening on portnum.  When a request is received, match all the path prefixes in longest-to-shortest order and if there is a match, invoke the procedure. If the status code is 0, close the connection and return from start-server; otherwise format and send the status code and object.
>
> If there is no suitable path prefix, rewrite the path, look under webroot for a corresponding file, and return it.  Issues: In what order do we try the rewrites?  If one matches, do we stop, try to match the rest against the result, or use the result and try again from the top?  Then return the file contents or an appropriate status such as 403 or 404.
>
> Comments?
>

Yes, usually what I do is hook everything API under /api and map the
path components to procedures something along the lines of:

(server-apply! (lambda (path json cookies) (match path ((api user
login) (login! json cookies) ...)))

It relies on something like chibi-match which is simpler than a regex
and covers most needs.

Hence serving static files is something along the lines of the following:

(server-apply! (lambda (path _1 _2) (match path (... (static . path)
(serve-static-at path)))))

So it seems to me we can get with one procedure and one helper to
serve static files:

  (server-start portnum proc)

Where proc takes three arguments:

- path, a list of strings (unlike the above code I have written) making the path
  that is the result of (string-split (request-path request) #\/))

- a json that is read from the body, if any.

- cookies.

The second helper procedure would be: (serve-static-file AT-FILEPATH)