Excited about Dream web framework

I’m excited about the Dream web framework by @antron. Have I missed a discussion about it here? It shares similarities with @rgrinberg’s Opium. Any early adopters that could share their experience or compare the two?

37 Likes

This looks amazing, nice job @antron!

3 Likes

Nope :slight_smile: I made the repo public only yesterday. I haven’t released or deliberately announced the project yet, but I do hope to release an “alpha1” in a few days to a week. I need to finish at least the tutorial examples, and fix a couple of bugs that are just too annoying to leave unfixed, even for an alpha.

I’d be happy to answer any questions now, or later in the “official” (heh) announcement thread, or even later :slight_smile:

13 Likes

I’d be happy to answer any questions now, or later in the “official” (heh) announcement thread, or even later :slight_smile:

I noticed the templating system, which is implemented as a preprocessor that demuxes OCaml and static content. Evaluates the HTML (with holes filled by OCaml expressions) to an OCaml string? Was the OCaml {| .. |} syntax not flexible enough?

You are right about what it does.

I used {| ... |} syntax in a private project for several weeks before starting Dream, and found it too awkward in practice. It seems to require manual usage of ^, String.concat, or Buffer, and fully written-out conversions.

I had used ECaml in 2014 and enjoyed it (no relation to package ecaml in opam AFAICT). I eventually found Embedded OCaml Templates and switched to that during the 2021 private project. It seems much easier to write templates this way, so I made something similar for Dream (with what I see as improvements).

7 Likes

…and I forgot to mention the most important, {| ... |} provides no default protection against injection attacks, creating a lot of programmer fatigue as one manually escapes everything, which at least seems to translate into a major security risk.

Almost any template system improves on this by doing at least HTML content and attribute escaping by default.

3 Likes

Dream’s template tutorial even launches an XSS attack against the template :slight_smile: But you have to opt in to being vulnerable, as the tutorial suggests to do.

4 Likes

Looking at ECaml is was surprised to see the use of List.iter:

<html>
<head></head>
<body>
<p><%= if Sys.os_type = "Unix" then "Hello world!" else "gtfo" %></p>
<ul>
% List.iter (fun s ->
<li><%= s %></li>
% ) ["hello"; "from"; "list"];
</ul>
</body>
</html>

This raises the question of semantics as this does not represent a string value. Maybe the problem does not exist in Embedded OCaml Templates and your templating language.

I suspect that {| .. |} is also missing a good syntax to build large strings that include computed values. One is forced to manually concatenate strings or use {|..|} as an argument to Printf.*printf and % escapes - which is inconvenient because all arguments are provided at the end. Maybe your experience can inform a more flexible future direction.

1 Like

In ECaml, each literal text part of the template gets passed to print_string by default. ECaml also allows configuring that. In typical usage, I would replace print_string by Buffer.add_string my_buffer for some buffer I allocated before the template, as suggested by the ECaml docs. I didn’t try anything more complicated, but I think you should be able to stream templates with ECaml.

Because of side-effecting interpretation, you can intermix control-flow fragments with literal text.

Dream templates are similar. They have two modes. By default, they allocate a buffer and call add_string for each piece of text. It’s also possible to stream templates instead, as a built-in option. In the streaming example, you can see interleaved text literals, control flow constructs, and calls to flush.

The example sends one <p> element per second (pretty useless!). I haven’t written the English part of it yet.

1 Like

I am curious where people are using server side html currently? I assume only json and graphql would be heavily used.

You mean in general? Server-side HTML is probably the majority of websites. JSON/GraphQL APIs are flashy but I doubt they’ve taken over as the most used method.

1 Like

Embedded OCaml Templates have the same semantics. I do not use print_string, but the tag that outputs a string has to be of type unit because it is desirable to be able to use any control structure on it.

2 Likes

This is something missing from Embedded Ocaml Templates I am afraid.
I am not at all an expert on web technology, I worked on exactly one website that used EJS before I decided it would be a good idea to have the same thing for Ocaml. Do you have a link to a library or even just documentation on how to implement such security features ?

The OWASP XSS Prevention Cheat Sheet gives a good summary of what kinds of escaping needs to be done in various contexts. Escaping rule 1 and the quoted attribute parts of rule 2 are pretty easy to implement together, as they entail (AFAIK) replacing five characters by entities:

match c with
| '&' -> "&amp;"
| '<' -> "&lt;"
| '>' -> "&gt;"
| '"' -> "&quot;"
| '\'' -> "&#x27;"

and these also cover the vast majority of use cases. This should be enabled by default.

By comparison, AFAIK, it is enabled in ECaml, specified for serialization in the HTML spec (roughly; the spec always emits attribute values with double quotes, so it doesn’t bother to escape apostrophes), is undoubtedly in done in many projects in the OCaml ecosystem, and, of course, Dream does it.

3 Likes

I just want to state for the sake of other readers, that Dream does support GraphQL, by integrating @andreas’s ocaml-graphql-server and GraphiQL.

For JSON, Dream currently offers basic CSRF protection for simple/common use cases, and recommends Yojson. I’ll probably look at JSON carefully again after the first alpha release, because I think JSON handling is too difficult in OCaml at the moment.

5 Likes

how strange - I would have expected the 5 pre-defined xml entities here - Extensible Markup Language (XML) 1.0 (Fifth Edition) - but &apos: is different. How that?

Edit: Got it! hex!

1 Like

I used the hex entity because of this in the OWASP recommendations:

&apos; not recommended because its not in the HTML spec (See: section 24.4.1) &apos; is in the XML and XHTML specs.

This probably refers to the HTML4 spec, because it is in the HTML5 spec, and has always been, in the years I’ve worked with it. Nevertheless, I decided to be paranoid and prefer the hex entity.

2 Likes

I’ve tested it yesterday, and it is awesome. Can’t wait to see it available on opam to use it on a new project

4 Likes

Do we have a comparison table between Ocsigen, Opium and this new one?
And where could we create one?

I can’t think of a good home for this content. Maybe host on ocamlverse, and have each framework link to it from their readme.