[racket] Lazy Request Handler

From: Nathan Breit (nabreit at gmail.com)
Date: Wed Mar 21 21:46:16 EDT 2012

Awesome! That helped a lot. Thanks!

On Wed, Mar 21, 2012 at 6:28 PM, Jay McCarthy <jay.mccarthy at gmail.com>wrote:

> Since you did not tell us what error you had, I assume the error was:
>
> serve/servlet: contract violation, expected: can-be-response?, given:
> #<promise>
>
> When I tried your code, I also had the error:
>
> current-directory: `exists' access denied for /home/jay/Downloads/
>
> because you need to give the sandbox permission to read, like:
>
> #:allow-read (list "/")
>
> But I assume that you know that error doesn't have to do with the Web
> server.
>
> Returning to the serve/servlet error...
>
> If you change your 'start' to:
>
> (define (start request)
>  (define prm ((lazy-eval 'lazy-handler) request))
>  (printf "~a ~a\n" prm (promise? prm))
>  (define ans (force prm))
>  (printf "~a\n" ans (promise-forced? prm))
>  ans)
>
> You will see the output:
>
> #<promise> #f
> Servlet (@ /main) exception:
> promise-forced?: expected argument of type <promise>; given: #<promise>
>
> This indicates the thing returned by your handler is not a promise and
> therefore cannot be forced.
>
> This is called structure generativity: every instantiation of a module
> has different structures, and sandboxes lead to multiple
> instantiations of the same module---racket/promise in this case. Thus,
> different 'promise' data structures.
>
> Fixing this is what 'sandbox-namespace-specs' is for.
>
> If you wrap your call to 'make-evaluator' in:
>
>  (parameterize ([sandbox-namespace-specs
>                  (list sandbox-make-namespace
>                        'racket/promise
>                        'web-server/http)])
>  .....)
>
> Then it will work. This shares the modules 'racket/promise' (to get
> the right promise data structure) and 'web-server/http' (to get the
> right request and response structures) between the evaluator and the
> host Racket program.
>
> In case you don't realize, using an evaluator is totally unnecessary.
> You can just write another module in the lazy language and require it
> in the strict program and call force normally. For example:
>
> #lang racket/load
>
> (module lazy-handler lazy
>  (require web-server/http/bindings
>           web-server/http/response-structs
>           web-server/http/xexpr)
>   (define (lazy-handler request)
>    (let ((bindings (request-bindings request)))
>      (if (exists-binding? 'hi bindings)
>        (response/xexpr "Hi!")
>         (response/xexpr ""))))
>  (provide lazy-handler))
>
> (module the-server racket
>  (require web-server/servlet-env
>           web-server/http/bindings
>           web-server/http/response-structs
>           web-server/http/xexpr
>           'lazy-handler)
>
>  (define (start request)
>    (define prm (lazy-handler request))
>    (printf "~a ~a\n" prm (promise? prm))
>    (define ans (force prm))
>    (printf "~a ~a\n" ans (promise-forced? prm))
>    ans)
>
>  (serve/servlet start
>                 #:launch-browser? #t
>                  #:quit? #f
>                 #:listen-ip #f
>                  #:servlet-path "/main"
>                  #:port 8080
>                 #:servlet-regexp #rx"main.*"
>                 #:extra-files-paths
>                  (list (build-path (current-directory)))))
>
> (require 'the-server)
>
> Hope this helps,
>
> Jay
>
>
>
> On Wed, Mar 21, 2012 at 11:44 AM, Nathan Breit <nabreit at gmail.com> wrote:
> > I'm trying to write a servlet that plugs into the existing server.
> Here's an
> > example:
> >
> > #lang racket
> > (require web-server/servlet-env)
> > (require web-server/http/bindings)
> > (require web-server/http/response-structs)
> > (require web-server/http/xexpr)
> >
> > (require racket/sandbox)
> > (define lazy-eval (make-evaluator 'lazy))
> >
> > (map lazy-eval
> >      '(
> >        (require web-server/http/bindings)
> >        (require web-server/http/response-structs)
> >        (require web-server/http/xexpr)
> >        (require racket/promise)
> >        (define (lazy-handler request)
> >          (let ((bindings (request-bindings request)))
> >            (if (exists-binding? 'hi bindings)
> >                (response/xexpr "Hi!")
> >                "")))
> >        ))
> >
> > (define (start request)
> >   (force ((lazy-eval 'lazy-handler)
> >           request)))
> >
> > (serve/servlet start
> >                #:launch-browser? #f
> >                #:quit? #f
> >                #:listen-ip #f
> >                #:servlet-path ""
> >                #:port 8080
> >                #:servlet-regexp #rx"main.*"
> >                #:extra-files-paths
> >                (list (build-path (current-directory) "extraFiles")))
> >
> > On Wed, Mar 21, 2012 at 6:22 AM, Matthias Felleisen <
> matthias at ccs.neu.edu>
> > wrote:
> >>
> >>
> >>
> >> On Mar 21, 2012, at 5:18 AM, Nathan Breit wrote:
> >>
> >> > Hi,
> >> > I'm trying to implement a Racket web-server handler that does lazy
> >> > evaluation. My approach so far as been to try making a
> evaluator/namespace
> >> > that uses the lazy racket, then evaluate a function in it that
> returns a
> >> > lazy request handler. However, I'm running into problems getting the
> handler
> >> > to read the request object. My last resort will be to make a request
> >> > serializer and pass serialized requests into the handler, but is
> there a
> >> > better way?
> >> > Thanks,
> >> > -Nathan
> >> > ____________________
> >> >  Racket Users list:
> >> >  http://lists.racket-lang.org/users
> >>
> >>
> >>
> >> Are you trying to write a web server in Lazy or are you trying to write
> a
> >> servlet in Lazy and plug it into the existing strict server? Perhaps you
> >> want to post a code snippet that shows where things fail. -- Matthias
> >>
> >
> >
> > ____________________
> >  Racket Users list:
> >  http://lists.racket-lang.org/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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20120321/aa6d79e4/attachment-0001.html>

Posted on the users mailing list.