Compare commits

..

No commits in common. "master" and "1.0.0-alpha7" have entirely different histories.

141 changed files with 816 additions and 1073 deletions

View File

@ -7,98 +7,101 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
os: os:
# Until https://github.com/ocaml/setup-ocaml/issues/872. - ubuntu-latest
# When fixing, search for other instances of this string in this file.
- ubuntu-22.04
ocaml: ocaml:
- 5.2.x - 5.0.x
- 4.14.x - 4.14.x
- 4.13.x
- 4.12.x
- 4.11.x
- 4.10.x
- 4.09.x
- 4.08.x
include: include:
- os: macos-latest - os: macos-latest
ocaml: 4.14.x ocaml: 4.12.x
- os: windows-latest - os: windows-latest
ocaml: 4.14.x ocaml: 4.14.x
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
with: with:
submodules: recursive submodules: recursive
- uses: ocaml/setup-ocaml@v3 - uses: avsm/setup-ocaml@v2
if: runner.os != 'Windows'
with: with:
ocaml-compiler: ${{matrix.ocaml}} ocaml-compiler: ${{matrix.ocaml}}
dune-cache: true
# For Caqti PostgreSQL examples. opam does actually install PostgreSQL for - uses: avsm/setup-ocaml@v2
# us. However, Homebrew doesn't link it by default, so we have to install
# and link it manually.
- run: brew install postgresql@15 && brew link --overwrite postgresql@15
if: runner.os == 'macOS'
# Workaround https://github.com/savonet/ocaml-ssl/issues/155 and/or
# https://github.com/ocaml/setup-ocaml/issues/856.
- run: opam pin add ssl 0.6.0 --no-action
if: runner.os == 'Windows' if: runner.os == 'Windows'
with:
ocaml-compiler: ${{matrix.ocaml}}
opam-repositories: |
opam-repository-mingw: https://github.com/ocaml-opam/opam-repository-mingw.git#sunset
default: https://github.com/ocaml/opam-repository.git
- run: opam exec -- make deps - run: opam depext --yes conf-sqlite3
- run: opam depext --yes conf-postgresql
- run: opam exec -- make - run: opam depext --yes conf-libev
# Tests on Windows are disabled because of a difference in ppx_expect
# output. See https://github.com/aantron/dream/pull/282. This difference
# remains as of ppx_expect 0.16.
- run: opam exec -- make test
if: runner.os != 'Windows' if: runner.os != 'Windows'
- run: opam lint --recursive example # The tests require ppx_expect. The latest versions of it introduced changes
# in the formatting of the output, and also require OCaml >= 4.10, which
- name: Build examples # makes testing on < 4.10 awkward. So, we skip tests on < 4.10.
if: runner.os != 'Windows' - shell: bash
run: | run: |
set -e set -e
set -x set -x
EXCLUDED_EXAMPLES='w-mirage*|r-tyxml|w-dream-html'
EXAMPLES=$(find example -maxdepth 1 -type d | grep -Ev $EXCLUDED_EXAMPLES | grep -v "^example/0" | grep -v "^example$" | sort)
shopt -s nullglob
for EXAMPLE in $EXAMPLES
do
FILE=$(find $EXAMPLE -maxdepth 1 -type f -and -path "${EXAMPLE}/*.ml")
FILE+=$(find $EXAMPLE -maxdepth 1 -type f -and -path "${EXAMPLE}/*.re")
FILE+=$(find $EXAMPLE -maxdepth 2 -type f -and -path "${EXAMPLE}/server/*.ml")
FILE+=$(find $EXAMPLE -maxdepth 2 -type f -and -path "${EXAMPLE}/server/*.re")
if [[ "$FILE" == "" ]]; then WITH_TEST=--with-test
continue case ${{matrix.ocaml}} in
4.09.x) WITH_TEST=;;
4.08.x) WITH_TEST=;;
esac
# Tests on Windows are disabled because of a difference in ppx_expect
# output. See https://github.com/aantron/dream/pull/282.
case ${{runner.os}} in
Windows) WITH_TEST=;;
esac
OPAM=$(which opam || true)
if [ -z "$OPAM" ]
then
OPAM=D:\\cygwin\\wrapperbin\\opam.cmd
fi fi
$OPAM install --yes --deps-only $WITH_TEST ./dream-pure.opam ./dream-httpaf.opam ./dream.opam
if [ ! -z "$WITH_TEST" ]
then
$OPAM exec -- dune runtest
EXAMPLES=$(find example -maxdepth 1 -type d -not -name "w-mirage*" -not -name "r-tyxml" | grep -v "^example/0" | grep -v "^example$" | sort)
shopt -s nullglob
for EXAMPLE in $EXAMPLES
do
FILE=$(ls $EXAMPLE/*.ml $EXAMPLE/*.re $EXAMPLE/server/*.ml $EXAMPLE/server/*.re)
EXE=$(echo $FILE | sed 's/\..*$/.exe/g') EXE=$(echo $FILE | sed 's/\..*$/.exe/g')
echo dune build $EXE echo dune build $EXE
opam exec -- dune build $EXE $OPAM exec -- dune build $EXE
done done
fi
quickstart: quickstart:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: os:
- ubuntu-22.04 - ubuntu-latest
ocaml: - macos-latest
- 5.2.x
- 4.14.x
include:
- os: macos-latest
ocaml: 4.14.x
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: ocaml/setup-ocaml@v3 - name: Quick start
with:
ocaml-compiler: ${{matrix.ocaml}}
dune-cache: true
- name: Run quickstart.sh
shell: bash
run: | run: |
set -x set -x
touch output touch output
@ -114,29 +117,25 @@ jobs:
fi fi
mirage: mirage:
if: false runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
with: with:
submodules: recursive submodules: recursive
- run: mkdir ../repo-copy - run: mkdir ../repo-copy
- run: cp -r * ../repo-copy/ - run: cp -r * ../repo-copy/
- uses: ocaml/setup-ocaml@v3 - uses: avsm/setup-ocaml@v2
with: with:
ocaml-compiler: 4.14.x ocaml-compiler: 4.14.x
dune-cache: true
# Needed until https://github.com/robur-coop/ocaml-letsencrypt/pull/34.
- run: opam pin add letsencrypt git+https://github.com/hannesm/ocaml-letsencrypt.git#no-cstruct --no-action
- run: opam install --yes --deps-only ./dream-pure.opam ./dream-httpaf.opam ./dream.opam ./dream-mirage.opam - run: opam install --yes --deps-only ./dream-pure.opam ./dream-httpaf.opam ./dream.opam ./dream-mirage.opam
- run: opam install --yes mirage mirage-clock-unix mirage-crypto-rng-mirage - run: opam install --yes mirage mirage-clock-unix
- run: cd example/w-mirage && mv config.ml config.ml.backup - run: cd example/w-mirage && mv config.ml config.ml.backup
- run: cd example/w-mirage && sed -e 's/package "dream-mirage"//' < config.ml.backup > config.ml - run: cd example/w-mirage && sed -e 's/package "dream-mirage"//' < config.ml.backup > config.ml
- run: cd example/w-mirage && opam exec -- mirage configure -t unix - run: cd example/w-mirage && opam exec -- mirage configure -t unix
- run: cd example/w-mirage && opam exec -- make depends - run: cd example/w-mirage && opam exec -- make depends
- run: cd example/w-mirage && ls duniverse - run: cd example/w-mirage && ls duniverse
- run: cp -r ../repo-copy example/w-mirage/duniverse/dream - run: cp -r ../repo-copy example/w-mirage/duniverse/dream
- run: cd example/w-mirage/duniverse && rm -rf ocaml-cstruct logs ke fmt lwt bytes seq mirage-flow sexplib0 ptime tls domain-name ocaml-ipaddr mirage-clock ocplib-endian digestif eqaf mirage-crypto mirage-runtime - run: cd example/w-mirage/duniverse && rm -rf ocaml-cstruct logs ke fmt lwt bytes seq mirage-flow sexplib0 ptime tls domain-name ocaml-ipaddr mirage-clock ocplib-endian
- run: cd example/w-mirage && mv config.ml.backup config.ml - run: cd example/w-mirage && mv config.ml.backup config.ml
- run: cd example/w-mirage && sed -e 's/(libraries/(libraries dream-mirage/' < dune.build > dune.build.2 - run: cd example/w-mirage && sed -e 's/(libraries/(libraries dream-mirage/' < dune.build > dune.build.2
- run: cd example/w-mirage && mv dune.build.2 dune.build - run: cd example/w-mirage && mv dune.build.2 dune.build

16
.gitmodules vendored Normal file
View File

@ -0,0 +1,16 @@
[submodule "src/vendor/httpaf"]
path = src/vendor/httpaf
url = https://github.com/aantron/httpaf.git
[submodule "src/vendor/gluten"]
path = src/vendor/gluten
url = https://github.com/aantron/gluten.git
[submodule "src/vendor/websocketaf"]
path = src/vendor/websocketaf
url = https://github.com/aantron/websocketaf.git
[submodule "src/vendor/h2"]
path = src/vendor/h2
url = https://github.com/aantron/ocaml-h2.git
[submodule "src/vendor/paf"]
path = src/vendor/paf
url = https://github.com/aantron/paf-le-chien.git
branch = dream

View File

@ -165,7 +165,3 @@ release-finish :
opam pin remove -y dream-pure dream-httpaf dream opam pin remove -y dream-pure dream-httpaf dream
sha256sum $(RELEASE).tar.gz sha256sum $(RELEASE).tar.gz
ls -l $(RELEASE).tar.gz ls -l $(RELEASE).tar.gz
.PHONY : release-clean
release-clean :
rm -rf $(RELEASE) $(RELEASE).tar.gz _release

View File

@ -77,24 +77,24 @@ Dream binary][one-binary], or use Dream in a subcommand. Dream tries to be as
functional as possible, touching global runtime state only lazily, when called functional as possible, touching global runtime state only lazily, when called
into. into.
[https]: https://github.com/aantron/dream/tree/master/example/l-https#folders-and-files [https]: https://github.com/aantron/dream/tree/master/example/l-https#files
[websocket]: https://github.com/aantron/dream/tree/master/example/k-websocket#folders-and-files [websocket]: https://github.com/aantron/dream/tree/master/example/k-websocket#files
[graphql]: https://github.com/aantron/dream/tree/master/example/w-graphql-subscription#folders-and-files [graphql]: https://github.com/aantron/dream/tree/master/example/w-graphql-subscription#files
[templates]: https://github.com/aantron/dream/tree/master/example/7-template#folders-and-files [templates]: https://github.com/aantron/dream/tree/master/example/7-template#files
[reason-templates]: https://github.com/aantron/dream/tree/master/example/r-template#folders-and-files [reason-templates]: https://github.com/aantron/dream/tree/master/example/r-template#files
[middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files [middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#files
[handler]: https://aantron.github.io/dream/#type-handler [handler]: https://aantron.github.io/dream/#type-handler
[routing]: https://github.com/aantron/dream/tree/master/example/3-router#folders-and-files [routing]: https://github.com/aantron/dream/tree/master/example/3-router#files
[cookies]: https://aantron.github.io/dream/#cookies [cookies]: https://aantron.github.io/dream/#cookies
[forms]: https://aantron.github.io/dream/#forms [forms]: https://aantron.github.io/dream/#forms
[sessions]: https://github.com/aantron/dream/tree/master/example/b-session#folders-and-files [sessions]: https://github.com/aantron/dream/tree/master/example/b-session#files
[back-ends]: https://aantron.github.io/dream/#back-ends [back-ends]: https://aantron.github.io/dream/#back-ends
[errors]: https://github.com/aantron/dream/tree/master/example/9-error#folders-and-files [errors]: https://github.com/aantron/dream/tree/master/example/9-error#files
[crypto]: https://aantron.github.io/dream/#cryptography [crypto]: https://aantron.github.io/dream/#cryptography
[logging]: https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files [logging]: https://github.com/aantron/dream/tree/master/example/2-middleware#files
[melange]: https://github.com/aantron/dream/tree/master/example/r-fullstack-melange#folders-and-files [melange]: https://github.com/aantron/dream/tree/master/example/r-fullstack-melange#files
[rescript]: https://github.com/aantron/dream/tree/master/example/w-fullstack-rescript#folders-and-files [rescript]: https://github.com/aantron/dream/tree/master/example/w-fullstack-rescript#files
[jsoo]: https://github.com/aantron/dream/tree/master/example/w-fullstack-jsoo#folders-and-files [jsoo]: https://github.com/aantron/dream/tree/master/example/w-fullstack-jsoo#files
[types]: https://aantron.github.io/dream/#types [types]: https://aantron.github.io/dream/#types
[basic-read]: https://aantron.github.io/dream/#val-body [basic-read]: https://aantron.github.io/dream/#val-body
[streaming]: https://aantron.github.io/dream/#streaming [streaming]: https://aantron.github.io/dream/#streaming
@ -102,15 +102,15 @@ into.
[alpn]: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation [alpn]: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation
[libs]: https://github.com/aantron/dream/tree/master/src [libs]: https://github.com/aantron/dream/tree/master/src
[deploy]: https://github.com/aantron/dream/tree/master/example#deploying [deploy]: https://github.com/aantron/dream/tree/master/example#deploying
[jsx]: https://github.com/aantron/dream/tree/master/example/r-tyxml#folders-and-files [jsx]: https://github.com/aantron/dream/tree/master/example/r-tyxml#files
[one-binary]: https://github.com/aantron/dream/tree/master/example/w-one-binary#folders-and-files [one-binary]: https://github.com/aantron/dream/tree/master/example/w-one-binary#files
<br> <br>
## Quick start ## Quick start
You can get You can get
[one](https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files) [one](https://github.com/aantron/dream/tree/master/example/2-middleware#files)
of the first [tutorials][tutorial] and build it locally with: of the first [tutorials][tutorial] and build it locally with:
<pre><b>bash -c "$(curl -fsSL https://raw.githubusercontent.com/aantron/dream/master/example/quickstart.sh)"</b></pre> <pre><b>bash -c "$(curl -fsSL https://raw.githubusercontent.com/aantron/dream/master/example/quickstart.sh)"</b></pre>
@ -139,10 +139,10 @@ After that, go to any of the [examples][tutorial], such as
dune exec ./middleware.exe dune exec ./middleware.exe
``` ```
[esy-example]: https://github.com/aantron/dream/tree/master/example/w-esy#folders-and-files [esy-example]: https://github.com/aantron/dream/tree/master/example/w-esy#files
[quickstart.sh]: https://github.com/aantron/dream/blob/master/example/quickstart.sh [quickstart.sh]: https://github.com/aantron/dream/blob/master/example/quickstart.sh
[esy]: https://esy.sh/ [esy]: https://esy.sh/
[2-middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files [2-middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#files
## esy ## esy
@ -173,14 +173,14 @@ esy`, and started with `npx esy start`.
[tutorial]: https://github.com/aantron/dream/tree/master/example#readme [tutorial]: https://github.com/aantron/dream/tree/master/example#readme
[examples]: https://github.com/aantron/dream/tree/master/example#examples [examples]: https://github.com/aantron/dream/tree/master/example#examples
[1-hello]: https://github.com/aantron/dream/tree/master/example/1-hello#folders-and-files [1-hello]: https://github.com/aantron/dream/tree/master/example/1-hello#files
[r-hello]: https://github.com/aantron/dream/tree/master/example/r-hello#folders-and-files [r-hello]: https://github.com/aantron/dream/tree/master/example/r-hello#files
[reason-examples]: https://github.com/aantron/dream/tree/master/example#reason [reason-examples]: https://github.com/aantron/dream/tree/master/example#reason
[deploying]: https://github.com/aantron/dream/tree/master/example#deploying [deploying]: https://github.com/aantron/dream/tree/master/example#deploying
[api-main]: https://aantron.github.io/dream/#types [api-main]: https://aantron.github.io/dream/#types
[fullstack]: https://github.com/aantron/dream/tree/master/example#full-stack [fullstack]: https://github.com/aantron/dream/tree/master/example#full-stack
[watch]: https://github.com/aantron/dream/tree/master/example/w-watch#folders-and-files [watch]: https://github.com/aantron/dream/tree/master/example/w-watch#files
[reload]: https://github.com/aantron/dream/tree/master/example/w-live-reload#folders-and-files [reload]: https://github.com/aantron/dream/tree/master/example/w-live-reload#files
<br> <br>
@ -217,7 +217,7 @@ Apart from the [issues](https://github.com/aantron/dream/issues), good places
to discuss Dream are... to discuss Dream are...
- #dream on the [Reason Discord](https://discord.gg/2JTYRq2rYh). - #dream on the [Reason Discord](https://discord.gg/2JTYRq2rYh).
- #webdev on the [OCaml Discord](https://discord.gg/sx45hPkkWV). - #webdev on the [OCaml Discord](https://discord.gg/sx45hPkkWV)
- The [OCaml Discuss forum](https://discuss.ocaml.org/). - The [OCaml Discuss forum](https://discuss.ocaml.org/).
- The development stream on [Twitch](https://www.twitch.tv/antron_ML). - The development stream on [Twitch](https://www.twitch.tv/antron_ML).

View File

@ -1140,6 +1140,46 @@ let part_replacement = {|
</pre> </pre>
|} |}
let upload_event_expected = {|<div class="spec type" id="type-upload_event">
<a href="#type-upload_event" class="anchor"></a><code><span><span class="keyword">type</span> upload_event</span><span> = </span><span>[ </span></code>
<table>
<tbody>
<tr id="type-upload_event.File" class="anchored">
<td class="def constructor">
<a href="#type-upload_event.File" class="anchor"></a><code><span>| </span></code><code><span>`File <span class="keyword">of</span> string * string</span></code>
</td>
</tr>
<tr id="type-upload_event.Field" class="anchored">
<td class="def constructor">
<a href="#type-upload_event.Field" class="anchor"></a><code><span>| </span></code><code><span>`Field <span class="keyword">of</span> string * string</span></code>
</td>
</tr>
<tr id="type-upload_event.Done" class="anchored">
<td class="def constructor">
<a href="#type-upload_event.Done" class="anchor"></a><code><span>| </span></code><code><span>`Done</span></code>
</td>
</tr>
<tr id="type-upload_event.Wrong_content_type" class="anchored">
<td class="def constructor">
<a href="#type-upload_event.Wrong_content_type" class="anchor"></a><code><span>| </span></code><code><span>`Wrong_content_type</span></code>
</td>
</tr>
</tbody>
</table>
<code><span> ]</span></code>
</div>
|}
let upload_event_replacement = {|
<pre><span class="keyword">type</span> upload_event = [
| `File <span class="of">of</span> <a href="https://ocaml.org/manual/latest/api/String.html">string</a> * <a href="https://ocaml.org/manual/latest/api/String.html">string</a>
| `Field <span class="of">of</span> <a href="https://ocaml.org/manual/latest/api/String.html">string</a> * <a href="https://ocaml.org/manual/latest/api/String.html">string</a>
| `Done
| `Wrong_content_type
]
</pre>
|}
let csrf_result_expected = {|<div class="spec type" id="type-csrf_result"> let csrf_result_expected = {|<div class="spec type" id="type-csrf_result">
<a href="#type-csrf_result" class="anchor"></a><code><span><span class="keyword">type</span> csrf_result</span><span> = </span><span>[ </span></code> <a href="#type-csrf_result" class="anchor"></a><code><span><span class="keyword">type</span> csrf_result</span><span> = </span><span>[ </span></code>
<table> <table>
@ -1657,6 +1697,18 @@ let new_field_replacement = {|
</pre> </pre>
|} |}
let new_global_expected = {|<div class="spec value" id="val-new_global">
<a href="#val-new_global" class="anchor"></a><code><span><span class="keyword">val</span> new_global : <span>?name:string <span class="arrow">-&gt;</span></span> <span>?show_value:<span>(<span><span class="type-var">'a</span> <span class="arrow">-&gt;</span></span> string)</span> <span class="arrow">-&gt;</span></span> <span><span>(<span>unit <span class="arrow">-&gt;</span></span> <span class="type-var">'a</span>)</span> <span class="arrow">-&gt;</span></span> <span><span class="type-var">'a</span> <a href="#type-global">global</a></span></span></code>
</div>
|}
let new_global_replacement = {|
<pre><span class="keyword">val</span> new_global :
?name:<a href="https://ocaml.org/manual/latest/api/String.html">string</a> ->
?show_value:('a -> <a href="https://ocaml.org/manual/latest/api/String.html">string</a>) ->
(<a href="https://ocaml.org/manual/latest/api/Unit.html">unit</a> -> 'a) -> 'a <a href="#type-global">global</a>
|}
let run_expected = {|<div class="spec value" id="val-run"> let run_expected = {|<div class="spec value" id="val-run">
<a href="#val-run" class="anchor"></a><code><span><span class="keyword">val</span> run : <span>?interface:string <span class="arrow">-&gt;</span></span> <span>?port:int <span class="arrow">-&gt;</span></span> <span>?socket_path:string <span class="arrow">-&gt;</span></span> <span>?stop:<span>unit <a href="#type-promise">promise</a></span> <span class="arrow">-&gt;</span></span> <a href="#val-run" class="anchor"></a><code><span><span class="keyword">val</span> run : <span>?interface:string <span class="arrow">-&gt;</span></span> <span>?port:int <span class="arrow">-&gt;</span></span> <span>?socket_path:string <span class="arrow">-&gt;</span></span> <span>?stop:<span>unit <a href="#type-promise">promise</a></span> <span class="arrow">-&gt;</span></span>
<span>?error_handler:<a href="#type-error_handler">error_handler</a> <span class="arrow">-&gt;</span></span> <span>?tls:bool <span class="arrow">-&gt;</span></span> <span>?certificate_file:string <span class="arrow">-&gt;</span></span> <span>?key_file:string <span class="arrow">-&gt;</span></span> <span>?error_handler:<a href="#type-error_handler">error_handler</a> <span class="arrow">-&gt;</span></span> <span>?tls:bool <span class="arrow">-&gt;</span></span> <span>?certificate_file:string <span class="arrow">-&gt;</span></span> <span>?key_file:string <span class="arrow">-&gt;</span></span>

View File

@ -434,6 +434,7 @@ p + .odoc-spec {
#val-origin_referrer_check + .spec-doc li + li, #val-origin_referrer_check + .spec-doc li + li,
#val-form + .spec-doc li + li, #val-form + .spec-doc li + li,
#type-part + .spec-doc li + li, #type-part + .spec-doc li + li,
#type-upload_event + .spec-doc li + li,
#val-upload + .spec-doc li + li, #val-upload + .spec-doc li + li,
#val-static + .spec-doc li + li, #val-static + .spec-doc li + li,
#val-from_path + .spec-doc li + li { #val-from_path + .spec-doc li + li {

View File

@ -36,7 +36,7 @@ init_theme();
</div> </div>
<ul> <ul>
<li><code>1.0.0~alpha7</code></li> <li><code>1.0.0~alpha6</code></li>
<li><code>opam install dream</code></li> <li><code>opam install dream</code></li>
<li><a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream">GitHub</a></li> <li><a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream">GitHub</a></li>
<li><a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream/edit/master/src/dream.mli">Edit these docs</a></li> <li><a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream/edit/master/src/dream.mli">Edit these docs</a></li>
@ -123,7 +123,7 @@ init_theme();
<li> <li>
A <a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream/tree/master/example#readme"> A <a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream/tree/master/example#readme">
Tutorial</a> &mdash; get started at Tutorial</a> &mdash; get started at
<a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream/tree/master/example/1-hello#folders-and-files"> <a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream/tree/master/example/1-hello#files">
<code>1-hello</code></a>! <code>1-hello</code></a>!
</li> </li>
<li> <li>

View File

@ -15,18 +15,31 @@ maintainer: "Anton Bachin <antonbachin@yahoo.com>"
depends: [ depends: [
"dream-pure" "dream-pure"
"dune" {>= "2.7.0"} # --instrument-with. "dune" {>= "2.7.0"} # --instrument-with.
"gluten"
"gluten-lwt-unix"
"h2" {< "0.13.0"}
"h2-lwt-unix"
"httpun" {< "0.2.0"}
"httpun-lwt-unix"
"httpun-ws"
"lwt" "lwt"
"lwt_ppx" {>= "1.2.2"} "lwt_ppx" {>= "1.2.2"}
"lwt_ssl" "lwt_ssl"
"ocaml" {>= "4.08.0"} "ocaml" {>= "4.08.0"}
"ssl" {>= "0.5.8"} # Ssl.get_negotiated_alpn_protocol. "ssl" {>= "0.5.8"} # Ssl.get_negotiated_alpn_protocol.
# Currently vendored.
# "gluten"
# "gluten-lwt-unix"
# "httpaf"
# "httpaf-lwt-unix"
# "h2"
# "h2-lwt-unix"
# "hpack"
# "websocketaf"
# Dependencies of vendored packages.
"angstrom" {>= "0.14.0"}
"base64" {>= "3.0.0"}
"bigstringaf" {>= "0.5.0"} # h2.
"digestif" {>= "0.7.2"} # websocket/af, sha1, default implementation.
"faraday" {>= "0.6.1"}
"faraday-lwt-unix"
"lwt_ssl" {>= "1.2.0"} # Gluten.
"psq" # h2.
] ]
build: [ build: [

View File

@ -29,7 +29,7 @@ Within this model, Dream adds:
- Helpers for Web formats, such as Base64url, and a modern cipher. - Helpers for Web formats, such as Base64url, and a modern cipher.
Because of the simple programming model, everything is optional and Because of the simple programming model, everything is optional and
composable. It is trivially possible to strip Dream down to just a composable. It is trivailly possible to strip Dream down to just a
bare driver of the various HTTP protocols. bare driver of the various HTTP protocols.
Dream is presented as a single module, whose API is documented on one Dream is presented as a single module, whose API is documented on one

View File

@ -29,7 +29,7 @@ Within this model, Dream adds:
- Helpers for Web formats, such as Base64url, and a modern cipher. - Helpers for Web formats, such as Base64url, and a modern cipher.
Because of the simple programming model, everything is optional and Because of the simple programming model, everything is optional and
composable. It is trivially possible to strip Dream down to just a composable. It is trivailly possible to strip Dream down to just a
bare driver of the various HTTP protocols. bare driver of the various HTTP protocols.
Dream is presented as a single module, whose API is documented on one Dream is presented as a single module, whose API is documented on one
@ -55,7 +55,7 @@ depends: [
("conf-libev" {os != "win32"} | "ocaml" {os = "win32"}) ("conf-libev" {os != "win32"} | "ocaml" {os = "win32"})
"cstruct" {>= "6.0.0"} "cstruct" {>= "6.0.0"}
"digestif" {>= "0.7"} # to_raw_string. "digestif" {>= "0.7"} # to_raw_string.
"dream-httpaf" {>= "1.0.0~alpha4"} "dream-httpaf" {>= "1.0.0~alpha3"}
"dream-pure" {>= "1.0.0~alpha2"} "dream-pure" {>= "1.0.0~alpha2"}
"dune" {>= "2.7.0"} # --instrument-with. "dune" {>= "2.7.0"} # --instrument-with.
"fmt" {>= "0.8.7"} # `Italic. "fmt" {>= "0.8.7"} # `Italic.
@ -89,7 +89,7 @@ depends: [
"html_of_jsx" {with-test} "html_of_jsx" {with-test}
"js_of_ocaml" {with-test} "js_of_ocaml" {with-test}
"js_of_ocaml-ppx" {with-test} "js_of_ocaml-ppx" {with-test}
"ppx_expect" {with-test & >= "v0.15.0" & < "v0.17.0"} # Breaking changes. "ppx_expect" {with-test & >= "v0.15.0"} # Formatting changes.
"ppx_yojson_conv" {with-test} "ppx_yojson_conv" {with-test}
"reason" {with-test} "reason" {with-test}
"tyxml" {with-test & >= "4.5.0"} "tyxml" {with-test & >= "4.5.0"}

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -40,17 +40,17 @@ name of the `.ml` file, but with `.ml` changed to `.exe`.
**Next steps:** **Next steps:**
- The next example, [**`2-middleware`**](../2-middleware#folders-and-files), adds a logger - The next example, [**`2-middleware`**](../2-middleware#files), adds a logger
to the app. to the app.
- [**`3-router`**](../3-router#folders-and-files) sends requests to different handlers, - [**`3-router`**](../3-router#files) sends requests to different handlers,
depending on their path. depending on their path.
<br> <br>
**See also:** **See also:**
- [**`r-hello`**](../r-hello#folders-and-files) is a Reason syntax version of this example. - [**`r-hello`**](../r-hello#files) is a Reason syntax version of this example.
- [**`w-watch`**](../w-watch#folders-and-files) sets up a development watcher. - [**`w-watch`**](../w-watch#files) sets up a development watcher.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -4,7 +4,7 @@
*Middleware* is just functions that take handlers and wrap them, producing *Middleware* is just functions that take handlers and wrap them, producing
bigger handlers that do a little bit more. This example takes the handler from bigger handlers that do a little bit more. This example takes the handler from
[**`1-hello`**](../1-hello#folders-and-files) and wraps it in one of the most useful [**`1-hello`**](../1-hello#files) and wraps it in one of the most useful
middlewares, the [*logger*](https://aantron.github.io/dream/#val-logger): middlewares, the [*logger*](https://aantron.github.io/dream/#val-logger):
```ocaml ```ocaml
@ -40,7 +40,7 @@ When you run this server and visit
You can write your own messages to the log using You can write your own messages to the log using
[`Dream.log`](https://aantron.github.io/dream/#val-log). See example [`Dream.log`](https://aantron.github.io/dream/#val-log). See example
[**`a-log`**](../a-log#folders-and-files) for more logging options. Now that we have the [**`a-log`**](../a-log#files) for more logging options. Now that we have the
logger, we will use it in all other examples, even though it's not really logger, we will use it in all other examples, even though it's not really
necessary &mdash; it just makes it much easier to see what is going on. necessary &mdash; it just makes it much easier to see what is going on.
@ -48,14 +48,14 @@ necessary &mdash; it just makes it much easier to see what is going on.
There's not much else to middlewares &mdash; they are really just functions There's not much else to middlewares &mdash; they are really just functions
from handlers to handlers, so you can create them anywhere. Example from handlers to handlers, so you can create them anywhere. Example
[**`4-counter`**](../4-counter#folders-and-files) already shows a simple custom middleware. [**`4-counter`**](../4-counter#files) already shows a simple custom middleware.
<!-- <!--
There are also more complicated middlewares defined in There are also more complicated middlewares defined in
- [**`m-locals`**](../m-locals#folders-and-files), - [**`m-locals`**](../m-locals/#files),
- [**`w-auto-reload`**](../w-auto-reload#folders-and-files), and - [**`w-auto-reload`**](../w-auto-reload/#files), and
- [**`w-index-html`**](../w-index-html#folders-and-files). - [**`w-index-html`**](../w-index-html/#files).
--> -->
<!-- TODO Fill out this list; probably a-promise belongs here. --> <!-- TODO Fill out this list; probably a-promise belongs here. -->
@ -64,10 +64,10 @@ There are also more complicated middlewares defined in
**Next steps:** **Next steps:**
- The next example, [**`3-router`**](../3-router#folders-and-files), shows - The next example, [**`3-router`**](../3-router#files), shows
[*routes*](https://aantron.github.io/dream/#routing), the other way to build [*routes*](https://aantron.github.io/dream/#routing), the other way to build
up handlers in Dream. up handlers in Dream.
- [**`4-counter`**](../4-counter#folders-and-files) builds the first custom middleware. - [**`4-counter`**](../4-counter#files) builds the first custom middleware.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -42,20 +42,20 @@ The syntax `:word` in a route creates a path parameter, which can be read with
When none of the routes match, the router returns a `404 Not Found` response. When none of the routes match, the router returns a `404 Not Found` response.
Except for the status code, the `404 Not Found` response is *completely* empty, Except for the status code, the `404 Not Found` response is *completely* empty,
so it might not display well in your browser. In example so it might not display well in your browser. In example
[**`9-error`**](../9-error#folders-and-files), we will decorate all error responses with [**`9-error`**](../9-error#files), we will decorate all error responses with
an error template in one central location. an error template in one central location.
<br> <br>
The router can do more than match simple routes: The router can do more than match simple routes:
- [**`f-static`**](../f-static#folders-and-files) forwards all requests with a certain - [**`f-static`**](../f-static#files) forwards all requests with a certain
prefix to a static file handler. prefix to a static file handler.
<!-- - [**`w-scope`**](../w-scope#folders-and-files) applies middlewares to groups of routes <!-- - [**`w-scope`**](../w-scope/#files) applies middlewares to groups of routes
&mdash; but only when they match. &mdash; but only when they match.
- [**`w-subsite`**](../w-subsite#folders-and-files) attaches a handler as a complete, - [**`w-subsite`**](../w-subsite/#files) attaches a handler as a complete,
nested sub-site, which might have its own router. --> nested sub-site, which might have its own router. -->
<!-- TODO --> <!-- TODO -->
@ -63,9 +63,9 @@ The router can do more than match simple routes:
**Next steps:** **Next steps:**
- [**`4-counter`**](../4-counter#folders-and-files) counts requests, and exposes a route for - [**`4-counter`**](../4-counter#files) counts requests, and exposes a route for
getting the count. getting the count.
- [**`5-promise`**](../5-promise#folders-and-files) introduces - [**`5-promise`**](../5-promise#files) introduces
[Lwt](https://github.com/ocsigen/lwt), the promise library used by Dream. [Lwt](https://github.com/ocsigen/lwt), the promise library used by Dream.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -37,16 +37,16 @@ which means they usually also
This example's middleware only does something *before* calling the This example's middleware only does something *before* calling the
`inner_handler`. To do something *after*, we will need to await the response `inner_handler`. To do something *after*, we will need to await the response
promise with [Lwt](https://github.com/ocsigen/lwt#readme), the promise library promise with [Lwt](https://github.com/ocsigen/lwt#readme), the promise library
used by Dream. The next example, [**`5-promise`**](../5-promise#folders-and-files), does used by Dream. The next example, [**`5-promise`**](../5-promise#files), does
exactly that! exactly that!
<br> <br>
**Next steps:** **Next steps:**
- [**`5-promise`**](../5-promise#folders-and-files) shows a middleware that awaits - [**`5-promise`**](../5-promise#files) shows a middleware that awaits
responses using [Lwt](https://github.com/ocsigen/lwt). responses using [Lwt](https://github.com/ocsigen/lwt).
- [**`6-echo`**](../6-echo#folders-and-files) responds to `POST` requests and reads their - [**`6-echo`**](../6-echo#files) responds to `POST` requests and reads their
bodies. bodies.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -2,7 +2,7 @@
<br> <br>
[**`4-counter`**](../4-counter#folders-and-files) was limited to counting requests *before* [**`4-counter`**](../4-counter#files) was limited to counting requests *before*
passing them on to the rest of the app. With the promise library passing them on to the rest of the app. With the promise library
[Lwt](https://github.com/ocsigen/lwt), we can await responses, and do something [Lwt](https://github.com/ocsigen/lwt), we can await responses, and do something
*after*. In this example, we separately count requests that were handled *after*. In this example, we separately count requests that were handled
@ -91,8 +91,8 @@ We will stick to `let%lwt` in the examples and keep things tidy.
**Next steps:** **Next steps:**
- [**`6-echo`**](../6-echo#folders-and-files) uses Dream and Lwt to read a request body. - [**`6-echo`**](../6-echo#files) uses Dream and Lwt to read a request body.
- [**`7-template`**](../7-template#folders-and-files) shows how to interleave HTML and - [**`7-template`**](../7-template#files) shows how to interleave HTML and
OCaml. OCaml.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -46,11 +46,11 @@ foo
We usually want to do something more interesting with the request body than just We usually want to do something more interesting with the request body than just
echo it, and there are several examples for that! echo it, and there are several examples for that!
- [**`d-form`**](../d-form#folders-and-files) parses request bodies as forms. - [**`d-form`**](../d-form#files) parses request bodies as forms.
- [**`e-json`**](../e-json#folders-and-files) parses bodies as JSON. - [**`e-json`**](../e-json#files) parses bodies as JSON.
- [**`g-upload`**](../g-upload#folders-and-files) receives file upload forms. - [**`g-upload`**](../g-upload#files) receives file upload forms.
- [**`i-graphql`**](../i-graphql#folders-and-files) receives GraphQL queries. - [**`i-graphql`**](../i-graphql#files) receives GraphQL queries.
- [**`j-stream`**](../j-stream#folders-and-files) streams huge bodies. - [**`j-stream`**](../j-stream#files) streams huge bodies.
We delay these examples a bit, so we can squeeze in a couple security topics We delay these examples a bit, so we can squeeze in a couple security topics
first. These examples do take client input, after all! So, it's better to first. These examples do take client input, after all! So, it's better to
@ -62,9 +62,9 @@ present them the right way.
**Next steps:** **Next steps:**
- [**`7-template`**](../7-template#folders-and-files) builds responses from templates and - [**`7-template`**](../7-template#files) builds responses from templates and
guards against injection attacks (XSS). guards against injection attacks (XSS).
- [**`8-debug`**](../8-debug#folders-and-files) renders error information in responses. - [**`8-debug`**](../8-debug#files) renders error information in responses.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -125,31 +125,27 @@ and not supported by Dream.
**Next steps:** **Next steps:**
- [**`8-debug`**](../8-debug#folders-and-files) shows how to turn on debug responses, and - [**`8-debug`**](../8-debug#files) shows how to turn on debug responses, and
get more info about errors. get more info about errors.
- [**`9-error`**](../9-error#folders-and-files) sets up a central error template for all - [**`9-error`**](../9-error#files) sets up a central error template for all
errors. errors.
- [**`r-template`**](../r-template#folders-and-files) is a Reason syntax version of this - [**`r-template`**](../r-template#files) is a Reason syntax version of this
example. example.
<br> <br>
**See also:** **See also:**
- [**`w-template-files`**](../w-template-files#folders-and-files) moves the template into a - [**`w-template-files`**](../w-template-files#files) moves the template into a
separate `.eml.html` to avoid problems with editor support. separate `.eml.html` to avoid problems with editor support.
- [**`w-template-logic`**](../w-template-logic#folders-and-files) shows how to put control - [**`w-template-logic`**](../w-template-logic#files) shows how to put control
flow into templates. flow into templates.
- [**`w-tyxml`**](../w-tyxml#folders-and-files) shows how to use - [**`w-tyxml`**](../w-tyxml#files) shows how to use
[TyXML](https://github.com/ocsigen/tyxml), a different templater that uses [TyXML](https://github.com/ocsigen/tyxml), a different templater that uses
OCaml's type system to prevent emitting many kinds of invalid HTML. OCaml's type system to prevent emitting many kinds of invalid HTML.
- [**`r-tyxml`**](../r-tyxml#folders-and-files) if you are using Reason. You can use TyXML - [**`r-tyxml`**](../r-tyxml#files) if you are using Reason. You can use TyXML
with JSX syntax server-side! with JSX syntax server-side!
- [**`w-dream-html`**](../w-dream-html#folders-and-files) shows how to use - [**`w-template-stream`**](../w-template-stream#files) streams templates to
[dream-html](https://github.com/yawaramin/dream-html), another alternative
library for generating HTML from OCaml, which is more closely integrated with
Dream.
- [**`w-template-stream`**](../w-template-stream#folders-and-files) streams templates to
responses, instead of building up complete response strings. responses, instead of building up complete response strings.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -94,7 +94,7 @@ work with in development.
You can have Dream show a custom error page with any information or graphics You can have Dream show a custom error page with any information or graphics
that you like &mdash; we will do this in the [very next that you like &mdash; we will do this in the [very next
example](../9-error#folders-and-files)! example](../9-error#files)!
<!-- TODO Fix after stack trace is fixed. --> <!-- TODO Fix after stack trace is fixed. -->
<!-- TODO Show the log --> <!-- TODO Show the log -->
@ -104,9 +104,9 @@ example](../9-error#folders-and-files)!
**Next steps:** **Next steps:**
- [**`9-error`**](../9-error#folders-and-files) handles all errors in one place, including - [**`9-error`**](../9-error#files) handles all errors in one place, including
displaying the debugger output. displaying the debugger output.
- [**`a-log`**](../a-log#folders-and-files) shows [log - [**`a-log`**](../a-log#files) shows [log
levels](https://aantron.github.io/dream/#type-log_level) and levels](https://aantron.github.io/dream/#type-log_level) and
[sub-logs](https://aantron.github.io/dream/#type-sub_log). [sub-logs](https://aantron.github.io/dream/#type-sub_log).

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -63,7 +63,7 @@ including return a completely new response.
<br> <br>
`debug_info` is a multiline string containing the same information as in the `debug_info` is a multiline string containing the same information as in the
previous example, [**`8-debug`**](../8-debug#folders-and-files). previous example, [**`8-debug`**](../8-debug#files).
<!-- TODO Images of the generated pages. --> <!-- TODO Images of the generated pages. -->
@ -80,9 +80,9 @@ Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Error_Handling_Cheat_Sheet
**Next steps:** **Next steps:**
- [**`a-log`**](../a-log#folders-and-files) shows how to write messages to Dream's - [**`a-log`**](../a-log#files) shows how to write messages to Dream's
[log](https://aantron.github.io/dream/#logging). [log](https://aantron.github.io/dream/#logging).
- [**`b-session`**](../b-session#folders-and-files) adds [session - [**`b-session`**](../b-session#files) adds [session
management](https://aantron.github.io/dream/#sessions) for associating state management](https://aantron.github.io/dream/#sessions) for associating state
with clients. with clients.

View File

@ -2,46 +2,46 @@
Dream's first several examples make up a **tutorial**. Each example is a Dream's first several examples make up a **tutorial**. Each example is a
complete project with a helpful README, and plenty of links to next steps and complete project with a helpful README, and plenty of links to next steps and
documentation. You can begin at [**`1-hello`**](1-hello#folders-and-files), or look in the documentation. You can begin at [**`1-hello`**](1-hello#files), or look in the
list below and jump to whatever interests you! list below and jump to whatever interests you!
- [**`1-hello`**](1-hello#folders-and-files) &nbsp;&mdash;&nbsp; the simplest Dream server - [**`1-hello`**](1-hello/#files) &nbsp;&mdash;&nbsp; the simplest Dream server
responds to every request with the same friendly message. responds to every request with the same friendly message.
- [**`2-middleware`**](2-middleware#folders-and-files) &nbsp;&mdash;&nbsp; adds the first - [**`2-middleware`**](2-middleware/#files) &nbsp;&mdash;&nbsp; adds the first
Dream middleware: the *logger*. Dream middleware: the *logger*.
- [**`3-router`**](3-router#folders-and-files) &nbsp;&mdash;&nbsp; different handlers for - [**`3-router`**](3-router/#files) &nbsp;&mdash;&nbsp; different handlers for
different paths. different paths.
- [**`4-counter`**](4-counter#folders-and-files) &nbsp;&mdash;&nbsp; the first *custom* - [**`4-counter`**](4-counter/#files) &nbsp;&mdash;&nbsp; the first *custom*
middleware! middleware!
- [**`5-promise`**](5-promise#folders-and-files) &nbsp;&mdash;&nbsp; introduces Lwt, the - [**`5-promise`**](5-promise/#files) &nbsp;&mdash;&nbsp; introduces Lwt, the
promise library used by Dream. promise library used by Dream.
- [**`6-echo`**](6-echo#folders-and-files) &nbsp;&mdash;&nbsp; reads request bodies. - [**`6-echo`**](6-echo/#files) &nbsp;&mdash;&nbsp; reads request bodies.
- [**`7-template`**](7-template#folders-and-files) &nbsp;&mdash;&nbsp; renders responses - [**`7-template`**](7-template/#files) &nbsp;&mdash;&nbsp; renders responses
from inline HTML templates and guards against XSS. from inline HTML templates and guards against XSS.
- [**`8-debug`**](8-debug#folders-and-files) &nbsp;&mdash;&nbsp; includes detailed - [**`8-debug`**](8-debug/#files) &nbsp;&mdash;&nbsp; includes detailed
information about errors in responses. information about errors in responses.
- [**`9-error`**](9-error#folders-and-files) &nbsp;&mdash;&nbsp; customize all error - [**`9-error`**](9-error/#files) &nbsp;&mdash;&nbsp; customize all error
responses in one place. responses in one place.
- [**`a-log`**](a-log#folders-and-files) &nbsp;&mdash;&nbsp; writing messages to Dream's - [**`a-log`**](a-log/#files) &nbsp;&mdash;&nbsp; writing messages to Dream's
log. log.
- [**`b-session`**](b-session#folders-and-files) &nbsp;&mdash;&nbsp; associates state with - [**`b-session`**](b-session/#files) &nbsp;&mdash;&nbsp; associates state with
client sessions. client sessions.
- [**`c-cookie`**](c-cookie#folders-and-files) &nbsp;&mdash;&nbsp; sets custom cookies. - [**`c-cookie`**](c-cookie/#files) &nbsp;&mdash;&nbsp; sets custom cookies.
- [**`d-form`**](d-form#folders-and-files) &nbsp;&mdash;&nbsp; reads forms with CSRF - [**`d-form`**](d-form#files) &nbsp;&mdash;&nbsp; reads forms with CSRF
prevention. prevention.
- [**`e-json`**](e-json#folders-and-files) &nbsp;&mdash;&nbsp; sends and receives JSON - [**`e-json`**](e-json#files) &nbsp;&mdash;&nbsp; sends and receives JSON
securely. securely.
- [**`f-static`**](f-static#folders-and-files) &nbsp;&mdash;&nbsp; serves static files from - [**`f-static`**](f-static#files) &nbsp;&mdash;&nbsp; serves static files from
a local directory. a local directory.
- [**`g-upload`**](g-upload#folders-and-files) &nbsp;&mdash;&nbsp; receives file uploads. - [**`g-upload`**](g-upload#files) &nbsp;&mdash;&nbsp; receives file uploads.
- [**`h-sql`**](h-sql#folders-and-files) &nbsp;&mdash;&nbsp; queries an SQL database. - [**`h-sql`**](h-sql#files) &nbsp;&mdash;&nbsp; queries an SQL database.
- [**`i-graphql`**](i-graphql#folders-and-files) &nbsp;&mdash;&nbsp; serves a GraphQL - [**`i-graphql`**](i-graphql#files) &nbsp;&mdash;&nbsp; serves a GraphQL
schema and GraphiQL. schema and GraphiQL.
- [**`j-stream`**](j-stream#folders-and-files) &nbsp;&mdash;&nbsp; streams request and - [**`j-stream`**](j-stream#files) &nbsp;&mdash;&nbsp; streams request and
response bodies. response bodies.
- [**`k-websocket`**](k-websocket#folders-and-files) &nbsp;&mdash;&nbsp; opens a WebSocket - [**`k-websocket`**](k-websocket#files) &nbsp;&mdash;&nbsp; opens a WebSocket
between client and server. between client and server.
- [**`l-https`**](l-https#folders-and-files) &nbsp;&mdash;&nbsp; enables HTTPS and HTTP/2 - [**`l-https`**](l-https#files) &nbsp;&mdash;&nbsp; enables HTTPS and HTTP/2
upgrades. upgrades.
That's it for the tutorial! That's it for the tutorial!
@ -52,43 +52,43 @@ That's it for the tutorial!
There are several examples showing Dream with Reason syntax. There are several examples showing Dream with Reason syntax.
- [**`r-hello`**](r-hello#folders-and-files) &nbsp;&mdash;&nbsp; the simplest Dream server. - [**`r-hello`**](r-hello#files) &nbsp;&mdash;&nbsp; the simplest Dream server.
- [**`r-template`**](r-template#folders-and-files) &nbsp;&mdash;&nbsp; renders HTML - [**`r-template`**](r-template#files) &nbsp;&mdash;&nbsp; renders HTML
templates and protects against XSS. templates and protects against XSS.
- [**`r-template-files`**](r-template-files#folders-and-files) &nbsp;&mdash;&nbsp; templates - [**`r-template-files`**](r-template-files#files) &nbsp;&mdash;&nbsp; templates
in separate `.html` files for better editor support. in separate `.html` files for better editor support.
- [**`r-template-logic`**](r-template-logic#folders-and-files) &nbsp;&mdash;&nbsp; control - [**`r-template-logic`**](r-template-logic#files) &nbsp;&mdash;&nbsp; control
flow inside templates. flow inside templates.
- [**`r-template-stream`**](r-template-stream#folders-and-files) &nbsp;&mdash;&nbsp; streams - [**`r-template-stream`**](r-template-stream#files) &nbsp;&mdash;&nbsp; streams
templates as response bodies. templates as response bodies.
- [**`r-tyxml`**](r-tyxml#folders-and-files) &nbsp;&mdash;&nbsp; type-checked server-side - [**`r-tyxml`**](r-tyxml#files) &nbsp;&mdash;&nbsp; type-checked server-side
JSX templates. JSX templates.
- [**`r-graphql`**](r-graphql#folders-and-files) &nbsp;&mdash;&nbsp; serves a GraphQL - [**`r-graphql`**](r-graphql#files) &nbsp;&mdash;&nbsp; serves a GraphQL
schema. schema.
<br> <br>
# Full-stack # Full-stack
- [**`r-fullstack-melange`**](r-fullstack-melange#folders-and-files) &nbsp;&mdash;&nbsp; - [**`r-fullstack-melange`**](r-fullstack-melange#files) &nbsp;&mdash;&nbsp;
server *and* client written in Reason! server *and* client written in Reason!
- [**`w-fullstack-rescript`**](w-fullstack-rescript#folders-and-files) &nbsp;&mdash;&nbsp; - [**`w-fullstack-rescript`**](w-fullstack-rescript#files) &nbsp;&mdash;&nbsp;
shares OCaml code between server and client using ReScript. shares OCaml code between server and client using ReScript.
- [**`w-fullstack-jsoo`**](w-fullstack-jsoo#folders-and-files) &nbsp;&mdash;&nbsp; shares - [**`w-fullstack-jsoo`**](w-fullstack-jsoo#files) &nbsp;&mdash;&nbsp; shares
OCaml code between server and client using js_of_ocaml. OCaml code between server and client using js_of_ocaml.
<br> <br>
# Deploying # Deploying
- [**`z-heroku`**](z-heroku#folders-and-files) &nbsp;&mdash;&nbsp; to - [**`z-heroku`**](z-heroku#files) &nbsp;&mdash;&nbsp; to
[Heroku](https://www.heroku.com). [Heroku](https://www.heroku.com).
- [**`z-fly`**](z-fly#folders-and-files) &nbsp;&mdash;&nbsp; to [Fly.io](https://fly.io/). - [**`z-fly`**](z-fly#files) &nbsp;&mdash;&nbsp; to [Fly.io](https://fly.io/).
- [**`z-docker-esy`**](z-docker-esy#folders-and-files) &nbsp;&mdash;&nbsp; on a server, - [**`z-docker-esy`**](z-docker-esy#files) &nbsp;&mdash;&nbsp; on a server,
using Docker, with package manager esy. using Docker, with package manager esy.
- [**`z-docker-opam`**](z-docker-opam#folders-and-files) &nbsp;&mdash;&nbsp; on a server, - [**`z-docker-opam`**](z-docker-opam#files) &nbsp;&mdash;&nbsp; on a server,
using Docker, with package manager opam. using Docker, with package manager opam.
- [**`z-systemd`**](z-systemd#folders-and-files) &nbsp;&mdash;&nbsp; on a server, as a - [**`z-systemd`**](z-systemd#files) &nbsp;&mdash;&nbsp; on a server, as a
systemd daemon. systemd daemon.
<br> <br>
@ -102,51 +102,49 @@ if something is missing!
<br> <br>
- [**`w-template-files`**](w-template-files#folders-and-files) &nbsp;&mdash;&nbsp; templates - [**`w-template-files`**](w-template-files#files) &nbsp;&mdash;&nbsp; templates
in separate `.html` files for better editor support. in separate `.html` files for better editor support.
- [**`w-template-logic`**](w-template-logic#folders-and-files) &nbsp;&mdash;&nbsp; control - [**`w-template-logic`**](w-template-logic#files) &nbsp;&mdash;&nbsp; control
flow inside templates. flow inside templates.
- [**`w-graphql-subscription`**](w-graphql-subscription#folders-and-files) - [**`w-graphql-subscription`**](w-graphql-subscription#files)
&nbsp;&mdash;&nbsp; GraphQL subscriptions. &nbsp;&mdash;&nbsp; GraphQL subscriptions.
- [**`w-postgres`**](w-postgres#folders-and-files) &nbsp;&mdash;&nbsp; connects to a - [**`w-postgres`**](w-postgres#files) &nbsp;&mdash;&nbsp; connects to a
PostgreSQL database. PostgreSQL database.
- [**`w-flash`**](w-flash#folders-and-files) &nbsp;&mdash;&nbsp; using flash messages, which - [**`w-flash`**](w-flash#files) &nbsp;&mdash;&nbsp; using flash messages, which
are displayed on the next request. are displayed on the next request.
- [**`w-chat`**](w-chat#folders-and-files) &nbsp;&mdash;&nbsp; a chat room based on - [**`w-chat`**](w-chat#files) &nbsp;&mdash;&nbsp; a chat room based on
WebSockets. WebSockets.
- [**`w-content-security-policy`**](w-content-security-policy#folders-and-files) - [**`w-content-security-policy`**](w-content-security-policy#files)
&nbsp;&mdash;&nbsp; sandboxes Web pages using `Content-Security-Policy`. &nbsp;&mdash;&nbsp; sandboxes Web pages using `Content-Security-Policy`.
- [**`w-esy`**](w-esy#folders-and-files) &nbsp;&mdash;&nbsp; gives detail on packaging with - [**`w-esy`**](w-esy#files) &nbsp;&mdash;&nbsp; gives detail on packaging with
[esy](https://esy.sh/), an npm-like package manager. [esy](https://esy.sh/), an npm-like package manager.
- [**`w-one-binary`**](w-one-binary#folders-and-files) &nbsp;&mdash;&nbsp; bakes static - [**`w-one-binary`**](w-one-binary#files) &nbsp;&mdash;&nbsp; bakes static
assets into a self-contained server binary. assets into a self-contained server binary.
- [**`w-watch`**](w-watch#folders-and-files) &nbsp;&mdash;&nbsp; sets up a development - [**`w-watch`**](w-watch#files) &nbsp;&mdash;&nbsp; sets up a development
watcher. watcher.
- [**`w-live-reload`**](w-live-reload#folders-and-files) &nbsp;&mdash;&nbsp; a simple - [**`w-live-reload`**](w-live-reload#files) &nbsp;&mdash;&nbsp; a simple
live-reloading setup. live-reloading setup.
- [**`w-nginx`**](w-nginx#folders-and-files) &nbsp;&mdash;&nbsp; uses nginx as a - [**`w-nginx`**](w-nginx#files) &nbsp;&mdash;&nbsp; uses nginx as a
reverse proxy. reverse proxy.
- [**`w-tyxml`**](w-tyxml#folders-and-files) &nbsp;&mdash;&nbsp; uses TyXML for type-checked - [**`w-tyxml`**](w-tyxml#files) &nbsp;&mdash;&nbsp; uses TyXML for type-checked
HTML templating. HTML templating.
- [**`w-dream-html`**](../w-dream-html#folders-and-files) &nbsp;&mdash;&nbsp; uses - [**`w-long-polling`**](w-long-polling#files) &nbsp;&mdash;&nbsp; old form of
dream-html for convenient HTML generation from OCaml.
- [**`w-long-polling`**](w-long-polling#folders-and-files) &nbsp;&mdash;&nbsp; old form of
asynchronous communication without WebSockets. asynchronous communication without WebSockets.
- [**`w-query`**](w-query#folders-and-files) &nbsp;&mdash;&nbsp; reads URL query parameters. - [**`w-query`**](w-query#files) &nbsp;&mdash;&nbsp; reads URL query parameters.
- [**`w-server-sent-events`**](w-server-sent-events#folders-and-files) &nbsp;&mdash;&nbsp; - [**`w-server-sent-events`**](w-server-sent-events#files) &nbsp;&mdash;&nbsp;
[`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource), [`EventSource`](https://developer.mozilla.org/en-US/docs/Web/API/EventSource),
an older alternative to WebSockets. an older alternative to WebSockets.
- [**`w-template-stream`**](w-template-stream#folders-and-files) &nbsp;&mdash;&nbsp; sends - [**`w-template-stream`**](w-template-stream#files) &nbsp;&mdash;&nbsp; sends
templates asynchronously, one chunk at a time. templates asynchronously, one chunk at a time.
- [**`w-upload-stream`**](w-upload-stream#folders-and-files) &nbsp;&mdash;&nbsp; streams - [**`w-upload-stream`**](w-upload-stream#files) &nbsp;&mdash;&nbsp; streams
uploaded files. uploaded files.
- [**`w-stress-response`**](w-stress-response#folders-and-files) &nbsp;&mdash;&nbsp; - [**`w-stress-response`**](w-stress-response#files) &nbsp;&mdash;&nbsp;
benchmarks streaming very large responses. benchmarks streaming very large responses.
- [**`w-stress-websocket-send`**](w-stress-websocket-send#folders-and-files) - [**`w-stress-websocket-send`**](w-stress-websocket-send#files)
&nbsp;&mdash;&nbsp; benchmarks sending WebSocket messages quickly. &nbsp;&mdash;&nbsp; benchmarks sending WebSocket messages quickly.
- [**`w-multipart-dump`**](w-multipart-dump#folders-and-files) &nbsp;&mdash;&nbsp; echoes - [**`w-multipart-dump`**](w-multipart-dump#files) &nbsp;&mdash;&nbsp; echoes
`multipart/form-data` bodies for debugging. `multipart/form-data` bodies for debugging.
- [**`z-playground`**](z-playground#folders-and-files) &nbsp;&mdash;&nbsp; source code of - [**`z-playground`**](z-playground#files) &nbsp;&mdash;&nbsp; source code of
the Dream playground. the Dream playground.
<br> <br>
@ -169,7 +167,7 @@ Ideas:
Basics: Basics:
- `w-content-negotiation` - `w-content-negotiation`
- [**`w-query`**](w-query#folders-and-files) &nbsp;&mdash;&nbsp; done. - [**`w-query`**](w-query#files) &nbsp;&mdash;&nbsp; done.
- `w-scope` &nbsp;&mdash;&nbsp; for - `w-scope` &nbsp;&mdash;&nbsp; for
[`Dream.scope`](https://aantron.github.io/dream/#val-scope). [`Dream.scope`](https://aantron.github.io/dream/#val-scope).
- `w-subsite` &nbsp;&mdash;&nbsp; for - `w-subsite` &nbsp;&mdash;&nbsp; for

View File

@ -76,9 +76,9 @@ let () =
**Next steps:** **Next steps:**
- [**`b-session`**](../b-session#folders-and-files) returns Web development proper with - [**`b-session`**](../b-session#files) returns Web development proper with
session management. session management.
- [**`c-cookie`**](../c-cookie#folders-and-files) shows cookie handling in Dream. - [**`c-cookie`**](../c-cookie#files) shows cookie handling in Dream.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -68,7 +68,7 @@ There are two other session back ends, which are persistent:
using a different random encryption key each time it starts. using a different random encryption key each time it starts.
- [`Dream.sql_sessions`](https://aantron.github.io/dream/#val-sql_sessions) - [`Dream.sql_sessions`](https://aantron.github.io/dream/#val-sql_sessions)
stores sessions in a database. It is shown in example stores sessions in a database. It is shown in example
[**`h-sql`**](../h-sql#folders-and-files). [**`h-sql`**](../h-sql#files).
<br> <br>
@ -90,7 +90,7 @@ new session will, again, be an empty pre-session.
It is best to use HTTPS when using sessions, to prevent session cookies from It is best to use HTTPS when using sessions, to prevent session cookies from
being easily observed by third parties. See being easily observed by third parties. See
[`Dream.run`](https://aantron.github.io/dream/#val-run) argument `~https`, and [`Dream.run`](https://aantron.github.io/dream/#val-run) argument `~https`, and
example [**`l-https`**](../l-https#folders-and-files). If you redirect from HTTP to HTTPS, example [**`l-https`**](../l-https#files). If you redirect from HTTP to HTTPS,
do not issue sessions for HTTP requests. If you do, don't accept them later do not issue sessions for HTTP requests. If you do, don't accept them later
from HTTPS requests. from HTTPS requests.
@ -100,8 +100,8 @@ from HTTPS requests.
**Next steps:** **Next steps:**
- Sessions already use cookies internally, but in - Sessions already use cookies internally, but in
[**`c-cookie`**](../c-cookie#folders-and-files) we set cookies for our own purposes! [**`c-cookie`**](../c-cookie#files) we set cookies for our own purposes!
- [**`d-form`**](../d-form#folders-and-files) builds secure forms on top of sessions. - [**`d-form`**](../d-form#files) builds secure forms on top of sessions.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -96,9 +96,9 @@ The easiest way to do that for general data is to use
**Next steps:** **Next steps:**
- [**`d-form`**](../d-form#folders-and-files) builds secure forms on top of sessions, and - [**`d-form`**](../d-form#files) builds secure forms on top of sessions, and
introduces automatic handling of CSRF tokens. introduces automatic handling of CSRF tokens.
- [**`e-json`**](../e-json#folders-and-files) sends and receives JSON instead! - [**`e-json`**](../e-json#files) sends and receives JSON instead!
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -2,7 +2,7 @@
<br> <br>
With the session middleware from example [**`b-session`**](../b-session#folders-and-files), With the session middleware from example [**`b-session`**](../b-session#files),
we can build a [secure form](https://aantron.github.io/dream/#forms): we can build a [secure form](https://aantron.github.io/dream/#forms):
```ocaml ```ocaml
@ -100,14 +100,14 @@ important on login forms and other sensitive pages.
However, this server is so simple that it doesn't store the data anywhere, and However, this server is so simple that it doesn't store the data anywhere, and
the data is not sensitive, so we took a shortcut. See the data is not sensitive, so we took a shortcut. See
[**`h-sql`**](../h-sql#folders-and-files) for an example with a proper redirection. [**`h-sql`**](../h-sql#files) for an example with a proper redirection.
<br> <br>
**Next steps:** **Next steps:**
- [**`e-json`**](../e-json#folders-and-files) receives and sends JSON. - [**`e-json`**](../e-json#files) receives and sends JSON.
- [**`f-static`**](../f-static#folders-and-files) serves static files from a local - [**`f-static`**](../f-static#files) serves static files from a local
directory. directory.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -49,7 +49,7 @@ To get this working, we have to add `ppx_yojson_conv` to our
</code></pre> </code></pre>
and to and to
[`json.opam`](https://github.com/aantron/dream/blob/master/example/e-json/e-json.opam): [`json.opam`](https://github.com/aantron/dream/blob/master/example/e-json/json.opam):
<pre><code>depends: [ <pre><code>depends: [
"ocaml" {>= "4.08.0"} "ocaml" {>= "4.08.0"}
@ -112,9 +112,9 @@ requests!
**Next steps:** **Next steps:**
- [**`f-static`**](../f-static#folders-and-files) serves static files from the local - [**`f-static`**](../f-static#files) serves static files from the local
file system. file system.
- [**`g-upload`**](../g-upload#folders-and-files) receives files from an upload form. - [**`g-upload`**](../g-upload#files) receives files from an upload form.
<br> <br>

View File

@ -6,10 +6,3 @@ depends: [
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
"ppx_yojson_conv" "ppx_yojson_conv"
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -56,7 +56,7 @@ You can replace the file loading behavior of
[crunch](https://github.com/mirage/ocaml-crunch) to compile a directory right [crunch](https://github.com/mirage/ocaml-crunch) to compile a directory right
into your Web app binary, and then serve that directory from memory with into your Web app binary, and then serve that directory from memory with
[`Dream.static`](https://aantron.github.io/dream/#val-static)! See example [`Dream.static`](https://aantron.github.io/dream/#val-static)! See example
[**`w-one-binary`**](../w-one-binary#folders-and-files). [**`w-one-binary`**](../w-one-binary#files).
You can also use `~loader` to set arbitrary headers on the response. You can also use `~loader` to set arbitrary headers on the response.
@ -64,9 +64,9 @@ You can also use `~loader` to set arbitrary headers on the response.
**Next steps:** **Next steps:**
- [**`g-upload`**](../g-upload#folders-and-files) receives files instead of serving them. - [**`g-upload`**](../g-upload#files) receives files instead of serving them.
- [**`h-sql`**](../h-sql#folders-and-files) runs SQL queries against a database. - [**`h-sql`**](../h-sql#files) runs SQL queries against a database.
- [**`w-one-binary`**](../w-one-binary#folders-and-files) bundles assets into a - [**`w-one-binary`**](../w-one-binary#files) bundles assets into a
self-contained binary. self-contained binary.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -74,7 +74,7 @@ However, this is only good for rare, small uploads, such as user avatars, or for
prototyping. prototyping.
For more heavy usage, see For more heavy usage, see
[`Dream.upload`](https://aantron.github.io/dream/#val-upload) for [`Dream.upload`](https://aantron.github.io/dream/#type-upload_event) for
streaming file uploads. streaming file uploads.
<br> <br>
@ -84,7 +84,7 @@ streaming file uploads.
[`Dream.multipart`](https://aantron.github.io/dream/#val-multipart) behaves just [`Dream.multipart`](https://aantron.github.io/dream/#val-multipart) behaves just
like [`Dream.form`](https://aantron.github.io/dream/#val-form) when it comes to like [`Dream.form`](https://aantron.github.io/dream/#val-form) when it comes to
[CSRF protection](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html). [CSRF protection](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html).
See example [**`d-form`**](../d-form#folders-and-files). We use See example [**`d-form`**](../d-form#files). We use
[`Dream.csrf_tag`](https://aantron.github.io/dream/#val-csrf_tag) to generate [`Dream.csrf_tag`](https://aantron.github.io/dream/#val-csrf_tag) to generate
the CSRF token in the template, and pass the `enctype="multipart/form-data"` the CSRF token in the template, and pass the `enctype="multipart/form-data"`
attribute as needed for forms to upload files. The template output looks like attribute as needed for forms to upload files. The template output looks like
@ -109,17 +109,17 @@ for a checklist of additional security precautions.
**Next steps:** **Next steps:**
- [**`h-sql`**](../h-sql#folders-and-files) runs SQL queries against a database. - [**`h-sql`**](../h-sql#files) runs SQL queries against a database.
- [**`i-graphql`**](../i-graphql#folders-and-files) handles GraphQL queries and serves - [**`i-graphql`**](../i-graphql#files) handles GraphQL queries and serves
GraphiQL. GraphiQL.
<br> <br>
**See also:** **See also:**
- [**`w-upload-stream`**](../w-upload-stream#folders-and-files) shows the streaming - [**`w-upload-stream`**](../w-upload-stream#files) shows the streaming
interface for receiving file uploads. interface for receiving file uploads.
- [**`w-multipart-dump`**](../w-multipart-dump#folders-and-files) shows the request body - [**`w-multipart-dump`**](../w-multipart-dump#files) shows the request body
that is interpreted by that is interpreted by
[`Dream.multipart`](https://aantron.github.io/dream/#val-multipart). [`Dream.multipart`](https://aantron.github.io/dream/#val-multipart).

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -14,7 +14,7 @@ module T = Caqti_type
let list_comments = let list_comments =
let query = let query =
let open Caqti_request.Infix in let open Caqti_request.Infix in
(T.unit ->* T.(t2 int string)) (T.unit ->* T.(tup2 int string))
"SELECT id, text FROM comment" in "SELECT id, text FROM comment" in
fun (module Db : DB) -> fun (module Db : DB) ->
let%lwt comments_or_error = Db.collect_list query () in let%lwt comments_or_error = Db.collect_list query () in
@ -82,7 +82,7 @@ comments!
We take the opportunity to try out We take the opportunity to try out
[`Dream.sql_sessions`](https://aantron.github.io/dream/#val-sql_sessions), which [`Dream.sql_sessions`](https://aantron.github.io/dream/#val-sql_sessions), which
stores session data persistently in `db.sqlite`. See example stores session data persistently in `db.sqlite`. See example
[**`b-session`**](../b-session#folders-and-files) for an introduction to session management. [**`b-session`**](../b-session#files) for an introduction to session management.
Both the comments and the sessions survive server restarts. Both the comments and the sessions survive server restarts.
<br> <br>
@ -132,7 +132,7 @@ We also had to make an addition to our
SQLite is good for small-to-medium sites and examples. For a larger site, SQLite is good for small-to-medium sites and examples. For a larger site,
microservices, or other needs, you can switch, for example, to PostgreSQL. See microservices, or other needs, you can switch, for example, to PostgreSQL. See
[**`w-postgres`**](../w-postgres#folders-and-files). [**`w-postgres`**](../w-postgres#files).
A good program for examining databases locally is A good program for examining databases locally is
[Beekeeper Studio](https://www.beekeeperstudio.io/). Dream might also integrate [Beekeeper Studio](https://www.beekeeperstudio.io/). Dream might also integrate
@ -156,9 +156,9 @@ See
**Next steps:** **Next steps:**
- [**`i-graphql`**](../i-graphql#folders-and-files) handles GraphQL queries and serves - [**`i-graphql`**](../i-graphql#files) handles GraphQL queries and serves
GraphiQL. GraphiQL.
- [**`j-stream`**](../j-stream#folders-and-files) streams response bodies to clients. - [**`j-stream`**](../j-stream#files) streams response bodies to clients.
<br> <br>

View File

@ -6,10 +6,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -89,17 +89,17 @@ GraphiQL conditionally, only during development.
**Next steps:** **Next steps:**
- [**`j-stream`**](../j-stream#folders-and-files) streams response bodies to clients. - [**`j-stream`**](../j-stream#files) streams response bodies to clients.
- [**`k-websocket`**](../k-websocket#folders-and-files) sends and receives messages over a - [**`k-websocket`**](../k-websocket#files) sends and receives messages over a
WebSocket. WebSocket.
<br> <br>
**See also:** **See also:**
- [**`r-graphql`**](../r-graphql#folders-and-files) is a version of this example in Reason - [**`r-graphql`**](../r-graphql#files) is a version of this example in Reason
syntax. syntax.
- [**`w-graphql-subscription`**](../w-graphql-subscription#folders-and-files) for GraphQL - [**`w-graphql-subscription`**](../w-graphql-subscription#files) for GraphQL
subscriptions. subscriptions.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -2,7 +2,7 @@
<br> <br>
In example [**`6-echo`**](../6-echo#folders-and-files), we echoed `POST` requests by reading In example [**`6-echo`**](../6-echo#files), we echoed `POST` requests by reading
their whole bodies into memory, and then writing them. Here, we echo request their whole bodies into memory, and then writing them. Here, we echo request
bodies chunk by chunk: bodies chunk by chunk:
@ -60,9 +60,9 @@ See [*Streams*](https://aantron.github.io/dream/#streams) in the API docs.
**Next steps:** **Next steps:**
- [**`k-websocket`**](../k-websocket#folders-and-files) sends and receives messages over a - [**`k-websocket`**](../k-websocket#files) sends and receives messages over a
WebSocket. WebSocket.
- [**`l-https`**](../l-https#folders-and-files) enables HTTPS, which is very easy with - [**`l-https`**](../l-https#files) enables HTTPS, which is very easy with
Dream. Dream.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -78,14 +78,14 @@ See [*WebSockets*](https://aantron.github.io/dream/#websockets) in the API docs.
**Last step:** **Last step:**
- [**`l-https`**](../l-https#folders-and-files) enables HTTPS. - [**`l-https`**](../l-https#files) enables HTTPS.
<br> <br>
**See also:** **See also:**
- [**`w-chat`**](../w-chat#folders-and-files) is a simple WebSocket-based chat application. - [**`w-chat`**](../w-chat#files) is a simple WebSocket-based chat application.
- [**`w-live-reload`**](../w-live-reload#folders-and-files) uses WebSockets to implement - [**`w-live-reload`**](../w-live-reload#files) uses WebSockets to implement
live reloading. live reloading.
- [**`w-graphql-subscription`**](../w-graphql-subscription) does not show a - [**`w-graphql-subscription`**](../w-graphql-subscription) does not show a
WebSocket directly, but shows GraphQL subscriptions, which are implemented WebSocket directly, but shows GraphQL subscriptions, which are implemented

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -42,7 +42,7 @@ cd $DIRECTORY
echo echo
echo -e "\e[0m✅ Fetching example files using git\e[0m" echo -e "\e[0m✅ Fetching example files using git\e[0m"
echo -e "\e[0m Source: $REPO/tree/$REF/example/$EXAMPLE#folders-and-files\e[0m" echo -e "\e[0m Source: $REPO/tree/$REF/example/$EXAMPLE#files\e[0m"
mkdir clone mkdir clone
cd clone cd clone
git init --quiet git init --quiet
@ -81,7 +81,7 @@ echo " dune exec ./$EXE --watch"
echo echo
echo -e "\e[0m✅ See\e[0m" echo -e "\e[0m✅ See\e[0m"
echo echo
echo " - This example:" $REPO/tree/$REF/example/$EXAMPLE#folders-and-files echo " - This example:" $REPO/tree/$REF/example/$EXAMPLE#files
echo " - Tutorial: " $REPO/tree/$REF/example#tutorial echo " - Tutorial: " $REPO/tree/$REF/example#tutorial
echo echo
echo 💲 dune exec ./$EXE echo 💲 dune exec ./$EXE

View File

@ -87,12 +87,12 @@ example in OCaml syntax.
**See also:** **See also:**
- [**`w-watch`**](../w-fswatch#folders-and-files) sets up a development watcher. - [**`w-watch`**](../w-fswatch#files) sets up a development watcher.
- [**`w-one-binary`**](../w-one-binary#folders-and-files) bundles assets into a - [**`w-one-binary`**](../w-one-binary#files) bundles assets into a
self-contained binary. self-contained binary.
- [**`7-template`**](../7-template#folders-and-files) discusses the templater, including - [**`7-template`**](../7-template#files) discusses the templater, including
security. The example is in OCaml syntax. security. The example is in OCaml syntax.
- [**`r-template`**](../r-template#folders-and-files) the code of the template example in - [**`r-template`**](../r-template#files) the code of the template example in
Reason syntax. Reason syntax.
<br> <br>

View File

@ -8,10 +8,3 @@ depends: [
"melange-webapi" "melange-webapi"
"reason" {>= "3.10.0"} "reason" {>= "3.10.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -83,9 +83,9 @@ the schema:
**See also:** **See also:**
- [**`i-graphql`**](../i-graphql#folders-and-files), the OCaml version of this example, for - [**`i-graphql`**](../i-graphql#files), the OCaml version of this example, for
some more discussion. some more discussion.
- [**`w-graphql-subscription`**](../w-graphql-subscription#folders-and-files) for GraphQL - [**`w-graphql-subscription`**](../w-graphql-subscription#files) for GraphQL
subscriptions. subscriptions.
<br> <br>

View File

@ -37,7 +37,7 @@ Note that we had to make an addition to
**See also:** **See also:**
- [**`r-template`**](../r-template#folders-and-files) shows templates with Reason syntax. - [**`r-template`**](../r-template#files) shows templates with Reason syntax.
- [**`2-middleware`**](../2-middleware) introduces the *logger*, the most - [**`2-middleware`**](../2-middleware) introduces the *logger*, the most
commonly used Dream middleware. The example is in OCaml syntax. commonly used Dream middleware. The example is in OCaml syntax.

View File

@ -3,7 +3,7 @@
<br> <br>
This example splits the code of the basic template example, This example splits the code of the basic template example,
[**`r-template`**](../r-template#folders-and-files), into two files. The first is the [**`r-template`**](../r-template#files), into two files. The first is the
template, in template, in
[`template.eml.html`](https://github.com/aantron/dream/blob/master/example/r-template-files/template.eml.html). We use the `.html` extension because it is [`template.eml.html`](https://github.com/aantron/dream/blob/master/example/r-template-files/template.eml.html). We use the `.html` extension because it is
mostly HTML, and to prevent `refmt` from trying to format the file: mostly HTML, and to prevent `refmt` from trying to format the file:
@ -57,8 +57,8 @@ file:
**See also:** **See also:**
- [**`r-template`**](../r-template#folders-and-files) for the one-file version. - [**`r-template`**](../r-template#files) for the one-file version.
- [**`7-template`**](../7-template#folders-and-files) for comments on [security - [**`7-template`**](../7-template#files) for comments on [security
information](../7-template#security). information](../7-template#security).
- [**`w-template-files`**](../w-template-files) for the OCaml version of this - [**`w-template-files`**](../w-template-files) for the OCaml version of this
example. example.

View File

@ -74,8 +74,8 @@ let () =
**See also:** **See also:**
- [**`7-template`**](../7-template#folders-and-files) for basic information about templates. - [**`7-template`**](../7-template#files) for basic information about templates.
- [**`w-template-logic`**](../w-template-logic#folders-and-files) for the OCaml version - [**`w-template-logic`**](../w-template-logic#files) for the OCaml version
of this example. of this example.
<br> <br>

View File

@ -49,7 +49,7 @@ The important differences with regular usage of templates are:
name `response`. name `response`.
- We use the promise library [Lwt](https://github.com/ocsigen/lwt) inside the - We use the promise library [Lwt](https://github.com/ocsigen/lwt) inside the
template for asynchronous control flow. See example template for asynchronous control flow. See example
[**`5-promise`**](../5-promise#folders-and-files) for an introduction to Lwt. [**`5-promise`**](../5-promise#files) for an introduction to Lwt.
The call to [`Dream.flush`](https://aantron.github.io/dream/#val-flush) isn't The call to [`Dream.flush`](https://aantron.github.io/dream/#val-flush) isn't
necessary in most real-world cases &mdash; Dream's HTTP layer automatically necessary in most real-world cases &mdash; Dream's HTTP layer automatically
@ -60,11 +60,11 @@ interactive, so we force writing of all output after generating each `<p>` tag.
**See also:** **See also:**
- [**`r-template`**](../r-template#folders-and-files) for the simpler way to do templates, - [**`r-template`**](../r-template#files) for the simpler way to do templates,
building up entire bodies as strings. building up entire bodies as strings.
- [**`7-template`**](../7-template#security) section *Security* for XSS - [**`7-template`**](../7-template#security) section *Security* for XSS
prevention considerations. prevention considerations.
- [**`w-template-stream`**](../w-template-stream#folders-and-files) is the OCaml version of - [**`w-template-stream`**](../w-template-stream#files) is the OCaml version of
this example. this example.
<br> <br>

View File

@ -59,11 +59,11 @@ same.
**See also:** **See also:**
- [**`r-template-files`**](../r-template-files#folders-and-files) puts the template into a - [**`r-template-files`**](../r-template-files#files) puts the template into a
separate `.eml.html` file, which can help with editor problems. separate `.eml.html` file, which can help with editor problems.
- [**`r-template-stream`**](../r-template-stream#folders-and-files) streams a template to a - [**`r-template-stream`**](../r-template-stream#files) streams a template to a
response. response.
- [**`9-error`**](../9-error#folders-and-files) sets up a central error template. The - [**`9-error`**](../9-error#files) sets up a central error template. The
example is in OCaml syntax. example is in OCaml syntax.
<br> <br>

View File

@ -76,7 +76,7 @@ Error: Unbound value html
**See also:** **See also:**
- [**`w-tyxml`**](../w-tyxml#folders-and-files) for an introduction to TyXML. - [**`w-tyxml`**](../w-tyxml#files) for an introduction to TyXML.
- [**`7-template`**](../7-template#security) section *Security* on output - [**`7-template`**](../7-template#security) section *Security* on output
security. TyXML escapes strings by default, just as the built-in templater security. TyXML escapes strings by default, just as the built-in templater
does. does.

View File

@ -45,7 +45,7 @@ scheme, rather than `ws://`, on the client.
**See also:** **See also:**
- [**k-websocket**](../k-websocket#folders-and-files) for an introduction to WebSockets. - [**k-websocket**](../k-websocket#files) for an introduction to WebSockets.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -1,67 +0,0 @@
# `w-dream-html`
<br>
[Dream-html](https://github.com/yawaramin/dream-html) can be used with Dream for
generating HTML. Dream-html is a library that offers functions for generating
HTML, SVG, and MathML, as well as out-of-the-box support for
[htmx](https://htmx.org/) attributes. It is closely integrated with Dream for
convenience.
```ocaml
let greet who =
let open Dream_html in
let open HTML in
html [lang "en"] [
head [] [
title [] "Greeting";
];
comment "Embedded in the HTML";
body [] [
h1 [] [txt "Good morning, %s!" who];
];
]
let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.get "/"
(fun _ -> Dream_html.respond (greet "world"));
]
```
<pre><code><b>$ cd example/w-dream-html</b>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./main.exe</b></code></pre>
Try it in the [playground](https://dream.as/w-dream-html).
Some notes:
- All text nodes and attributes are HTML-escaped by default for security, with
exceptions noted in the documentation
- All text nodes and attributes accept format strings for conveniently embedding
variables in the HTML
- Functions like `Dream_html.respond`, `Dream_html.send`, `Dream_html.csrf_tag`
provide convenient integration with Dream
- The `<!DOCTYPE html>` prefix is automatically rendered before the `<html>` tag
- The `SVG` and `MathML` modules provide their corresponding markup. The `Hx`
module provides htmx attributes.
<br>
<br>
**See also:**
- [**`7-template`**](../7-template#security) section *Security* on output
security. Dream-html escapes strings by default, just as the built-in templater
does.
- [**`w-tyxml`**](../w-tyxml#folders-and-files) is a similar library that also generates
HTML, with different design tradeoffs.
<br>
[Up to the example index](../#examples)

View File

@ -1,3 +0,0 @@
(executable
(name html)
(libraries dream-html))

View File

@ -1 +0,0 @@
(lang dune 2.0)

View File

@ -1,23 +0,0 @@
let greet who =
let open Dream_html in
let open HTML in
html [lang "en"] [
head [] [
title [] "Greeting";
];
comment "Embedded in the HTML";
body [] [
h1 [] [txt "Good morning, %s!" who];
];
]
let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.get "/"
(fun _ -> Dream_html.respond (greet "world"));
]

View File

@ -1,14 +0,0 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"dream-html" {>= "3.3.1"}
"dune" {>= "2.0.0"}
]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -55,7 +55,7 @@ You can then use the `esy` command without the `npx` prefix.
If you need to run multiple build steps before `dune exec`, use If you need to run multiple build steps before `dune exec`, use
[`esy.build`](https://esy.sh/docs/en/configuration.html#esybuild). Here is an [`esy.build`](https://esy.sh/docs/en/configuration.html#esybuild). Here is an
example from [**`w-fullstack-jsoo`**](../w-fullstack-jsoo#folders-and-files): example from [**`w-fullstack-jsoo`**](../w-fullstack-jsoo#files):
```json ```json
"esy": { "esy": {
@ -124,12 +124,12 @@ See the examples linked below.
**See also:** **See also:**
- [**`w-fullstack-rescript`**](../w-fullstack-rescript#folders-and-files) for full-stack - [**`w-fullstack-rescript`**](../w-fullstack-rescript#files) for full-stack
development with ReScript. development with ReScript.
- [**`r-fullstack-melange`**](../r-fullstack-melange#folders-and-files) for full-stack - [**`r-fullstack-melange`**](../r-fullstack-melange#files) for full-stack
development with Melange and Reason syntax. development with Melange and Reason syntax.
- [**`w-fswatch`**](../w-fswatch#folders-and-files) for a development watcher. - [**`w-fswatch`**](../w-fswatch#files) for a development watcher.
- [**`w-one-binary`**](../w-one-binary#folders-and-files) for bundling assets into a - [**`w-one-binary`**](../w-one-binary#files) for bundling assets into a
self-contained binary. self-contained binary.
<br> <br>

View File

@ -107,7 +107,7 @@ blows up their original size by 4/3.
**See also:** **See also:**
- [**`c-cookie`**](../c-cookie#folders-and-files) shows cookie handling, the mechanism that - [**`c-cookie`**](../c-cookie#files) shows cookie handling, the mechanism that
flash messages are implemented over. flash messages are implemented over.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -70,7 +70,7 @@ Then visit [http://localhost:8080](http://localhost:8080), and you will see...
**See also:** **See also:**
- [**`w-one-binary`**](../w-one-binary#folders-and-files) for bundling assets into a - [**`w-one-binary`**](../w-one-binary#files) for bundling assets into a
self-contained binary. self-contained binary.
<br> <br>

View File

@ -7,10 +7,3 @@ depends: [
"js_of_ocaml" "js_of_ocaml"
"js_of_ocaml-ppx" "js_of_ocaml-ppx"
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -85,12 +85,12 @@ client in `./static/client.js`. The example serves the bundled client using
**See also:** **See also:**
- [**`w-esy`**](../w-esy#folders-and-files) details the server's [esy](https://esy.sh/) - [**`w-esy`**](../w-esy#files) details the server's [esy](https://esy.sh/)
packaging. packaging.
- [**`w-fswatch`**](../w-fswatch#folders-and-files) sets up a primitive development watcher. - [**`w-fswatch`**](../w-fswatch#files) sets up a primitive development watcher.
- [**`w-one-binary`**](../w-one-binary#folders-and-files) bundles assets into a - [**`w-one-binary`**](../w-one-binary#files) bundles assets into a
self-contained binary. self-contained binary.
- [**`f-static`**](../r-hello#folders-and-files) presents - [**`f-static`**](../r-hello#files) presents
[`Dream.static`](https://aantron.github.io/dream/#val-static). [`Dream.static`](https://aantron.github.io/dream/#val-static).
<br> <br>

View File

@ -79,8 +79,8 @@ similar.
**See also:** **See also:**
- [**`i-graphql`**](../i-graphql#folders-and-files) for a basic GraphQL example. - [**`i-graphql`**](../i-graphql#files) for a basic GraphQL example.
- [**`k-websocket`**](../k-websocket#folders-and-files) for direct WebSocket usage. - [**`k-websocket`**](../k-websocket#files) for direct WebSocket usage.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -50,7 +50,7 @@ Good morning, world! Random tag: jRak
<br> <br>
This example plays very well with [**`w-watch`**](../w-watch#folders-and-files), which shows This example plays very well with [**`w-watch`**](../w-watch#files), which shows
how to rebuild and restart a development server every time sources are modified how to rebuild and restart a development server every time sources are modified
in the file system. Combining the two examples, it is possible to propagate in the file system. Combining the two examples, it is possible to propagate
reloading all the way to the client, whenever any of the server's source code reloading all the way to the client, whenever any of the server's source code
@ -60,8 +60,8 @@ changes.
**See also:** **See also:**
- [**`k-websocket`**](../k-websocket#folders-and-files) introduces WebSockets. - [**`k-websocket`**](../k-websocket#files) introduces WebSockets.
- [**`w-watch`**](../w-watch#folders-and-files) rebuilds and restarts a server each - [**`w-watch`**](../w-watch#files) rebuilds and restarts a server each
time its source code changes. time its source code changes.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -3,7 +3,7 @@
<br> <br>
*Long polling* is a technique, largely made obsolete by *Long polling* is a technique, largely made obsolete by
[WebSockets](../k-websocket#folders-and-files), where a client sends a request, but the [WebSockets](../k-websocket#files), where a client sends a request, but the
server does not respond until some data is available. This delayed response server does not respond until some data is available. This delayed response
works as a sort of “push” from the client's point of view, because it comes at works as a sort of “push” from the client's point of view, because it comes at
a time of the server's choosing. a time of the server's choosing.
@ -46,7 +46,7 @@ polling.”
**See also:** **See also:**
- [**`k-websocket`**](../k-websocket#folders-and-files) for a more modern way of achieving - [**`k-websocket`**](../k-websocket#files) for a more modern way of achieving
asynchronous client-server communication. asynchronous client-server communication.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -45,7 +45,7 @@ end
<br> <br>
It's the basic example [**`2-middleware`**](../2-middleware#folders-and-files) adapted to It's the basic example [**`2-middleware`**](../2-middleware#files) adapted to
Mirage. To build and run, do Mirage. To build and run, do
<pre><code><b>$ cd example/w-mirage</b> <pre><code><b>$ cd example/w-mirage</b>

View File

@ -1,35 +0,0 @@
# `w-mlx`
<br>
[mlx](https://github.com/ocaml-mlx/mlx), an OCaml syntax dialect which adds JSX
expressions, can be used with Dream for generating HTML.
```ocaml
let greet ~who () =
<html>
<head>
<title>"Greeting"</title>
</head>
<body>
<h1>"Good morning, " (JSX.string who) "!"</h1>
</body>
</html>
let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.get "/" (fun _ ->
let html = JSX.render <greet who="world" /> in
Dream.html html)
]
```
<pre><code><b>$ cd example/w-mlx</b>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./mlx.exe</b></code></pre>
<br>
[Up to the example index](../#examples)

View File

@ -1,4 +0,0 @@
(executable
(name mlx)
(libraries dream html_of_jsx)
(preprocess (pps html_of_jsx.ppx)))

View File

@ -1,10 +0,0 @@
(lang dune 3.16)
(dialect
(name mlx)
(implementation
(merlin_reader mlx)
(extension mlx)
(preprocess
(run mlx-pp %{input-file}))))

View File

@ -1,18 +0,0 @@
let greet ~who () =
<html>
<head>
<title>"Greeting"</title>
</head>
<body>
<h1>"Good morning, " (JSX.string who) "!"</h1>
</body>
</html>
let () =
Dream.run
@@ Dream.logger
@@ Dream.router [
Dream.get "/" (fun _ ->
let html = JSX.render <greet who="world" /> in
Dream.html html)
]

View File

@ -1,16 +0,0 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"dream"
"dune" {>= "3.16.0"}
"mlx"
"html_of_jsx"
]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -55,8 +55,8 @@ curl -F 'a=b' http://localhost:8080/
**See also:** **See also:**
- [**`g-upload`**](../g-upload#folders-and-files) is the proper file upload example. - [**`g-upload`**](../g-upload#files) is the proper file upload example.
- [**`6-echo`**](../6-echo#folders-and-files) is a proper echo example :) - [**`6-echo`**](../6-echo#files) is a proper echo example :)
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -150,11 +150,11 @@ docker-compose logs web -f
**See also:** **See also:**
- [**`f-static`**](../f-static#folders-and-files) has Dream serve static files on its own, - [**`f-static`**](../f-static#files) has Dream serve static files on its own,
without a reverse proxy. without a reverse proxy.
- [**`z-docker-esy`**](../z-docker-esy#folders-and-files) deploys to Digital Ocean with - [**`z-docker-esy`**](../z-docker-esy#files) deploys to Digital Ocean with
Docker Compose and esy, including Docker installation instructions. Docker Compose and esy, including Docker installation instructions.
- [**`z-docker-opam`**](../z-docker-opam#folders-and-files) deploys with Docker Compose and - [**`z-docker-opam`**](../z-docker-opam#files) deploys with Docker Compose and
opam. opam.
<br> <br>

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -111,10 +111,10 @@ To add more files, just add them to the `assets/` directory and re-run
**See also:** **See also:**
- [**`w-esy`**](../w-esy#folders-and-files) for details on packaging with esy. - [**`w-esy`**](../w-esy#files) for details on packaging with esy.
- [**`w-watch`**](../w-watch#folders-and-files) for a primitive watcher, which can be - [**`w-watch`**](../w-watch#files) for a primitive watcher, which can be
extended to watch `assets/`. extended to watch `assets/`.
- [**`f-static`**](../f-static#folders-and-files) shows the basics of - [**`f-static`**](../f-static#files) shows the basics of
[`Dream.static`](https://aantron.github.io/dream/#val-static). [`Dream.static`](https://aantron.github.io/dream/#val-static).
<br> <br>

View File

@ -6,10 +6,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -9,7 +9,7 @@ Web server with a PostgreSQL database.
The The
[code](https://github.com/aantron/dream/blob/master/example/w-postgres/postgres.eml.ml) [code](https://github.com/aantron/dream/blob/master/example/w-postgres/postgres.eml.ml)
is almost identical to [**`h-sql`**](../h-sql#folders-and-files). The only differences are: is almost identical to [**`h-sql`**](../h-sql#files). The only differences are:
- we now listen on `"0.0.0.0"`, since our client will definitely be outside the - we now listen on `"0.0.0.0"`, since our client will definitely be outside the
Docker container, so not on `localhost`, and Docker container, so not on `localhost`, and
@ -108,11 +108,11 @@ Tips:
**See also:** **See also:**
- [**`h-sql`**](../h-sql#folders-and-files) is the SQLite, non-Docker version of this - [**`h-sql`**](../h-sql#files) is the SQLite, non-Docker version of this
example. example.
- [**`z-docker-esy`**](../z-docker-esy#folders-and-files) deploys to Digital Ocean with - [**`z-docker-esy`**](../z-docker-esy#files) deploys to Digital Ocean with
Docker Compose and esy, including Docker installation instructions. Docker Compose and esy, including Docker installation instructions.
- [**`z-docker-opam`**](../z-docker-opam#folders-and-files) deploys with Docker Compose and - [**`z-docker-opam`**](../z-docker-opam#files) deploys with Docker Compose and
opam. opam.
<br> <br>

View File

@ -6,10 +6,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -42,9 +42,9 @@ interface to server-sent events.
**See also:** **See also:**
- [**`k-websocket`**](../k-websocket#folders-and-files) for WebSockets, which largely - [**`k-websocket`**](../k-websocket#files) for WebSockets, which largely
supersede server-sent events. supersede server-sent events.
- [**`w-template-stream`**](../w-template-stream#folders-and-files) for another example of - [**`w-template-stream`**](../w-template-stream#files) for another example of
“real-time” streaming with “real-time” streaming with
[`Dream.flush`](https://aantron.github.io/dream/#val-flush). [`Dream.flush`](https://aantron.github.io/dream/#val-flush).

View File

@ -5,10 +5,3 @@ depends: [
"dream" "dream"
"dune" {>= "2.0.0"} "dune" {>= "2.0.0"}
] ]
synopsis: "One of the Dream examples"
homepage: "https://github.com/aantron/dream"
bug-reports: "https://github.com/aantron/dream/issues"
author: "Anton Bachin <antonbachin@yahoo.com>"
license: "MIT"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

Some files were not shown because too many files have changed in this diff Show More