[racket] Help needed in writing Macro to transform (lambda (req) ....) to be used in web-server/servlet using auth cookies

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Sun Jun 26 00:29:17 EDT 2011

2011/6/25 J G Cho <gcho at fundingmatters.com>:
> That was completely self-inflicted typo, which makes learning new
> stuff that much more difficult. Thanks for catching it.
>
> Got past that error and then ran into a few more. So it now reads:
>
> #lang racket
>
> (require web-server/web-server
>         web-server/dispatchers/filesystem-map)
> (require (prefix-in files: web-server/dispatchers/dispatch-files))
>
> (define (start-file-server base)
>   (serve
>      #:dispatch
>      (files:make
>         #:url->path (make-url->path base)
>         #:path->mime-type (lambda (path) #"application/octet-stream")
>         #:indices (list "index.html"))
>      #:port 8080))
>
> (start-file-server (current-directory))
>
> Now I am getting
>
> #<procedure:...-server-unit.rkt:46:2>
>
> (from both DrRacket and command-line) instead of a running file server.

It did start a file server. Did you try to go to the contact it with
your browser?

>
> Just for the hell of it, I changed (start-file-server (current-directory)) to
> start-file-server
>  and ran the code and got
> #<procedure:start-file-server>
> as I expected. Not that this helps me at all.
>
> ((start-file-server (current-directory))) just returns.

What did you think it would do?

The documentation above that example says:

"Constructs an appropriate dispatch-server-config^, invokes the
dispatch-server@, and calls its serve function."

And serve (found from clicking on the dispatch-server@ link) says:

"Runs the server—the confirmation channel will be send an exception if
one occurs starting the server or the port number if there is none—and
returns a procedure that shuts down the server."

The procedure that you get back will shut it down. So, when you ran
the result, you were turning OFF the server.

In the case of your command-line version, since there is nothing left
in the program to do, racket exits and the server shuts off. In
DrRacket, however, it keeps running because you can still do things in
the REPL.

If you keep reading the page that that example is on you'll see two
useful things:

"(do-not-return) → void

This function does not return. If you are writing a script to load the
Web Server you are likely to want to call this functions at the end of
your script."

And

"serve/launch/wait"

which is what is underneath serve/servlet to open up a browser and
leave the server running until you quit.

I recommend using serve/launch/wait.

Jay


>
> Is there something else I can/should try?
>
> On Sat, Jun 25, 2011 at 10:56 PM, Jay McCarthy <jay.mccarthy at gmail.com> wrote:
>> 2011/6/25 J G Cho <gcho at fundingmatters.com>:
>>> Yikes. I did read those documents before sometime ago when I started
>>> to learn about Racket. Without much comprehension! I really hoped to
>>> stay with WebApps part and stay oblivious to the internals of the
>>> Server. No such luck if I really want to take advantage of all the
>>> neat things it can do.
>>>
>>> Per your reply with links, I read them again trying to make sense of
>>> your sequencing dispatchers code. I think I can sorta get a feel for
>>> sequence:make and lift:make etc but ...
>>>
>>> Right now, I feel very comfortable 'hugging the shore' writing my
>>> little servlets. Stringing together my own custom dispatchers feel
>>> like taking a new sail boat out to uncharted big ocean.
>>>
>>> You see, I am still banging my head making my way around the documents
>>> on Racket HTTP Server, which is not the easiest to digest.
>>>
>>> First, the first sentence I read is  "Web Server is just a
>>> configuration of a dispatching server." My reaction is, 'Huh? I've
>>> never heard such statement over the years doing web apps starting with
>>> Perl CGI, PHP, JSP, RoR, GAE to mention a few. The statement might be
>>> true but it's not helping me find my way around. Sounds more like zen
>>> koan or something experts utter that completely makes no sense to a
>>> beginner.'
>>
>> That section then explains what a dispatching server is.
>>
>>>
>>> Second, I am trying out the file server example (from 3. Launching Servers).
>>>
>>> I made a file file-server.rkt by copying the code:
>>>
>>> #lang racket
>>>
>>> (require web-server/webserver
>>
>> You meant (require web-server/web-server) as it says at the top of
>> that page. It's very easy to make typos on this sort of thing. :(
>>
>> Jay
>>
>>>         web-server/dispatchers/filesystem-map)
>>>
>>> (define (start-file-server base)
>>>   (serve
>>>      #:dispatch
>>>      (files:make
>>>         #:url->path (make->url->path base)
>>>         #:path->mime-type (lambda (path) #"application/octet-stream"))
>>>         #:indices (list "index.html")
>>>      #:port 8080))
>>>
>>> (start-file-server  (current-directory))
>>>
>>>
>>> I am invoking it with
>>>
>>> path to /Racket5.1/bin/racket -t file-server.rkt
>>>
>>> (the way I start my servlets from command line when not using DrRacket).
>>>
>>> I am greeted with:
>>>
>>> default-load-handler: cannot open input file: "path
>>> to/Racket5.1/collects/web-server/webserver.rkt" (No such file or
>>> directory; errno=2)
>>>
>>> Either the example is wrong or the author has left out a small detail
>>> obvious to him but not so to this beginner.
>>>
>>> It's going to take a bit of blood/sweat/tears/scars...
>>>
>>> But on the other hand, the design seems very promising/exciting if I
>>> can get past the initial learning pains. Taking the auth checking code
>>> out of the procedures is such a huge gain!
>>>
>>> Thank you.
>>>
>>>
>>> On Sat, Jun 25, 2011 at 1:10 PM, Jay McCarthy <jay.mccarthy at gmail.com> wrote:
>>>> The Web server is set up as a pipeline of "dispatchers", which are
>>>> functions that accept the TCP connection and the HTTP request and
>>>> either write a response or refuse to handle the request. This chapter
>>>> of the documentation:
>>>>
>>>> http://docs.racket-lang.org/web-server-internal/dispatchers.html
>>>>
>>>> discusses all the dispatchers that make up the standard server. They
>>>> can be combined very easily to customize the server to do exactly what
>>>> you want.
>>>>
>>>> Launching a server with your custom dispatcher is as easy as using
>>>> serve/servlet or web-server/insta:
>>>>
>>>> http://docs.racket-lang.org/web-server-internal/web-server.html
>>>>
>>>> Jay
>>>>
>>>> 2011/6/25 J G Cho <gcho at fundingmatters.com>:
>>>>> Seems like an elegant approach but....  "dispatcher outside the
>>>>> servlet" goes over my head like an UFO over a crop duster.
>>>>>
>>>>> I guess I will have to dig deeper into how the server is put together.
>>>>>
>>>>> On Sat, Jun 25, 2011 at 1:23 AM, Jay McCarthy <jay.mccarthy at gmail.com> wrote:
>>>>>> I find it more convenient to setup a dispatcher outside the servlet
>>>>>> that checks for the authenticator, that way once it has passed that
>>>>>> part of the dispatch chain, security can be relied upon. Something
>>>>>> like...
>>>>>>
>>>>>> (serve/launch/wait
>>>>>>  (sequence:make
>>>>>>  (lift:make (lambda (req) (if (or (unsecured-url? req)
>>>>>> (authenticated? req)) (next-dispatcher) (display-error/login-page))))
>>>>>>  (dispatch/servlet ...)))
>>>>>>
>>>>>> Then the servlet code can basically ignore the authenticator.
>>>>>>
>>>>>> Jay
>>>>>>
>>>>>> 2011/6/24 J G Cho <gcho at fundingmatters.com>:
>>>>>>> Hello again,
>>>>>>>
>>>>>>> I am guessing my problem calls for macro (which is "beyond my pay
>>>>>>> scale") and I am hoping this is the right place.
>>>>>>>
>>>>>>> Anyway, after reading this
>>>>>>> http://docs.racket-lang.org/web-server/faq.html#(part._.What_special_considerations_are_there_for_security_with_the_.Web_.Server_)
>>>>>>>
>>>>>>> I am led to believe that I will be writing lots of code like this:
>>>>>>>
>>>>>>> (define (some-sensitive-content req)
>>>>>>>
>>>>>>>   (if (user-is-legit req) ;check auth cookie
>>>>>>>      (...what have you ...)
>>>>>>>      (do-login-and-then-maybe-handle req)))
>>>>>>>
>>>>>>> So here is my first attemp at macro which sorta works:
>>>>>>>
>>>>>>> (define-syntax (guarded-handler stx)
>>>>>>>  (syntax-case stx ()
>>>>>>>    [(_ name body)
>>>>>>>     #'(begin (define (name req)
>>>>>>>                (if (user-is-legit req)
>>>>>>>                    body
>>>>>>>                    (ask-login req))))]))
>>>>>>>
>>>>>>> (guarded-handler gated-content
>>>>>>>                 (response/xexpr
>>>>>>>                  `(html (head (title "Gated Content"))
>>>>>>>                         (body (p "Shhhhhhh")
>>>>>>>                               (p
>>>>>>>                                (a ([href "/logout "])
>>>>>>>                                   "Done"))))))
>>>>>>>
>>>>>>> What I would really like, however, is
>>>>>>>
>>>>>>> (guard (lambda (req) ...)) to transformed to:
>>>>>>>
>>>>>>> (lambda (req)
>>>>>>>   (if (user-is-legit req)
>>>>>>>      (...what have you ...)
>>>>>>>      (do-login-and-then-maybe-handle  req)))
>>>>>>>
>>>>>>> such that I can use it like:
>>>>>>>
>>>>>>> (define (count-dot-com i)
>>>>>>>  (count-dot-com
>>>>>>>  (send/suspend/dispatch
>>>>>>>   (λ (embed/url)
>>>>>>>     (response/xexpr
>>>>>>>      `(html
>>>>>>>        (head (title "Count!"))
>>>>>>>        (body (h2 (a ([href ,(embed/url
>>>>>>>                              (guard (λ (req)
>>>>>>>                                (sub1 i))))])
>>>>>>>                     "-"))
>>>>>>> ...
>>>>>>>
>>>>>>> (define (count-dot-com i)
>>>>>>>  (send/suspend/dispatch
>>>>>>>   (λ (embed/url)
>>>>>>>     (response/xexpr
>>>>>>>      `(html
>>>>>>>        (head (title "Count!"))
>>>>>>>        (body (h2 (a ([href ,(embed/url
>>>>>>>
>>>>>>>                              (guard (λ (req)
>>>>>>>                                (count-dot-com (sub1 i))))])
>>>>>>>                     "-")
>>>>>>> ...
>>>>>>>
>>>>>>> in addition to the first case like this:
>>>>>>>
>>>>>>> (define gated-content
>>>>>>>  (guard (lambda (req) ...))
>>>>>>>
>>>>>>> Seems simple enough but my naive macros (not shown here to protect my
>>>>>>> fragile ego) are failing.
>>>>>>> Any help/suggestion is greatly appreciated.
>>>>>>>
>>>>>>> jGc
>>>>>>>
>>>>>>> _________________________________________________
>>>>>>>  For list-related administrative tasks:
>>>>>>>  http://lists.racket-lang.org/listinfo/users
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> 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
>>>>
>>>
>>
>>
>>
>> --
>> 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



Posted on the users mailing list.