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

From: J G Cho (gcho at fundingmatters.com)
Date: Sat Jun 25 22:42:37 EDT 2011

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.'

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
         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
>



Posted on the users mailing list.