[racket] passing a list of dispatch clauses to dispatch-rules
There's an annoying terminological problem.
The core Web server has a concept of a dispatcher sequence and
(next-dispatcher) jumps to the next of those. The web-server/dispatch
library helps you write a function that does pattern matching on the
URL of a request. What you want is that after you take a branch in
that function, you'd like to have the branch fail and then the pattern
matching try again.
racket/match [which web-server/dispatch is built on] supports
something like that:
(define (a in)
(match in
[x
(define y (string->number x))
(if y
y
(failure-cont))]
["home"
"It's home!"]
[_
"Unknown"]))
(module+ test
(require rackunit)
(check-equal? (a "4") 4)
(check-equal? (a "home") "It's home!")
(check-equal? (a "five") "Unknown"))
But the use of (failure-cont) has to be syntactically within the
match, i.e. the following does not work:
(define (b-helper x)
(define y (string->number x))
(if y
y
(failure-cont)))
(define (b in)
(match in
[x
(b-helper y)]
["home"
"It's home!"]
[_
"Unknown"]))
If you really need to sequence them this way, then you could use
1. serve/launch/wait
2. sequence dispatcher
3. dispatch/servlet handling files
4. and then dispatch/servlet handling everything else
So that the (next-dispatcher) in step 3 jumped to step 4.
Jay
On Tue, Dec 17, 2013 at 1:23 PM, Janos Tobias Locsei
<jtlocsei at cantab.net> wrote:
> Just realized I can the desired behavior by just putting the (string-arg) as
> the last clause:
>
> (define-values (url-based-dispatch url-generator)
> (dispatch-rules
>
> [("home") display-home]
> [("some-app") run-app]
> [((string-arg)) dispatch-static-html]))
>
> I'm still curious though whether it's possible to skip to the next clause by
> calling next-dispatcher within one dispatch function. The discussion at
> http://lists.racket-lang.org/users/archive/2013-September/059728.html
> made me think this was possible. In that example, I thought that when
> "funny-fish.png" is matched and fail-to-fs throws next-dispatcher that the
> idea was for the program to keep trying with the rest of the clauses in the
> dispatch rules.
>
> Tobias
>
>
> On 17 December 2013 17:25, Janos Tobias Locsei <jtlocsei at cantab.net> wrote:
>>
>> Hi Jay, I tried again using serve/servelet. This is my full code:
>>
>> #lang racket
>>
>> (require web-server/dispatch ; for dispatch-rules
>> web-server/dispatchers/dispatch ; for next-dispatcher
>> web-server/servlet-env ; for serve/servlet
>> web-server/http ; for response/xexpr
>> )
>>
>> (define-values (url-based-dispatch url-generator)
>> (dispatch-rules
>> [((string-arg)) dispatch-static-html]
>> [("home") display-home]
>> [("some-app") run-app]))
>>
>> (define (dispatch-static-html request a-path-string)
>> (display "Entered dispatch-static-html\n")
>> ; This will eventually have code to search for static html
>> ; files and display them. For now, just pretend we couldn't find
>> ; the relevant html file so we throw next-dispatcher.
>> (next-dispatcher))
>>
>> (define (display-home request)
>> (display "Entered display-home\n")
>> (response/xexpr
>> `(html
>> (head (title "Home"))
>> (body (h1 "Home")
>> (p "Welcome to the home page")))))
>>
>> (define (run-app request)
>> (display "Entered run-app\n")
>> (response/xexpr
>> `(html
>> (head (title "App"))
>> (body (h1 "App")
>> (p "This app is actually just a static page")))))
>>
>>
>> (define (respond-unknown request)
>> (display "Entered respond-unknown\n")
>> (response/xexpr
>> `(html
>> (head (title "Unknown Reponse"))
>> (body (h1 "Unknown Response")
>> (p "Sorry, I couldn't find what you're looking for")))))
>>
>> (serve/servlet
>> url-based-dispatch ; answers requests
>> #:servlet-path "/home" ; default url
>> #:servlet-regexp #rx"" ; capture all top-level requests
>> #:file-not-found-responder respond-unknown)
>>
>> What I was expecting (and wanting) was that for the URL
>> "http://localhost:8000/home" the function dispatch-static-html would be
>> called (because it matches any URL), it would throw next-dispatcher, and
>> then display-home would be called, since it's the next matching clause.
>>
>> But in reality when dispatch-static-html throws next-dispatcher the
>> program jumps straight to respond-unknown, which I specified as the
>> file-not-found-responder keyword argument when I called serve/servlet.
>>
>> What am I missing? Is there a way to get the program to do what I wanted
>> it to?
>>
>> Thanks for all your time with this.
>>
>> Tobias
>>
>>
>>
>>
>> -------------------------------
>>
>>
>> Thanks Jay, that makes sense. I was testing it without using
>> serve/servlet, using the example on
>> http://docs.racket-lang.org/web-server/dispatch.html
>>
>> I will try again using serve/servlet.
>>
>>
>> On 17 December 2013 14:45, Jay McCarthy <jay.mccarthy at gmail.com> wrote:
>>>
>>> The first one is what I would write, except that I'd put it after the
>>> ["" ...] case so it doesn't shadow it.
>>>
>>> How are you testing this code? (next-dispatcher) is supposed to throw
>>> an exception, but it will caught and used by the Web server when you
>>> are using serve/servlet, etc.
>>>
>>> Jay
>>>
>>> On Tue, Dec 17, 2013 at 7:11 AM, Janos Tobias Locsei
>>> <jtlocsei at cantab.net> wrote:
>>> > I thought I'd add a note about what my overall objective with this is,
>>> > in
>>> > case there's a completely different way of achieving the same thing.
>>> >
>>> > Basically what I want is to be able to serve a combination of apps and
>>> > static html pages on my domain, but I don't want ".html" as the end of
>>> > the
>>> > url for the static pages. So, if someone goes to the url
>>> >
>>> > http://mysite.com/lolcats
>>> >
>>> > ...then I'd like the web server will look in the directory
>>> > /htdocs/static-html/ and check whether there's a file called
>>> > lolcats.html,
>>> > and serve that page if it's there.
>>> >
>>> > My idea was that to achieve this I'd write a dispatch function that
>>> > would
>>> > check the static-html directory for a file with the correct name, and
>>> > serve
>>> > that page using the "include-template" function in
>>> > web-server/templates.
>>> >
>>> > But if there's an easier/better way of achieving the same thing then
>>> > I'm
>>> > open to that.
>>> >
>>> > Tobias
>>> >
>>> >
>>> >
>>>
>>>
>>>
>>> --
>>> Jay McCarthy <jay at cs.byu.edu>
>>> Assistant Professor / Brigham Young University
>>> http://faculty.cs.byu.edu/~jay
>>>
>>> "The glory of God is Intelligence" - D&C 93
>>
>>
>
--
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://faculty.cs.byu.edu/~jay
"The glory of God is Intelligence" - D&C 93