Skip to content

Commit

Permalink
Tweak and hyperlink example/w-template-files
Browse files Browse the repository at this point in the history
Part of #68.
See #55 (comment).
  • Loading branch information
aantron committed Jul 2, 2021
1 parent 65e104d commit 795f824
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 84 deletions.
6 changes: 4 additions & 2 deletions example/7-template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
Dream [*templates*](https://aantron.github.io/dream/#templates) allow
interleaving OCaml and HTML in a straightforward way, and help with
[XSS protection](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).
After looking at the correct example, we will
[weaken and then exploit it](#security).
After looking at a secure example, we will [weaken and then exploit
it](#security).

```ocaml
let render param =
Expand Down Expand Up @@ -141,6 +141,8 @@ and not supported by Dream.

**See also:**

- [**`w-template-files`**](../w-template-files) moves the template into a
separate `.eml.html` to avoid problems with editor support.
- [**`w-tyxml`**](../w-tyxml#files) shows how to use
[TyXML](https://github.com/ocsigen/tyxml), a different templater that uses
OCaml's type system to prevent emitting many kinds of invalid HTML.
Expand Down
2 changes: 2 additions & 0 deletions example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ if something is missing!

<br>

- [**`w-template-files`**](w-template-files#files) &nbsp;&mdash;&nbsp;
templates in separate `.html` files for better editor support.
- [**`w-graphql-subscription`**](w-graphql-subscription#files)
&nbsp;&mdash;&nbsp; GraphQL subscriptions.
- [**`w-chat`**](w-chat#files) &nbsp;&mdash;&nbsp; a chat room based on
Expand Down
106 changes: 24 additions & 82 deletions example/w-template-files/README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
# `w-template-files`

Dream [*templates*](https://aantron.github.io/dream/#templates) allow
interleaving OCaml and HTML in a straightforward way, and help with
[XSS protection](https://cheatsheetseries.owasp.org/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.html).
<br>

While templates can be written with other code in `.ml` files, they
can also live in their own source files. This can be useful as
templates become larger, or when you have many templates.
While templates can be written with other code in `.ml` files, they can also
live in their own source files. This can be useful as templates become larger,
or when you have many templates.

If your template file is mostly HTML, you can give it a name like
`template.eml.html`, to trigger HTML syntax highlighting by your
editor. Additionally, if you are using `ocamlformat`, the `.html`
extension will prevent errors that come from `ocamlformat` attempting
to format the HTML in the template. (See [this
issue](https://github.com/aantron/dream/issues/55) for more
information.)

## Files
`template.eml.html`, to trigger HTML syntax highlighting by your editor.
Additionally, if you are using `ocamlformat`, the `.html` extension will
prevent errors that come from `ocamlformat` attempting to format the syntax of
the template.

### `template.eml.html`
This example does just that. It splits the code of the basic template example,
[**7-template**](../7-template#files), into two files. The first is the
template, in
[`template.eml.html`](https://github.com/aantron/dream/blob/master/example/w-template-files/template.eml.html):

```ocaml
```html
let render param =
<html>
<body>
Expand All @@ -29,18 +26,10 @@ let render param =
</html>
```

You will be able to access this function as `Template.render` in the
`server.ml` file.

The substitution, `<%s param %>`, uses [`Printf` conversion
specifications](https://caml.inria.fr/pub/docs/manual-ocaml/libref/Printf.html)
from the standard library. So, you can do things like this:

- `<%i my_int %>` to print an OCaml `int`.
- `<%02x my_hex_int %>` to print an `int` in hexadecimal, with at
least two characters, left-padded with zeroes.

### `server.ml`
After preprocessing by the templater, this file becomes `template.ml`, so it
defines a module `Template`, containing a function `Template.render`. We call
this function from the main server in
[`server.ml`](https://github.com/aantron/dream/blob/master/example/w-template-files/server.ml):

```ocaml
let () =
Expand All @@ -51,73 +40,26 @@ let () =
Dream.get "/:word"
(fun request ->
Dream.param "word" request
(* This is the `render` function we defined in
`template.eml.html`. *)
|> Template.render
|> Dream.html);
]
@@ Dream.not_found
```

### dune

This requires a bit more setup in our
[`dune`](https://github.com/aantron/dream/blob/master/example/w-template-files/dune)
file to run the template preprocessor. Note that the `render`
function defined in `template.eml.html` will be available to the
server code as `Template.render` as we set the `targets template.ml`
in the `rule` stanza in the dune file.

```
(executable
(name server)
(libraries dream))
(rule
(targets template.ml)
(deps template.eml.html)
(action (run dream_eml %{deps} --workspace %{workspace_root})))
(data_only_dirs _esy esy.lock)
```

## Run it

<pre><code><b>$ cd example/w-template-files</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>

Now, you should be able to browse to
[http://localhost:8080/dream](http://localhost:8080/dream) and see the
response. Try changing `dream` to something else and watch how the
response changes!

## Security

See section *Security* in the counterpart OCaml example
[**`7-template`**](../7-template#security) for a discussion of how the
templater prevents script injection (XSS) attacks, and its
limitations. That section even disables some of the protection, and
launches an XSS attack against the template! It works equally well
with this example &mdash; the templates are the same.
<br>

## See also
**See also:**

- [**`w-tyxml`**](../w-tyxml#files) shows how to use
[TyXML](https://github.com/ocsigen/tyxml), a different templater
that uses OCaml's type system to prevent emitting many kinds of
invalid HTML.
- [**`r-tyxml`**](../r-tyxml#files) if you are using Reason. You can
use TyXML with JSX syntax server-side!
- [**`w-template-stream`**](../w-template-stream#files) streams
templates to responses, instead of building up complete response
strings.
- [**`r-template`**](../r-template#files) is a Reason syntax version
of this example.
- [**`r-template-stream`**](../r-template-stream#files) streams a
template to a response.
- [**7-template**](../7-template#files) for comments on the
[`dune` file](https://github.com/aantron/dream/blob/master/example/w-template-files/dune)
and [security
information](https://github.com/aantron/dream/tree/master/example/7-template#security).

<br>

[Up to the tutorial index](../#readme)
[Up to the example index](../#examples)

0 comments on commit 795f824

Please sign in to comment.