[racket] Dynamic Templates?

From: Greg Hendershott (greghendershott at gmail.com)
Date: Thu Jun 6 22:36:33 EDT 2013

Great timing! It's been on my short list to make my static blog
generator more flexible. From
http://docs.racket-lang.org/web-server/templates.html I got the idea
that it would be suitable only for static templates, but now I
understand that's not the case. Today I made a topic branch using this
approach that's working well, which I plan to merge after some testing
and polishing.

p.s. Maybe it's obvious, but because `include-template` uses
`include-at/relative-to/reader`, it won't include a template if you
give it a full path. Maybe there's a more-elegant way, but I found it
worked to parameterize `current-directory` around the call to `eval`.


On Wed, Jun 5, 2013 at 4:45 PM, Jay McCarthy <jay.mccarthy at gmail.com> wrote:
> While it is supposed to be pithy, it is also serious.
>
> When I wrote it, I imagine that people would do something like this:
>
> #lang racket/base
> (require web-server/templates)
>
> (define (template-content t x)
>   (eval #`(let ([x #,x]) (include-template #,t))))
>
> (template-content "t.txt" 5)
> (template-content "t.txt" 6)
>
> and trust that the template wouldn't include @(system "rm -fr /"). I
> think that a simple eval works just fine for when you, the programmer,
> want to change the content dynamic (although I'd say it is better to
> use the web-server language so you can restart with the same
> continuations, etc.)
>
> Your solution is great for a template that a user provides, although
> it has the hole that the template could call @include-template and
> maybe find itself and go into a infinite loop, so it's not totally
> "secure" unless you use a sandbox.
>
> Jay
>
> On Wed, Jun 5, 2013 at 1:53 PM, Joe Gibbs Politz <joe at cs.brown.edu> wrote:
>> I'm writing a web server in a #lang that doesn't support macros or
>> syntactic abstraction.  I would like to be able to use some sort of
>> templating dynamically with bindings given by values, e.g.
>>
>> template.render("page-with-hole-for-username.html", { username: "Joe" })
>>
>> The FAQ (http://docs.racket-lang.org/web-server/faq.html#(part._.How_do_.I_use_templates__dynamically__))
>> in the documentation for templates ends with this pithy
>> recommendation:
>>
>> "If you insist on dynamicism, there is always eval."
>>
>> I assume this isn't intended seriously, and instead to discourage what
>> I'm asking about, but I'm unfortunately not seeing another way to
>> write my program.  The code at the end of this message seems like the
>> best I can do while being relatively safe, but also like a dubious
>> inclusion on a web server given the eval.
>>
>> Is this the best I can hope for?  Is there another collection I should
>> be looking into?  Any other recommendations?
>>
>> Thanks!
>> Joe P.
>>
>>
>> #lang racket/base
>>
>> (require
>>   web-server/templates)
>>
>> (define (render-template filename dict)
>>   (define namespace-for-template (make-empty-namespace))
>>   (namespace-attach-module (current-namespace) 'web-server/templates
>> namespace-for-template)
>>   (hash-map dict
>>     (lambda (key value)
>>       (define name-of-identifier (string->symbol key))
>>       (namespace-set-variable-value!
>>         name-of-identifier
>>         value
>>         #f
>>         namespace-for-template)))
>>   (parameterize [(current-namespace namespace-for-template)]
>>     (namespace-require 'web-server/templates))
>>   (define to-eval #`(include-template #,(datum->syntax
>> #'render-template filename)))
>>   (eval to-eval namespace-for-template))
>> ____________________
>>   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
> ____________________
>   Racket Users list:
>   http://lists.racket-lang.org/users

Posted on the users mailing list.