I am writing a little blog using the Racket webserver (requiring web-server/templates, web-server/servlet-env, web-server/servlet, web-server/dispatch
). Whenever I want to render a template, I do something this:
(define (render-homeworks-overview-page)
(let
([dates
(sort
(get-all-homework-dates)
#:key my-date->string
string<?)])
(include-template "templates/homework-overview.html")))
Defining a little procedure, to provide the template with all the necessary values, in this case dates
, which is then used inside the template. This works well so far, but I thought maybe I could get rid of the let
in all those render procedures, by putting it once into a more abstract render-template
procedure, which is then called by all the render procedures. Alternatively, the calls to this more abstract procedure could become so simple, that I don't need all the little render procedures anymore. I want to supply the values as keyword arguments and so far I got the following code:
(define render-template
(make-keyword-procedure
(lambda
(keywords keyword-args [content "<p>no content!</p>"] [template-path "template/base.html"])
(let
([content content])
(include-template template-path)))))
This would have a default value for the content displayed in the template and a default path for the template to render and take arbitrary keyword arguments, so that any render procedure could supply whatever is needed by a template by giving it as a keyword.
However, I cannot run this code, because there is an error:
include-at/relative-to/reader: not a pathname string, `file' form, or `lib' form for file
The template-path
in the call (include-template template-path)
is underlined red, to indicate that the error is there. However when I replace the template-path
with an ordinary string like so:
(define render-template
(make-keyword-procedure
(lambda
(keywords keyword-args [content "<p>no content!</p>"] [template-path "template/base.html"])
(let
([content content])
(include-template "templates/base.html")))))
The error does not occur. It seems that Racket somehow wants to ensure, that there is a valid path given to include-template
. But I want that to be a value given to the procedure. Otherwise I cannot write a procedure doing this job.
Also I want the values of the keywords provided to the procedure to be visible to the template. I am not sure, if that is automatically the case, or if I need to put a let
of some kind around the include-template
call, because I could not get the code to run yet, to test this.
How can I write such procedure?
As an example of an ideal procedure I'd like to have:
- Jinja2's
render_template
I can supply any keyword argument I wish and render any template I wish to render. I also do not really understand, why including something like "rm -rf /"
could damage anything. To me it seems the webserver should simply check if a file exists with that name. Obviously it will not exist, so throw an error. How should this ever lead to any unwanted damage? In consequence I do not understand the reasoning behind limiting what can be used as a path to a template to strings (except for workarounds). However, this might be too much for one SO question and should maybe put into another question about the "why" of things.