Compare commits

..

25 Commits

Author SHA1 Message Date
Anton Bachin
27ff43177b
Typo in README.md 2024-12-20 11:18:22 +03:00
Mostafa Touny
204a792b57
example/h-sql: tup2 is deprecated (#370) 2024-12-17 12:47:11 +03:00
asymmetric
da94944400
example/w-template-logic: explain % (#366) 2024-12-10 14:08:48 +03:00
Anton Bachin
ac92bc072e Module Dream assumes latest dream-httpaf 2024-12-01 20:24:14 +03:00
alxtuz
deb4526387
Replace all #files anchors by #folders-and-files (#361) 2024-11-04 21:47:42 +03:00
alxtuz
59ce312808
dream.mli: use #folders-and-files in example links (#360) 2024-11-01 17:43:55 +03:00
alxtuz
e4fa99812b
Docs: link to example/e-json from Dream.json (#359) 2024-11-01 11:59:45 +03:00
Anton Bachin
e94401a7d8
CI: try dune-cache (#353) 2024-10-25 08:13:50 +03:00
alxtuz
6c75fb9e22 CI: skip example/w-dream-html (#358)
w-dream-html depends on external package dream-html, which, in turn,
depends on package dream, which makes it awkward to install dream-html
inside Dream's CI. So skip this example.
2024-10-22 09:20:32 +03:00
alxtuz
186ab997d8 Fix opam lint in examples (#356)
Resolves #350.
2024-10-17 18:47:09 +03:00
Emmanuel Ferdman
b7b477379f
Update e-json.opam reference (#354)
Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
2024-10-15 11:23:58 +03:00
Anton Bachin
a888e44e88
Replace vendored httpaf with httpun (#351) 2024-10-14 20:00:57 +03:00
Yawar Amin
c8ec9d1af9
Add dream-html example (#323) 2024-10-14 19:59:53 +03:00
Andrey Popp
6a1a2f0db2
Examples: add w-mlx (#330) 2024-10-14 19:39:10 +03:00
Anton Bachin
91b470dcd8
CI: use Ubuntu 22.04 (#352)
See https://github.com/ocaml/setup-ocaml/issues/872
2024-10-14 19:24:27 +03:00
Anton Bachin
d088771512 Dream.run docs: remove mention of ~stop_on_input
It was removed in #46, but a dangling reference to it still remained.
Caught by Yawar Amin in

  https://github.com/aantron/dream/issues/46#issuecomment-1962267244
2024-09-09 19:01:14 +03:00
Anton Bachin
5858e47c92
Log fd numbers (#345) 2024-09-05 18:56:19 +03:00
Anton Bachin
3f556c89f0 Fix some whitespace 2024-09-05 13:26:31 +03:00
Anton Bachin
1bf9f992f8 Fix typo 2024-09-05 12:56:41 +03:00
Anton Bachin
e84720d2ee Adjust whitespace and disabled job 2024-09-04 00:58:59 +03:00
Max Große
d3cb68bf18
Fix CI (#337)
Fixes #338.
Incorporates and closes #335.

Co-authored-by: Anton Bachin <antonbachin@yahoo.com>
2024-09-04 00:54:04 +03:00
Max Große
f8958e71cf
Fix typo in .opam description (#343) 2024-09-03 10:09:25 +03:00
Max Große
2b13c3206a
Remove unused documentation (#342)
upload_event was removed from dream.mli in 018e8e273c5e01e24efefa8e2b2b5a9e4145c7a1
new_global was removed in d81b1986b67ccf8024deeb3d1c223452116fdb4d
2024-09-03 09:49:21 +03:00
Anton Bachin
d2656380b5 Bump version shown in the docs 2024-09-03 09:43:54 +03:00
Anton Bachin
5a7871f845 Add make release-clean target 2024-09-03 09:40:22 +03:00
141 changed files with 1073 additions and 816 deletions

View File

@ -7,101 +7,98 @@ jobs:
fail-fast: false
matrix:
os:
- ubuntu-latest
# Until https://github.com/ocaml/setup-ocaml/issues/872.
# When fixing, search for other instances of this string in this file.
- ubuntu-22.04
ocaml:
- 5.0.x
- 5.2.x
- 4.14.x
- 4.13.x
- 4.12.x
- 4.11.x
- 4.10.x
- 4.09.x
- 4.08.x
include:
- os: macos-latest
ocaml: 4.12.x
ocaml: 4.14.x
- os: windows-latest
ocaml: 4.14.x
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: avsm/setup-ocaml@v2
if: runner.os != 'Windows'
- uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: ${{matrix.ocaml}}
dune-cache: true
- uses: avsm/setup-ocaml@v2
# For Caqti PostgreSQL examples. opam does actually install PostgreSQL for
# 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'
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 depext --yes conf-sqlite3
- run: opam depext --yes conf-postgresql
- run: opam depext --yes conf-libev
- run: opam exec -- make deps
- run: opam exec -- make
# 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'
# 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
# makes testing on < 4.10 awkward. So, we skip tests on < 4.10.
- shell: bash
- run: opam lint --recursive example
- name: Build examples
if: runner.os != 'Windows'
run: |
set -e
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")
WITH_TEST=--with-test
case ${{matrix.ocaml}} in
4.09.x) WITH_TEST=;;
4.08.x) WITH_TEST=;;
esac
if [[ "$FILE" == "" ]]; then
continue
fi
# 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
$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')
echo dune build $EXE
$OPAM exec -- dune build $EXE
done
fi
EXE=$(echo $FILE | sed 's/\..*$/.exe/g')
echo dune build $EXE
opam exec -- dune build $EXE
done
quickstart:
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macos-latest
- ubuntu-22.04
ocaml:
- 5.2.x
- 4.14.x
include:
- os: macos-latest
ocaml: 4.14.x
runs-on: ${{matrix.os}}
steps:
- name: Quick start
- uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: ${{matrix.ocaml}}
dune-cache: true
- name: Run quickstart.sh
shell: bash
run: |
set -x
touch output
@ -117,25 +114,29 @@ jobs:
fi
mirage:
runs-on: ubuntu-latest
if: false
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
with:
submodules: recursive
- run: mkdir ../repo-copy
- run: cp -r * ../repo-copy/
- uses: avsm/setup-ocaml@v2
- uses: ocaml/setup-ocaml@v3
with:
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 mirage mirage-clock-unix
- run: opam install --yes mirage mirage-clock-unix mirage-crypto-rng-mirage
- 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 && opam exec -- mirage configure -t unix
- run: cd example/w-mirage && opam exec -- make depends
- run: cd example/w-mirage && ls duniverse
- 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
- 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 && 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 && mv dune.build.2 dune.build

16
.gitmodules vendored
View File

@ -1,16 +0,0 @@
[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,3 +165,7 @@ release-finish :
opam pin remove -y dream-pure dream-httpaf dream
sha256sum $(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
into.
[https]: https://github.com/aantron/dream/tree/master/example/l-https#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#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#files
[middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#files
[https]: https://github.com/aantron/dream/tree/master/example/l-https#folders-and-files
[websocket]: https://github.com/aantron/dream/tree/master/example/k-websocket#folders-and-files
[graphql]: https://github.com/aantron/dream/tree/master/example/w-graphql-subscription#folders-and-files
[templates]: https://github.com/aantron/dream/tree/master/example/7-template#folders-and-files
[reason-templates]: https://github.com/aantron/dream/tree/master/example/r-template#folders-and-files
[middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files
[handler]: https://aantron.github.io/dream/#type-handler
[routing]: https://github.com/aantron/dream/tree/master/example/3-router#files
[routing]: https://github.com/aantron/dream/tree/master/example/3-router#folders-and-files
[cookies]: https://aantron.github.io/dream/#cookies
[forms]: https://aantron.github.io/dream/#forms
[sessions]: https://github.com/aantron/dream/tree/master/example/b-session#files
[sessions]: https://github.com/aantron/dream/tree/master/example/b-session#folders-and-files
[back-ends]: https://aantron.github.io/dream/#back-ends
[errors]: https://github.com/aantron/dream/tree/master/example/9-error#files
[errors]: https://github.com/aantron/dream/tree/master/example/9-error#folders-and-files
[crypto]: https://aantron.github.io/dream/#cryptography
[logging]: https://github.com/aantron/dream/tree/master/example/2-middleware#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#files
[jsoo]: https://github.com/aantron/dream/tree/master/example/w-fullstack-jsoo#files
[logging]: https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files
[melange]: https://github.com/aantron/dream/tree/master/example/r-fullstack-melange#folders-and-files
[rescript]: https://github.com/aantron/dream/tree/master/example/w-fullstack-rescript#folders-and-files
[jsoo]: https://github.com/aantron/dream/tree/master/example/w-fullstack-jsoo#folders-and-files
[types]: https://aantron.github.io/dream/#types
[basic-read]: https://aantron.github.io/dream/#val-body
[streaming]: https://aantron.github.io/dream/#streaming
@ -102,15 +102,15 @@ into.
[alpn]: https://en.wikipedia.org/wiki/Application-Layer_Protocol_Negotiation
[libs]: https://github.com/aantron/dream/tree/master/src
[deploy]: https://github.com/aantron/dream/tree/master/example#deploying
[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#files
[jsx]: https://github.com/aantron/dream/tree/master/example/r-tyxml#folders-and-files
[one-binary]: https://github.com/aantron/dream/tree/master/example/w-one-binary#folders-and-files
<br>
## Quick start
You can get
[one](https://github.com/aantron/dream/tree/master/example/2-middleware#files)
[one](https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files)
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>
@ -139,10 +139,10 @@ After that, go to any of the [examples][tutorial], such as
dune exec ./middleware.exe
```
[esy-example]: https://github.com/aantron/dream/tree/master/example/w-esy#files
[esy-example]: https://github.com/aantron/dream/tree/master/example/w-esy#folders-and-files
[quickstart.sh]: https://github.com/aantron/dream/blob/master/example/quickstart.sh
[esy]: https://esy.sh/
[2-middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#files
[2-middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files
## esy
@ -173,14 +173,14 @@ esy`, and started with `npx esy start`.
[tutorial]: https://github.com/aantron/dream/tree/master/example#readme
[examples]: https://github.com/aantron/dream/tree/master/example#examples
[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#files
[1-hello]: https://github.com/aantron/dream/tree/master/example/1-hello#folders-and-files
[r-hello]: https://github.com/aantron/dream/tree/master/example/r-hello#folders-and-files
[reason-examples]: https://github.com/aantron/dream/tree/master/example#reason
[deploying]: https://github.com/aantron/dream/tree/master/example#deploying
[api-main]: https://aantron.github.io/dream/#types
[fullstack]: https://github.com/aantron/dream/tree/master/example#full-stack
[watch]: https://github.com/aantron/dream/tree/master/example/w-watch#files
[reload]: https://github.com/aantron/dream/tree/master/example/w-live-reload#files
[watch]: https://github.com/aantron/dream/tree/master/example/w-watch#folders-and-files
[reload]: https://github.com/aantron/dream/tree/master/example/w-live-reload#folders-and-files
<br>
@ -217,7 +217,7 @@ Apart from the [issues](https://github.com/aantron/dream/issues), good places
to discuss Dream are...
- #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 development stream on [Twitch](https://www.twitch.tv/antron_ML).

View File

@ -1140,46 +1140,6 @@ let part_replacement = {|
</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">
<a href="#type-csrf_result" class="anchor"></a><code><span><span class="keyword">type</span> csrf_result</span><span> = </span><span>[ </span></code>
<table>
@ -1697,18 +1657,6 @@ let new_field_replacement = {|
</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">
<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>

View File

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

View File

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

View File

@ -15,31 +15,18 @@ maintainer: "Anton Bachin <antonbachin@yahoo.com>"
depends: [
"dream-pure"
"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_ppx" {>= "1.2.2"}
"lwt_ssl"
"ocaml" {>= "4.08.0"}
"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: [

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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:**
- The next example, [**`2-middleware`**](../2-middleware#files), adds a logger
- The next example, [**`2-middleware`**](../2-middleware#folders-and-files), adds a logger
to the app.
- [**`3-router`**](../3-router#files) sends requests to different handlers,
- [**`3-router`**](../3-router#folders-and-files) sends requests to different handlers,
depending on their path.
<br>
**See also:**
- [**`r-hello`**](../r-hello#files) is a Reason syntax version of this example.
- [**`w-watch`**](../w-watch#files) sets up a development watcher.
- [**`r-hello`**](../r-hello#folders-and-files) is a Reason syntax version of this example.
- [**`w-watch`**](../w-watch#folders-and-files) sets up a development watcher.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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
bigger handlers that do a little bit more. This example takes the handler from
[**`1-hello`**](../1-hello#files) and wraps it in one of the most useful
[**`1-hello`**](../1-hello#folders-and-files) and wraps it in one of the most useful
middlewares, the [*logger*](https://aantron.github.io/dream/#val-logger):
```ocaml
@ -40,7 +40,7 @@ When you run this server and visit
You can write your own messages to the log using
[`Dream.log`](https://aantron.github.io/dream/#val-log). See example
[**`a-log`**](../a-log#files) for more logging options. Now that we have the
[**`a-log`**](../a-log#folders-and-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
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
from handlers to handlers, so you can create them anywhere. Example
[**`4-counter`**](../4-counter#files) already shows a simple custom middleware.
[**`4-counter`**](../4-counter#folders-and-files) already shows a simple custom middleware.
<!--
There are also more complicated middlewares defined in
- [**`m-locals`**](../m-locals/#files),
- [**`w-auto-reload`**](../w-auto-reload/#files), and
- [**`w-index-html`**](../w-index-html/#files).
- [**`m-locals`**](../m-locals#folders-and-files),
- [**`w-auto-reload`**](../w-auto-reload#folders-and-files), and
- [**`w-index-html`**](../w-index-html#folders-and-files).
-->
<!-- TODO Fill out this list; probably a-promise belongs here. -->
@ -64,10 +64,10 @@ There are also more complicated middlewares defined in
**Next steps:**
- The next example, [**`3-router`**](../3-router#files), shows
- The next example, [**`3-router`**](../3-router#folders-and-files), shows
[*routes*](https://aantron.github.io/dream/#routing), the other way to build
up handlers in Dream.
- [**`4-counter`**](../4-counter#files) builds the first custom middleware.
- [**`4-counter`**](../4-counter#folders-and-files) builds the first custom middleware.
<br>

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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
`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
used by Dream. The next example, [**`5-promise`**](../5-promise#files), does
used by Dream. The next example, [**`5-promise`**](../5-promise#folders-and-files), does
exactly that!
<br>
**Next steps:**
- [**`5-promise`**](../5-promise#files) shows a middleware that awaits
- [**`5-promise`**](../5-promise#folders-and-files) shows a middleware that awaits
responses using [Lwt](https://github.com/ocsigen/lwt).
- [**`6-echo`**](../6-echo#files) responds to `POST` requests and reads their
- [**`6-echo`**](../6-echo#folders-and-files) responds to `POST` requests and reads their
bodies.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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>
[**`4-counter`**](../4-counter#files) was limited to counting requests *before*
[**`4-counter`**](../4-counter#folders-and-files) was limited to counting requests *before*
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
*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:**
- [**`6-echo`**](../6-echo#files) uses Dream and Lwt to read a request body.
- [**`7-template`**](../7-template#files) shows how to interleave HTML and
- [**`6-echo`**](../6-echo#folders-and-files) uses Dream and Lwt to read a request body.
- [**`7-template`**](../7-template#folders-and-files) shows how to interleave HTML and
OCaml.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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
echo it, and there are several examples for that!
- [**`d-form`**](../d-form#files) parses request bodies as forms.
- [**`e-json`**](../e-json#files) parses bodies as JSON.
- [**`g-upload`**](../g-upload#files) receives file upload forms.
- [**`i-graphql`**](../i-graphql#files) receives GraphQL queries.
- [**`j-stream`**](../j-stream#files) streams huge bodies.
- [**`d-form`**](../d-form#folders-and-files) parses request bodies as forms.
- [**`e-json`**](../e-json#folders-and-files) parses bodies as JSON.
- [**`g-upload`**](../g-upload#folders-and-files) receives file upload forms.
- [**`i-graphql`**](../i-graphql#folders-and-files) receives GraphQL queries.
- [**`j-stream`**](../j-stream#folders-and-files) streams huge bodies.
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
@ -62,9 +62,9 @@ present them the right way.
**Next steps:**
- [**`7-template`**](../7-template#files) builds responses from templates and
- [**`7-template`**](../7-template#folders-and-files) builds responses from templates and
guards against injection attacks (XSS).
- [**`8-debug`**](../8-debug#files) renders error information in responses.
- [**`8-debug`**](../8-debug#folders-and-files) renders error information in responses.
<br>

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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
that you like &mdash; we will do this in the [very next
example](../9-error#files)!
example](../9-error#folders-and-files)!
<!-- TODO Fix after stack trace is fixed. -->
<!-- TODO Show the log -->
@ -104,9 +104,9 @@ example](../9-error#files)!
**Next steps:**
- [**`9-error`**](../9-error#files) handles all errors in one place, including
- [**`9-error`**](../9-error#folders-and-files) handles all errors in one place, including
displaying the debugger output.
- [**`a-log`**](../a-log#files) shows [log
- [**`a-log`**](../a-log#folders-and-files) shows [log
levels](https://aantron.github.io/dream/#type-log_level) and
[sub-logs](https://aantron.github.io/dream/#type-sub_log).

View File

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

View File

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

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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.
- [`Dream.sql_sessions`](https://aantron.github.io/dream/#val-sql_sessions)
stores sessions in a database. It is shown in example
[**`h-sql`**](../h-sql#files).
[**`h-sql`**](../h-sql#folders-and-files).
<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
being easily observed by third parties. See
[`Dream.run`](https://aantron.github.io/dream/#val-run) argument `~https`, and
example [**`l-https`**](../l-https#files). If you redirect from HTTP to HTTPS,
example [**`l-https`**](../l-https#folders-and-files). If you redirect from HTTP to HTTPS,
do not issue sessions for HTTP requests. If you do, don't accept them later
from HTTPS requests.
@ -100,8 +100,8 @@ from HTTPS requests.
**Next steps:**
- Sessions already use cookies internally, but in
[**`c-cookie`**](../c-cookie#files) we set cookies for our own purposes!
- [**`d-form`**](../d-form#files) builds secure forms on top of sessions.
[**`c-cookie`**](../c-cookie#folders-and-files) we set cookies for our own purposes!
- [**`d-form`**](../d-form#folders-and-files) builds secure forms on top of sessions.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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:**
- [**`d-form`**](../d-form#files) builds secure forms on top of sessions, and
- [**`d-form`**](../d-form#folders-and-files) builds secure forms on top of sessions, and
introduces automatic handling of CSRF tokens.
- [**`e-json`**](../e-json#files) sends and receives JSON instead!
- [**`e-json`**](../e-json#folders-and-files) sends and receives JSON instead!
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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>
With the session middleware from example [**`b-session`**](../b-session#files),
With the session middleware from example [**`b-session`**](../b-session#folders-and-files),
we can build a [secure form](https://aantron.github.io/dream/#forms):
```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
the data is not sensitive, so we took a shortcut. See
[**`h-sql`**](../h-sql#files) for an example with a proper redirection.
[**`h-sql`**](../h-sql#folders-and-files) for an example with a proper redirection.
<br>
**Next steps:**
- [**`e-json`**](../e-json#files) receives and sends JSON.
- [**`f-static`**](../f-static#files) serves static files from a local
- [**`e-json`**](../e-json#folders-and-files) receives and sends JSON.
- [**`f-static`**](../f-static#folders-and-files) serves static files from a local
directory.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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>
and to
[`json.opam`](https://github.com/aantron/dream/blob/master/example/e-json/json.opam):
[`json.opam`](https://github.com/aantron/dream/blob/master/example/e-json/e-json.opam):
<pre><code>depends: [
"ocaml" {>= "4.08.0"}
@ -112,9 +112,9 @@ requests!
**Next steps:**
- [**`f-static`**](../f-static#files) serves static files from the local
- [**`f-static`**](../f-static#folders-and-files) serves static files from the local
file system.
- [**`g-upload`**](../g-upload#files) receives files from an upload form.
- [**`g-upload`**](../g-upload#folders-and-files) receives files from an upload form.
<br>

View File

@ -6,3 +6,10 @@ depends: [
"dune" {>= "2.0.0"}
"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
into your Web app binary, and then serve that directory from memory with
[`Dream.static`](https://aantron.github.io/dream/#val-static)! See example
[**`w-one-binary`**](../w-one-binary#files).
[**`w-one-binary`**](../w-one-binary#folders-and-files).
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:**
- [**`g-upload`**](../g-upload#files) receives files instead of serving them.
- [**`h-sql`**](../h-sql#files) runs SQL queries against a database.
- [**`w-one-binary`**](../w-one-binary#files) bundles assets into a
- [**`g-upload`**](../g-upload#folders-and-files) receives files instead of serving them.
- [**`h-sql`**](../h-sql#folders-and-files) runs SQL queries against a database.
- [**`w-one-binary`**](../w-one-binary#folders-and-files) bundles assets into a
self-contained binary.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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.
For more heavy usage, see
[`Dream.upload`](https://aantron.github.io/dream/#type-upload_event) for
[`Dream.upload`](https://aantron.github.io/dream/#val-upload) for
streaming file uploads.
<br>
@ -84,7 +84,7 @@ streaming file uploads.
[`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
[CSRF protection](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html).
See example [**`d-form`**](../d-form#files). We use
See example [**`d-form`**](../d-form#folders-and-files). We use
[`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"`
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:**
- [**`h-sql`**](../h-sql#files) runs SQL queries against a database.
- [**`i-graphql`**](../i-graphql#files) handles GraphQL queries and serves
- [**`h-sql`**](../h-sql#folders-and-files) runs SQL queries against a database.
- [**`i-graphql`**](../i-graphql#folders-and-files) handles GraphQL queries and serves
GraphiQL.
<br>
**See also:**
- [**`w-upload-stream`**](../w-upload-stream#files) shows the streaming
- [**`w-upload-stream`**](../w-upload-stream#folders-and-files) shows the streaming
interface for receiving file uploads.
- [**`w-multipart-dump`**](../w-multipart-dump#files) shows the request body
- [**`w-multipart-dump`**](../w-multipart-dump#folders-and-files) shows the request body
that is interpreted by
[`Dream.multipart`](https://aantron.github.io/dream/#val-multipart).

View File

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

View File

@ -6,3 +6,10 @@ depends: [
"dream"
"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:**
- [**`j-stream`**](../j-stream#files) streams response bodies to clients.
- [**`k-websocket`**](../k-websocket#files) sends and receives messages over a
- [**`j-stream`**](../j-stream#folders-and-files) streams response bodies to clients.
- [**`k-websocket`**](../k-websocket#folders-and-files) sends and receives messages over a
WebSocket.
<br>
**See also:**
- [**`r-graphql`**](../r-graphql#files) is a version of this example in Reason
- [**`r-graphql`**](../r-graphql#folders-and-files) is a version of this example in Reason
syntax.
- [**`w-graphql-subscription`**](../w-graphql-subscription#files) for GraphQL
- [**`w-graphql-subscription`**](../w-graphql-subscription#folders-and-files) for GraphQL
subscriptions.
<br>

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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:**
- [**`l-https`**](../l-https#files) enables HTTPS.
- [**`l-https`**](../l-https#folders-and-files) enables HTTPS.
<br>
**See also:**
- [**`w-chat`**](../w-chat#files) is a simple WebSocket-based chat application.
- [**`w-live-reload`**](../w-live-reload#files) uses WebSockets to implement
- [**`w-chat`**](../w-chat#folders-and-files) is a simple WebSocket-based chat application.
- [**`w-live-reload`**](../w-live-reload#folders-and-files) uses WebSockets to implement
live reloading.
- [**`w-graphql-subscription`**](../w-graphql-subscription) does not show a
WebSocket directly, but shows GraphQL subscriptions, which are implemented

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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,3 +5,10 @@ depends: [
"dream"
"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 -e "\e[0m✅ Fetching example files using git\e[0m"
echo -e "\e[0m Source: $REPO/tree/$REF/example/$EXAMPLE#files\e[0m"
echo -e "\e[0m Source: $REPO/tree/$REF/example/$EXAMPLE#folders-and-files\e[0m"
mkdir clone
cd clone
git init --quiet
@ -81,7 +81,7 @@ echo " dune exec ./$EXE --watch"
echo
echo -e "\e[0m✅ See\e[0m"
echo
echo " - This example:" $REPO/tree/$REF/example/$EXAMPLE#files
echo " - This example:" $REPO/tree/$REF/example/$EXAMPLE#folders-and-files
echo " - Tutorial: " $REPO/tree/$REF/example#tutorial
echo
echo 💲 dune exec ./$EXE

View File

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

View File

@ -8,3 +8,10 @@ depends: [
"melange-webapi"
"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:**
- [**`i-graphql`**](../i-graphql#files), the OCaml version of this example, for
- [**`i-graphql`**](../i-graphql#folders-and-files), the OCaml version of this example, for
some more discussion.
- [**`w-graphql-subscription`**](../w-graphql-subscription#files) for GraphQL
- [**`w-graphql-subscription`**](../w-graphql-subscription#folders-and-files) for GraphQL
subscriptions.
<br>

View File

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

View File

@ -3,7 +3,7 @@
<br>
This example splits the code of the basic template example,
[**`r-template`**](../r-template#files), into two files. The first is the
[**`r-template`**](../r-template#folders-and-files), into two files. The first is the
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
mostly HTML, and to prevent `refmt` from trying to format the file:
@ -57,8 +57,8 @@ file:
**See also:**
- [**`r-template`**](../r-template#files) for the one-file version.
- [**`7-template`**](../7-template#files) for comments on [security
- [**`r-template`**](../r-template#folders-and-files) for the one-file version.
- [**`7-template`**](../7-template#folders-and-files) for comments on [security
information](../7-template#security).
- [**`w-template-files`**](../w-template-files) for the OCaml version of this
example.

View File

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

View File

@ -49,7 +49,7 @@ The important differences with regular usage of templates are:
name `response`.
- We use the promise library [Lwt](https://github.com/ocsigen/lwt) inside the
template for asynchronous control flow. See example
[**`5-promise`**](../5-promise#files) for an introduction to Lwt.
[**`5-promise`**](../5-promise#folders-and-files) for an introduction to Lwt.
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
@ -60,11 +60,11 @@ interactive, so we force writing of all output after generating each `<p>` tag.
**See also:**
- [**`r-template`**](../r-template#files) for the simpler way to do templates,
- [**`r-template`**](../r-template#folders-and-files) for the simpler way to do templates,
building up entire bodies as strings.
- [**`7-template`**](../7-template#security) section *Security* for XSS
prevention considerations.
- [**`w-template-stream`**](../w-template-stream#files) is the OCaml version of
- [**`w-template-stream`**](../w-template-stream#folders-and-files) is the OCaml version of
this example.
<br>

View File

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

View File

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

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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,3 +5,10 @@ depends: [
"dream"
"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

@ -0,0 +1,67 @@
# `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

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

View File

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

View File

@ -0,0 +1,23 @@
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

@ -0,0 +1,14 @@
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
[`esy.build`](https://esy.sh/docs/en/configuration.html#esybuild). Here is an
example from [**`w-fullstack-jsoo`**](../w-fullstack-jsoo#files):
example from [**`w-fullstack-jsoo`**](../w-fullstack-jsoo#folders-and-files):
```json
"esy": {
@ -124,12 +124,12 @@ See the examples linked below.
**See also:**
- [**`w-fullstack-rescript`**](../w-fullstack-rescript#files) for full-stack
- [**`w-fullstack-rescript`**](../w-fullstack-rescript#folders-and-files) for full-stack
development with ReScript.
- [**`r-fullstack-melange`**](../r-fullstack-melange#files) for full-stack
- [**`r-fullstack-melange`**](../r-fullstack-melange#folders-and-files) for full-stack
development with Melange and Reason syntax.
- [**`w-fswatch`**](../w-fswatch#files) for a development watcher.
- [**`w-one-binary`**](../w-one-binary#files) for bundling assets into a
- [**`w-fswatch`**](../w-fswatch#folders-and-files) for a development watcher.
- [**`w-one-binary`**](../w-one-binary#folders-and-files) for bundling assets into a
self-contained binary.
<br>

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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:**
- [**`w-one-binary`**](../w-one-binary#files) for bundling assets into a
- [**`w-one-binary`**](../w-one-binary#folders-and-files) for bundling assets into a
self-contained binary.
<br>

View File

@ -7,3 +7,10 @@ depends: [
"js_of_ocaml"
"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:**
- [**`w-esy`**](../w-esy#files) details the server's [esy](https://esy.sh/)
- [**`w-esy`**](../w-esy#folders-and-files) details the server's [esy](https://esy.sh/)
packaging.
- [**`w-fswatch`**](../w-fswatch#files) sets up a primitive development watcher.
- [**`w-one-binary`**](../w-one-binary#files) bundles assets into a
- [**`w-fswatch`**](../w-fswatch#folders-and-files) sets up a primitive development watcher.
- [**`w-one-binary`**](../w-one-binary#folders-and-files) bundles assets into a
self-contained binary.
- [**`f-static`**](../r-hello#files) presents
- [**`f-static`**](../r-hello#folders-and-files) presents
[`Dream.static`](https://aantron.github.io/dream/#val-static).
<br>

View File

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

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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>
This example plays very well with [**`w-watch`**](../w-watch#files), which shows
This example plays very well with [**`w-watch`**](../w-watch#folders-and-files), which shows
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
reloading all the way to the client, whenever any of the server's source code
@ -60,8 +60,8 @@ changes.
**See also:**
- [**`k-websocket`**](../k-websocket#files) introduces WebSockets.
- [**`w-watch`**](../w-watch#files) rebuilds and restarts a server each
- [**`k-websocket`**](../k-websocket#folders-and-files) introduces WebSockets.
- [**`w-watch`**](../w-watch#folders-and-files) rebuilds and restarts a server each
time its source code changes.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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>
*Long polling* is a technique, largely made obsolete by
[WebSockets](../k-websocket#files), where a client sends a request, but the
[WebSockets](../k-websocket#folders-and-files), where a client sends a request, but the
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
a time of the server's choosing.
@ -46,7 +46,7 @@ polling.”
**See also:**
- [**`k-websocket`**](../k-websocket#files) for a more modern way of achieving
- [**`k-websocket`**](../k-websocket#folders-and-files) for a more modern way of achieving
asynchronous client-server communication.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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>
It's the basic example [**`2-middleware`**](../2-middleware#files) adapted to
It's the basic example [**`2-middleware`**](../2-middleware#folders-and-files) adapted to
Mirage. To build and run, do
<pre><code><b>$ cd example/w-mirage</b>

35
example/w-mlx/README.md Normal file
View File

@ -0,0 +1,35 @@
# `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)

4
example/w-mlx/dune Normal file
View File

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

View File

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

View File

18
example/w-mlx/mlx.mlx Normal file
View File

@ -0,0 +1,18 @@
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)
]

16
example/w-mlx/w-mlx.opam Normal file
View File

@ -0,0 +1,16 @@
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:**
- [**`g-upload`**](../g-upload#files) is the proper file upload example.
- [**`6-echo`**](../6-echo#files) is a proper echo example :)
- [**`g-upload`**](../g-upload#folders-and-files) is the proper file upload example.
- [**`6-echo`**](../6-echo#folders-and-files) is a proper echo example :)
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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:**
- [**`f-static`**](../f-static#files) has Dream serve static files on its own,
- [**`f-static`**](../f-static#folders-and-files) has Dream serve static files on its own,
without a reverse proxy.
- [**`z-docker-esy`**](../z-docker-esy#files) deploys to Digital Ocean with
- [**`z-docker-esy`**](../z-docker-esy#folders-and-files) deploys to Digital Ocean with
Docker Compose and esy, including Docker installation instructions.
- [**`z-docker-opam`**](../z-docker-opam#files) deploys with Docker Compose and
- [**`z-docker-opam`**](../z-docker-opam#folders-and-files) deploys with Docker Compose and
opam.
<br>

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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:**
- [**`w-esy`**](../w-esy#files) for details on packaging with esy.
- [**`w-watch`**](../w-watch#files) for a primitive watcher, which can be
- [**`w-esy`**](../w-esy#folders-and-files) for details on packaging with esy.
- [**`w-watch`**](../w-watch#folders-and-files) for a primitive watcher, which can be
extended to watch `assets/`.
- [**`f-static`**](../f-static#files) shows the basics of
- [**`f-static`**](../f-static#folders-and-files) shows the basics of
[`Dream.static`](https://aantron.github.io/dream/#val-static).
<br>

View File

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

View File

@ -6,3 +6,10 @@ depends: [
"dream"
"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,3 +5,10 @@ depends: [
"dream"
"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:**
- [**`k-websocket`**](../k-websocket#files) for WebSockets, which largely
- [**`k-websocket`**](../k-websocket#folders-and-files) for WebSockets, which largely
supersede server-sent events.
- [**`w-template-stream`**](../w-template-stream#files) for another example of
- [**`w-template-stream`**](../w-template-stream#folders-and-files) for another example of
“real-time” streaming with
[`Dream.flush`](https://aantron.github.io/dream/#val-flush).

View File

@ -5,3 +5,10 @@ depends: [
"dream"
"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