Compare commits

...

126 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
Anton Bachin
05a04f56c2 Dream.run: warn on any use of ~adjust_terminal 2024-08-23 16:00:18 +03:00
Anton Bachin
ea262bce22 Adjust whitespace after preceding commit 2024-08-23 15:50:39 +03:00
Max Große
b3f89c860f
Dream.run: disable ~adjust_terminal behavior (#336) 2024-08-23 15:46:13 +03:00
Anton Bachin
b0b401bf4b
Warn upon re-entrant call to Dream.sql (#333)
Resolves #332.
2024-08-21 17:29:44 +03:00
Anton Bachin
6081749621 Document Dream.sql_pool ?size argument
Prompted by #332.
2024-08-21 11:52:24 +03:00
Anton Bachin
4ea4d94ca6 Touch up Makefiles 2024-08-21 11:51:30 +03:00
Anton Bachin
17c113380f
Adapt to mirage-crypto 1.0.0 (#334)
Fixes #328.
Closes #331.
2024-08-21 11:10:28 +03:00
Anton Bachin
7e5f18abcb Add html_of_jsx as with-test dependency 2024-07-25 09:06:13 +03:00
David Sancho
d72f21d18f
Add html_of_jsx example (#326) 2024-07-25 09:05:05 +03:00
Anton Bachin
b059575c57 Install tyxml-jsx as a test dep
Possible since https://github.com/ocsigen/tyxml/pull/312 was released in
TyXML 4.6.0.
2024-07-24 14:48:31 +03:00
Anton Bachin
41eaac9afc Docs: add a lot more links 2024-05-29 22:57:14 +03:00
Anton Bachin
d30fa5e322 make release: use SHA-256 instead of MD5
As recommended by the linter in opam-repository.
2024-05-28 15:46:06 +03:00
Anton Bachin
8eb7cf2c40 Docs: update version and copyright year 2024-05-28 14:52:20 +03:00
Anton Bachin
b2abbecfe5 Try again to disable dream.as GitHub Actions 2024-05-28 12:43:42 +03:00
Anton Bachin
e71c7aed2f Remove references to playground and dream.as
Maintaining dream.as has become a time sink and it is often down. This
is likely due to an upstream issue in the HTTP stack, which might be
replaced soon anyway. For now, it is best not to try to run the
playground.

Closes #123.
Closes #222.
2024-05-28 12:34:00 +03:00
Anton Bachin
3033ad6f85 make release: handle opam versions better 2024-05-28 12:00:53 +03:00
Anton Bachin
ba5e384b9f dream.opam: depend on latest dream-httpaf 2024-05-28 00:57:55 +03:00
v-gb
78c79e3328
Fix build error in Fly.io Dockerfile (#315) 2024-01-18 13:38:56 +03:00
Quentin Stiévenart
e9154ac51d
Fix typo in doc of Dream.router (#314)
Dream.param takes the request as first argument.
2024-01-02 17:51:02 +03:00
re.natillas
e513b8a6db
Update docker install command (#312)
Update example/z-docker-esy Docker install command
2023-12-26 13:34:21 +03:00
Anton Bachin
f96c81209f Tweak CONTRIBUTING.md
Resolves #310.
2023-12-26 11:57:10 +03:00
Anton Bachin
bbbf188a01 Examples: add --root . to build steps
Resolves #308.
2023-12-26 10:12:58 +03:00
re.natillas
5f42c87227
Sync example/r-template-files README with the code (#311) 2023-12-25 20:43:17 +03:00
Anton Bachin
1d582af222 Docs: reflow text in .mli files 2023-12-25 20:05:07 +03:00
denver-s
1337a4d4d7 Docs: replace inria.fr URLs with ocaml.org URLs
inria.fr URLs now redirect to ocaml.org.
2023-12-25 20:05:07 +03:00
Anton Bachin
337a35fb12 Depend on current Dream in playground 2023-12-01 00:50:27 +03:00
Anton Bachin
087b5ff1ea Oversight in example/r-fullstack-melange README 2023-11-30 20:00:23 +03:00
Anton Bachin
e570114299 Update example/r-fullstack-melange
- Use opam instead of esy, following Melange.
- Use new Dune build integration.

Fixes #293.
2023-11-30 19:55:57 +03:00
Anton Bachin
090b62287b example/z-playground: add dummy examples.ml
Fixes #294.
2023-11-30 17:39:05 +03:00
Anton Bachin
8abe1a162e README: detail opam instructions 2023-11-30 17:19:15 +03:00
Anton Bachin
e27a8123cf README: prefer opam 2023-11-30 17:16:27 +03:00
Anton Bachin
108c3cc4a9 Give all example .opam files unique names
This simplifies the example command lines. More importantly, it makes it
much easier to vendor Dream into a project.
2023-11-30 17:12:38 +03:00
Anton Bachin
680d5d289d Tweak example/1-hello text 2023-11-29 19:15:24 +03:00
Anton Bachin
c75379625d Partially port the systemd example to opam 2023-11-29 19:13:04 +03:00
Anton Bachin
41d4bb0b38 Fix Debian Docker examples; convert to opam
Install libssl3 package in Debian.

Fixes #305.
2023-11-29 19:07:38 +03:00
Anton Bachin
20f62d209e Convert most examples to opam
Reason examples still use esy.
2023-11-29 18:18:33 +03:00
Anton Bachin
59abca6af0 Convert Quick Start script to use opam 2023-11-29 16:40:57 +03:00
Anton Bachin
a9a9dfc09f Docs: flip logic of sun and moon theme icons 2023-11-14 12:42:16 +03:00
Anton Bachin
3c49624bb2 Document Dream.run ?socket_path 2023-11-14 12:31:37 +03:00
Anton Bachin
cb60070633 Adjust whitespace after preceding commit 2023-11-12 19:01:05 +03:00
Thomas Gazagnaire
689eb2cff6
Support for listening on Unix domain sockets (#219)
Resolves #218.
2023-11-12 18:58:46 +03:00
Anton Bachin
99388503cc EML: don't access internal Dream_pure module
Fixes #291.
2023-11-12 18:25:39 +03:00
Anton Bachin
4c18ba8450 WebSocket: don't need client handlers value
Since https://github.com/anmonteiro/websocketaf/issues/39, an Obj.magic
cast from the server's WebSocket handlers to the client's is not longer
necessary.

See also https://github.com/aantron/dream/issues/181.
2023-11-10 21:06:30 +03:00
Anton Bachin
a2cfbf4975 WebSocket: allow non-FIN frames
Since https://github.com/anmonteiro/websocketaf/issues/33, websocket/af
supports sending frames without the FIN bit. Begin using this in Dream.

See also https://github.com/aantron/dream/issues/181.
2023-11-10 20:54:40 +03:00
Anton Bachin
aaabf4dfe3 WebSocket: send ping and pong payloads
Since https://github.com/anmonteiro/websocketaf/issues/36 was fixed
recently, websocket/af supports sending ping and pong payloads, as
required by the WebSocket spec. This commit has dream-httpaf using that
support.

See also https://github.com/aantron/dream/issues/181.
2023-11-10 11:23:19 +03:00
Anton Bachin
8cb51f18ee Document Dream.form ~csrf:false 2023-11-07 21:06:02 +03:00
Anton Bachin
a3579218c2 Upgrade to latest websocket/af fork commits 2023-11-07 18:58:19 +03:00
Anton Bachin
d802548914 Upgrade H2 to 0.11 and newest commits 2023-11-07 18:50:20 +03:00
Anton Bachin
51902fc63c Pull in latest http/af fork commits
These commits do not affect the Dream code in any way.
2023-11-07 18:43:36 +03:00
Anton Bachin
c86e49225e Upgrade Gluten to 0.5 2023-11-07 18:37:35 +03:00
Anton Bachin
9c72a39ef8 Log initialization: respect custom log levels
Fixes #299.
2023-11-06 14:26:42 +03:00
Pedro Dias
1c60e60f17
example/z-docker-opam: update alpine version (#300) 2023-11-02 16:36:41 +03:00
Tim McGilchrist
f5c8ba0cff
Update dream-mirage (#283)
Mainly to provide csrf_tag rather than form_tag helper.
2023-11-02 16:27:16 +03:00
Louis Pilfold
60a0dc5df5
Fix typo (#292) 2023-10-31 17:33:19 +03:00
Petter A. Urkedal
6e58736e28
Compatibility with Caqti 2.0.0 (#302) 2023-10-31 17:20:40 +03:00
Anton Bachin
8140a600e4 Advance vendored Gluten commit
Fixes #286 by including anmonteiro/gluten#58.
2023-07-14 15:41:54 +03:00
Benjamin Thomas
4a5310b09b
Fix JSON example broken by ppx_yojson_conv 0.16.0 (#287) 2023-07-14 15:25:57 +03:00
Benjamin Thomas
aada26ce54
CONTRIBUTING.md: fix bad remote URL (#288) 2023-07-13 14:33:17 +03:00
Anton Bachin
7a2c5a03ff Add Dream.drop_session_field
Resolves #284.
2023-06-22 15:50:26 +03:00
Thomas Coopman
1bf8e1115c Add STDOUT as output from dream_eml (#228)
Resolves #227.
2023-06-05 15:12:32 +03:00
Anton Bachin
10ae36fa5f Live reload: retry indefinitely 2023-06-01 16:37:01 +03:00
Anton Bachin
8e89f7cd2a Live reload: remove optional arguments 2023-06-01 16:37:01 +03:00
Thibaut Mattio
7b46896bf9 Add a Dream.livereload middleware
The code is adapted from dream-livereload, itself adapted from the w-live-reload example.
We update the w-live-reload to use the newly introduced middleware.

Apply nits
2023-06-01 16:37:01 +03:00
Anton Bachin
635c0589e9
Get the Windows CI working (#282)
The syntax of the constraint is based on a suggestion in Discord.

Tests are disabled due to a difference in ppx_expect output on Windows.

Co-authored-by: Et7f3 <cadeaudeelie@gmail.com>
2023-05-22 16:14:19 +03:00
Anton Bachin
b55d1914cf Docs: initialize theme earlier to avoid flicker
Follow-on to #268.
2023-05-22 16:08:59 +03:00
Tom Ekander
e529b0eb15
Docs: add light- heme and use save in local storage (#268)
Also removed the shadow on the <h1> element. It was probably left over
from an early version of the dark theme, before Dream's alpha 1 release.

Resolves #235.

Co-authored-by: Anton Bachin <antonbachin@yahoo.com>
2023-05-22 16:08:23 +03:00
Anton Bachin
6e666d4c70 Playground: update lockfiles 2023-05-14 16:55:08 +03:00
Anton Bachin
f5558638f3 Upgrades while rebuilding the playground 2023-05-14 16:34:55 +03:00
Anton Bachin
d35a6338d1 Update dream-serve and add a couple tests 2023-05-14 08:15:06 +03:00
Yawar Amin
c7da98b718
Fix typo (#281) 2023-05-14 08:13:14 +03:00
Anton Bachin
e14bd91a44 Remove deprecated values
Path getter and setter not removed. See #238. not_found just deprecated,
so not removed, for users to have more of a chance to adapt.
2023-05-11 06:51:12 +03:00
Jean-Michel Bea
14093e16cc Reason 3.8.x releases support recent OCaml
Cherry-picked from #229.
2023-05-11 05:49:31 +03:00
Dennis Dang
006196fa0c
Upgrade GraphiQL to 2.4.1 (#271) 2023-05-03 15:21:46 +03:00
Anton Bachin
0826c267b3 Clarify docs expected markup mismatch message 2023-04-28 15:27:18 +03:00
Anton Bachin
881d26da23 Refresh CONTRIBUTING.md 2023-04-28 15:10:33 +03:00
Anton Bachin
765da90414 .gitignore nano .swp files 2023-04-28 10:24:40 +03:00
Anton Bachin
860e4563bd Fix link to example/w-watch in 1-hello 2023-04-27 10:37:21 +03:00
Dennis Dang
313fe46c3f
Update w-watch's README command to match directory (#267) 2023-04-25 07:47:00 +03:00
Anton Bachin
76faf6f3b2 Docs: link to note about trailing /
Follow-on to #265.
2023-04-24 10:36:27 +03:00
Rawley
561e99d837
Router: add doc about trailing slashes (#265) 2023-04-24 09:30:20 +03:00
Anton Bachin
c27a83ecd9 Adapt example/9-error to not_found deprecation
Done in 23b740622b4084162ffcd067d5a59514bcb7d289.
2023-04-23 22:22:43 +03:00
Anton Bachin
7117d90379 example/w-watch: requires Dune 3.7.0 2023-04-23 21:29:29 +03:00
Anton Bachin
d135ba6046 Change logger's tag to dream.logger
dream.log is too generic -- it appears to refer to the whole Dream log,
when it is meant to refer to Dream's logger.
2023-04-23 21:23:57 +03:00
Dennis Dang
dbf01b83df
Warn if response header has empty name (#262)
Co-authored-by: Anton Bachin <antonbachin@yahoo.com>
2023-04-23 17:20:11 +03:00
Anton Bachin
f784018e1d Rename w-fswatch to w-watch
Follow-on to #266.
2023-04-23 16:47:39 +03:00
Anton Bachin
23b740622b Deprecate Dream.not_found 2023-04-23 16:40:24 +03:00
Dennis Dang
a57e8bc860
Use dune exec -w in fswatch example (#266) 2023-04-23 16:39:29 +03:00
Anton Bachin
3df0d85c0a Dream.run docs: don't show non-existent options 2023-04-23 09:02:26 +03:00
Anton Bachin
1b0ac702b0 Update Dream.run docs w.r.t. ?debug
?debug was removed in 640a1b218b0c6932088077416455463ffd34f036. This
commit updates the docs to refer to its replacement.
2023-04-23 08:57:03 +03:00
Dennis Dang
a2961cd7fa
Upgrade ocamlformat to 0.25.1 (#263) 2023-04-22 20:42:14 +03:00
Anton Bachin
baa222bb8e Upgrade vendored deps and adapt their Eio support 2023-04-21 08:32:57 +03:00
Tim McGilchrist
18cd2a08ac
Mirage: add dependency on rresult (#260) 2023-04-21 07:37:58 +03:00
Anton Bachin
a39c938835 README: add Twitch to contact info 2023-04-20 22:13:24 +03:00
Anton Bachin
edd0cd9167 Fix make watch 2023-04-19 09:29:33 +03:00
Anton Bachin
da604f1478 make build: Dune workspace-friendly command 2023-04-19 09:14:33 +03:00
Anton Bachin
599efd55fc Docs: fix cross-reference 2023-04-14 10:57:29 +03:00
Anton Bachin
f0cde12979 Examples: esy.json: upgrade OCaml to 4.14
esy does not seem to offer OCaml 5.0.0 at the moment.

Resolves #256.
2023-04-14 10:32:25 +03:00
Anton Bachin
d2f0016613 Upgrade examples to use Dream alpha 5
Resolves #257.
2023-04-14 05:43:02 +03:00
Anton Bachin
fcc618d200 Rephrase note about nginx WebSocket proxying 2023-03-29 20:20:26 +03:00
Thomas Refis
27ee901773
nginx example: add a note about the use of websockets (#252) 2023-03-29 20:12:59 +03:00
Anton Bachin
cede19ac1b Upgrade to odoc 2.0.2 2023-03-29 13:43:25 +03:00
312 changed files with 8780 additions and 3963 deletions

View File

@ -1,9 +1,9 @@
name: docker-esy
on:
push:
paths:
- 'example/z-docker-esy/**'
- .github/workflows/docker-esy.yml
on: workflow_call
# push:
# paths:
# - 'example/z-docker-esy/**'
# - .github/workflows/docker-esy.yml
jobs:
deploy:

View File

@ -1,9 +1,9 @@
name: docker-opam
on:
push:
paths:
- 'example/z-docker-opam/**'
- .github/workflows/docker-opam.yml
on: workflow_call
# push:
# paths:
# - 'example/z-docker-opam/**'
# - .github/workflows/docker-opam.yml
jobs:
deploy:

View File

@ -1,9 +1,9 @@
name: systemd
on:
push:
paths:
- 'example/z-systemd/**'
- .github/workflows/systemd.yml
on: workflow_call
# push:
# paths:
# - 'example/z-systemd/**'
# - .github/workflows/systemd.yml
jobs:
deploy:

View File

@ -7,79 +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
# Windows is blocked until we no longer require libev; Dream still works
# on Windows, but testing it is awkward at the moment.
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
- uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: ${{matrix.ocaml}}
dune-cache: true
- run: opam depext --yes conf-postgresql
- run: opam depext --yes conf-libev
# Needed until https://github.com/reasonml/reason/pull/2660 is in opam.
- run: opam pin add reason --yes --no-action --dev-repo
# 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'
# 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.
- run: |
# 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'
- 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'
- run: opam lint --recursive example
- name: Build examples
if: runner.os != 'Windows'
run: |
set -e
set -x
WITH_TEST=--with-test
case ${{matrix.ocaml}} in
4.09.x) WITH_TEST=;;
4.08.x) WITH_TEST=;;
esac
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)
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=$(ls $EXAMPLE/*.ml $EXAMPLE/*.re $EXAMPLE/server/*.ml $EXAMPLE/server/*.re)
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
continue
fi
EXE=$(echo $FILE | sed 's/\..*$/.exe/g')
echo dune build $EXE
opam exec -- dune build $EXE
done
fi
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
@ -95,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

1
.gitignore vendored
View File

@ -26,3 +26,4 @@ scratch/
# Editors
.vscode/
*.swp

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

@ -1,4 +1,4 @@
version = 0.24.1
version = 0.25.1
profile = conventional
leading-nested-match-parens = false

View File

@ -1,4 +1,4 @@
Copyright (c) 2021-2023, Anton Bachin
Copyright (c) 2021-2024, Anton Bachin
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,14 +1,17 @@
PACKAGES := dream-pure,dream-httpaf,dream
.PHONY : build
build :
@dune build -p dream-pure,dream-httpaf,dream --no-print-directory @install
@dune build --only-packages $(PACKAGES) --no-print-directory @install
.PHONY : watch
watch :
@dune build -p dream-pure,dream-httpaf,dream --no-print-directory -w
@dune build --only-packages $(PACKAGES) --no-print-directory @install -w
.PHONY : deps
deps :
opam install --deps-only --with-test ./dream-pure.opam ./dream-httpaf.opam ./dream.opam
opam install --deps-only --with-test --with-doc \
./dream-pure.opam ./dream-httpaf.opam ./dream.opam
TEST ?= test
ROOT := $(shell [ -f ../dune-workspace ] && echo .. || echo .)
@ -28,7 +31,7 @@ test-watch :
.PHONY : coverage-serve
coverage-serve :
cd _coverage && dune exec -- serve -p 8082
cd _coverage && dune exec -- dream-serve -p 8082
.PHONY : promote
promote :
@ -149,9 +152,9 @@ release : clean
(cd _release && tar xf $(RELEASE).tar.gz)
opam remove -y dream-pure dream-httpaf dream gluten httpaf h2 websocketaf paf
opam pin remove -y dream-pure dream-httpaf dream
opam pin add -y --no-action dream-pure _release/$(RELEASE) --kind=path
opam pin add -y --no-action dream-httpaf _release/$(RELEASE) --kind=path
opam pin add -y --no-action dream _release/$(RELEASE) --kind=path
opam pin add -y --no-action dream-pure.dev _release/$(RELEASE) --kind=path
opam pin add -y --no-action dream-httpaf.dev _release/$(RELEASE) --kind=path
opam pin add -y --no-action dream.dev _release/$(RELEASE) --kind=path
opam reinstall -y --verbose dream
@echo Run make release-finish to complete after killing the server
cd example/1-hello && dune exec --root . ./hello.exe || true
@ -160,5 +163,9 @@ release : clean
release-finish :
opam remove -y dream-pure dream-httpaf dream
opam pin remove -y dream-pure dream-httpaf dream
md5sum $(RELEASE).tar.gz
sha256sum $(RELEASE).tar.gz
ls -l $(RELEASE).tar.gz
.PHONY : release-clean
release-clean :
rm -rf $(RELEASE) $(RELEASE).tar.gz _release

View File

@ -12,7 +12,6 @@ Easy-to-use, feature-complete Web framework without boilerplate.
<p align="center">
<a href="#quick-start">Quick Start</a> |
<a href="http://dream.as">Playground</a> |
<a href="https://github.com/aantron/dream/tree/master/example#readme">
Tutorial</a> |
<a href="https://aantron.github.io/dream/">Reference</a>
@ -78,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
@ -103,33 +102,32 @@ 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
Visit one of the first tutorials in the [online
playground][2-middleware-playground], and read its
[docs](https://github.com/aantron/dream/tree/master/example/2-middleware#files).
You can get and build it locally with:
You can get
[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>
Most of the other [examples][tutorial] are also loaded in the playground. See
the links on its [home page][playground].
## esy
Visit any of the [examples][tutorial], such as
[**`2-middleware`**][2-middleware], and re-create the files locally. The file
[`esy.json`](https://github.com/aantron/dream/blob/master/example/2-middleware/esy.json)
shows how to depend on Dream. All of the examples are installed by running `npx
esy`, and started with `npx esy start`.
### opam
Create a project directory with an optional local switch:
```
mkdir project
cd project
opam switch create . 5.1.0
eval $(opam env)
```
Install Dream:
```
opam install dream
```
@ -141,12 +139,18 @@ 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
[playground]: http://dream.as
[2-middleware-playground]: http://dream.as/2-middleware
[2-middleware]: https://github.com/aantron/dream/tree/master/example/2-middleware#folders-and-files
## esy
Visit any of the [examples][tutorial], such as
[**`2-middleware`**][2-middleware], and re-create the files locally. The file
[`esy.json`](https://github.com/aantron/dream/blob/master/example/2-middleware/esy.json)
shows how to depend on Dream. All of the examples are installed by running `npx
esy`, and started with `npx esy start`.
<br>
@ -165,18 +169,18 @@ dune exec ./middleware.exe
small-to-medium deployments.
- [**Examples**][examples] &mdash; These cover various HTTP scenarios.
- [**API reference**][api-main]
- [Watching][fswatch] and [live reloading][reload].
- [Watching][watch] and [live reloading][reload].
[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
[fswatch]: https://github.com/aantron/dream/tree/master/example/w-fswatch#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>
@ -213,8 +217,9 @@ 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).
Highlight `@antron` to poke @aantron specifically.

View File

@ -19,13 +19,13 @@ Contributions are very welcome. This includes not only code PRs, but also:
To get the version of Dream installed in a project that uses it, run
```
npx esy ls-builds
opam list dream
```
or
```
opam list dream
npx esy ls-builds
```
<br>
@ -40,25 +40,26 @@ cd dream
```
Note: the clone *must* be `--recursive`, because Dream several dependencies
vendored as [submodules](https://github.com/aantron/dream/tree/master/src/vendor)!
vendored as
[submodules](https://github.com/aantron/dream/tree/master/src/vendor).
Later, you'll need to fork the repository on GitHub, and add your fork as a
remote:
```
git remote add fork git@github.com/my-github-name/dream.git
git remote add fork git@github.com:my-github-name/dream.git
```
Install Dream's dependencies:
```
opam install --deps-only ./dream.opam --with-test
make deps
```
If you don't have an opam switch ready, first create one with
```
opam switch create . 4.12.0 --no-install
opam switch create . 4.14.1 --no-install
```
You can now add some code that will exercise your change, so you can test it as
@ -71,7 +72,10 @@ you work. There are two main places for this:
To run tests from a single directory, for example `test/expect/pure`, run
`make test TEST=test/expect/pure`.
2. The examples in `example/`. I often test changes by modifying an example that
2. The tests can also be run in watch mode using `make test-watch`. This is not
compatible with coverage reports at the moment.
3. The examples in `example/`. I often test changes by modifying an example that
is almost on topic for the code I'm changing, and then not committing the
example. In some cases, though, it's easiest to fork or write a new example
for some new code, and commit it. New examples greatly appreciated! To build
@ -104,10 +108,10 @@ If you want to work again later, be sure to use `--recurse-submodules` during
git pull --recurse-submodules
```
Please don't force-push into a PR &mdash; it makes incremental review very
difficult, and we will squash-merge most PRs anyway!
**Note:** Please don't force-push into a PR &mdash; it makes incremental review
very difficult, and we will squash-merge most PRs anyway!
Also please don't resolve conversations in PRs. Reviewers use resolving
**Note:** Please don't resolve conversations in PRs. Reviewers use resolving
conversations to keep track of what has been addressed.
<br>
@ -146,8 +150,8 @@ To build the docs, go to
make deps
```
This will install npm packages and opam packages (some of which are pinned to
git commits).
This will install npm and opam packages. In particular, the site currently
requires odoc 2.0.2, Soupault, and a specific version of Highlight.js.
After that, back in the project root,
@ -162,3 +166,11 @@ make docs
```
to build the docs locally. They are output to `docs/web/build/index.html`.
You can also use
```
make docs-watch
```
to rebuild the docs automatically as you write them.

View File

@ -39,8 +39,8 @@ b {
<body>
<pre><code><b>$ cd example/2-middleware</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./middleware.exe</b>
<span class="dim">08.03.21 22:19:21.126</span> Running at http://localhost:8080
<span class="dim">08.03.21 22:19:21.126</span> Type Ctrl+C to stop
<span class="dim">08.03.21 22:19:24.927</span> dream.log <span class="info">INFO</span> <span class="odd">REQ 1</span> GET / 127.0.0.1:58549 Mozilla/5.0 ...

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -26,6 +26,6 @@ lockfile.
Useful links:
- OCaml [*Syntax of documentation comments*](http://caml.inria.fr/pub/docs/manual-ocaml/ocamldoc.html#ss:ocamldoc-syntax)
- OCaml [*Syntax of documentation comments*](https://v2.ocaml.org/manual/ocamldoc.html#ss:ocamldoc-syntax)
- Lambda Soup [*Module Soup*](https://aantron.github.io/lambdasoup/)
- Soupault [*Tips and tricks*](https://soupault.app/tips-and-tricks/)

View File

@ -13,8 +13,35 @@ let if_expected expected test f =
f ()
else begin
Soup.write_file "actual" actual;
Printf.ksprintf failwith "Mismatch; wrote %s"
(Filename.concat (Sys.getcwd ()) "actual")
prerr_newline ();
prerr_newline ();
prerr_endline "Mismatch with expected initial HTML content.";
prerr_newline ();
prerr_endline
"The Dream docs build rewrites HTML emitted by odoc to make it neater.";
prerr_endline
"Each rewritten tag has an expected initial content for sanity checking.";
prerr_endline "The actual found content has been written to";
prerr_newline ();
prerr_endline (" " ^ (Filename.concat (Sys.getcwd ()) "actual"));
prerr_newline ();
begin match String.split_on_char '\n' actual with
| [] -> ()
| first_line::_ ->
prerr_endline "Hint:";
prerr_newline ();
prerr_endline (" " ^ first_line);
prerr_newline ()
end;
prerr_endline "Hint: make sure odoc 2.0.2 is installed.";
prerr_endline
"Other versions of odoc generate markup that doesn't match the expected.";
prerr_newline ();
Printf.ksprintf failwith "Mismatch"
end
let add_backing_lines soup =

View File

@ -1,7 +1,7 @@
(executable
(name index)
(modules index)
(libraries common lambdasoup))
(libraries common lambdasoup str))
(library
(name common)

File diff suppressed because it is too large Load Diff

View File

@ -60,6 +60,49 @@
src: url('tenor-sans-v12-latin-regular.woff2') format('woff2');
}
/* Theme */
/* Dark theme (default) */
:root, body:not([data-theme="light"]) {
--bg-color: #131618;
--text-color: #c9d1d9;
--code-bg-color: #2c333b;
--border-color: #282828;
--link-color: #8dc5ff;
--external-link-color: #5d7fcd;
--anchor-color: #bfcdea;
--of-color: #bec5cd;
--target-backing-color: #390022;
--hljs-keyword-color: #ff6c9b;
--hljs-identifier-color: #70df5c;
--hljs-tag-color: #c28eff;
--hljs-string-color: #e3db7a;
}
/* Light theme */
:root, body[data-theme="light"] {
--bg-color: #f5f7fa;
--text-color: #1f2937;
--code-bg-color: #eef1f6;
--header-bg-color: #f5f7fa;
--border-color: #e0e0e0;
--link-color: #1c7ed6;
--external-link-color: #1d4ed8;
--anchor-color: #888;
--of-color: #6b7280;
--target-backing-color: #f7f6f3;
--hljs-keyword-color: #d94879;
--hljs-identifier-color: #22863a;
--hljs-tag-color: #6f42c1;
--hljs-string-color: #b94e48;
}
body {
font-family: Lato, -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell, Open Sans, Helvetica Neue, Helvetica, Arial, sans-serif;
font-size: 16px;
@ -101,15 +144,15 @@ h6 {
/* Colors and presentation styles. */
body {
background-color: #131618;
color: #c9d1d9;
background-color: var(--bg-color);
color: var(--text-color);
}
.odoc-content pre {
background-color: #1a1f26;
background-color: var(--code-bg-color);
margin-left: 1em;
margin-right: 1em;
border: 1px solid #111;
border: 1px solid var(--border-color);
}
.odoc-content .spec > pre {
background: none;
@ -119,7 +162,7 @@ body {
.odoc-content code {
/* color: #ddd; */
background-color: #2c333b;
background-color: var(--code-bg-color);
padding: 0 5px;
margin: 0 1px;
white-space: nowrap;
@ -150,17 +193,40 @@ body {
} */
header {
background-color: #131618;
border-bottom: 1px solid #282828;
background-color: var(--bg-color);
border-bottom: 1px solid var(--border-color);
}
header .topmost {
/* background-color: #0f131a; */
border-bottom: 1px solid #282828;
border-bottom: 1px solid var(--border-color);
}
h1 {
text-shadow: -2px 2px black;
.topmost .toolbar {
float: right;
}
.topmost .toggle-theme-btn {
all: unset;
position: relative;
}
.topmost .toggle-theme-btn::before {
content: "\F185"; /* sun */
position: absolute;
left: calc(0% - 16px + -8px);
top: calc(0% + 4px);
width: 16px;
height: 16px;
display: flex;
justify-content: center;
align-items: center;
font-family: FontAwesome, FontAwesomeBrands;
font-size: 15px;
}
body:not([data-theme="light"]) .topmost .toggle-theme-btn::before {
content: "\F186"; /* moon */
}
header pre {
@ -191,7 +257,7 @@ footer {
}
:target .backing {
background-color: #390022;
background-color: var(--target-backing-color);
}
nav ~ * a[href="#builtin"],
@ -205,16 +271,16 @@ nav ~ * a[href="#templates"] {
font-style: italic;
}
a[href*=example] {
header a[href*=example], .spec-doc a[href*=example] {
font-weight: bold;
}
a[href^=http]::after {
header a[href^=http]::after, .spec-doc a[href^=http]::after {
content: "\f35d";
font-family: FontAwesome;
font-size: 10px;
line-height: 18px;
color: #5d7fcd;
color: var(--external-link-color);
position: relative;
top: -1px;
margin-left: 2px;
@ -225,7 +291,7 @@ a[href^=http]::after {
}
a, a:visited, a:active {
color: #8dc5ff;
color: var(--link-color);
text-decoration: none;
}
@ -234,27 +300,27 @@ a:hover {
}
.odoc-content a > code {
color: #8dc5ff;
color: var(--link-color);
}
.hljs-module-access, .hljs-keyword, .keyword {
color: #ff6c9b;
color: var(--hljs-keyword-color);
}
.hljs-identifier, .hljs-literal, .hljs-type {
color: #70df5c;
color: var(--hljs-identifier-color);
}
.hljs-tag {
color: #c28eff;
color: var(--hljs-tag-color);
}
.hljs-string {
color: #e3db7a;
color: var(--hljs-string-color);
}
.of {
color: #bec5cd;
color: var(--of-color);
}
.topmost ul {
@ -368,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 {
@ -407,7 +472,7 @@ ul ul li {
height: 100%;
width: 43rem;
/* background-color: #262626; */
border-right: 1px solid #282828;
border-right: 1px solid var(--border-color);
}
h2, h2 ~ :not(.odoc-spec):not(nav), footer {
@ -582,8 +647,8 @@ h2:first-of-type {
overflow-y: scroll;
scrollbar-width: none;
line-height: 30px;
border-right: 1px solid #262626;
background-color: #131618;
border-right: 1px solid var(--border-color);
background-color: var(--bg-color);
/* color: #ddd; */
}
.odoc-toc::-webkit-scrollbar {
@ -674,7 +739,7 @@ h2 > .anchor, h3 > .anchor {
font-family: FontAwesome;
font-size: 10px;
font-style: oblique;
color: #bfcdea;
color: var(--anchor-color);
position: relative;
top: -1.75px;
left: -4px;

View File

@ -4,8 +4,7 @@
// Copyright 2021 Anton Bachin *)
console.log("foo");
/* Scrolling */
function current_section() {
var threshold = window.innerHeight / 2;
@ -49,3 +48,38 @@ function scroll() {
};
window.onscroll = scroll;
/* Theme mode */
var THEME_MODE_KEY = "dream-theme"
function apply_theme(theme) {
if (theme === "light") {
document.body.setAttribute("data-theme", "light");
} else {
document.body.removeAttribute("data-theme");
}
}
function toggle_theme() {
var current_theme = localStorage.getItem(THEME_MODE_KEY);
var new_theme = current_theme === "dark" ? "light" : "dark";
localStorage.setItem(THEME_MODE_KEY, new_theme);
apply_theme(new_theme);
}
function init_theme() {
var default_theme = "dark";
var stored_theme = localStorage.getItem(THEME_MODE_KEY) || default_theme;
apply_theme(stored_theme);
}
function prepare_button() {
var theme_toggle_button = document.querySelector(".toggle-theme-btn");
if (theme_toggle_button) {
theme_toggle_button.addEventListener("click", toggle_theme);
}
}
document.addEventListener("DOMContentLoaded", prepare_button);

View File

@ -24,6 +24,10 @@
</head>
<body class="index">
<script>
init_theme();
</script>
<header>
<div class="topmost">
<div class="titles">
@ -32,11 +36,15 @@
</div>
<ul>
<li><code>1.0.0~alpha5</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/blob/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>
</ul>
<div class="toolbar">
<button class="toggle-theme-btn">&nbsp;</button>
</div>
</div>
<pre><span class="keyword">let</span> hello who =
@ -115,18 +123,13 @@
<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>
Many <a target="_blank" rel="noreferrer noopener" href="https://github.com/aantron/dream/tree/master/example#reason">
Examples</a>, covering all kinds of scenarios.
</li>
<li>
An online <a target="_blank" rel="noreferrer noopener" href="http://dream.as/">
<b>Playground</b></a>, where you can try Dream without installing
anything!
</li>
</ul>
</div>
</header>
@ -135,7 +138,7 @@
<div id="api"></div>
<footer>
Copyright © 2021 Anton Bachin.
Copyright © 2021-2024 Anton Bachin.
<br>
Released under the MIT license. See
<a href="https://github.com/aantron/dream/blob/master/LICENSE.md">

View File

@ -4,10 +4,6 @@ synopsis: "Dream docs"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"
depends: [
"lambdasoup"
"odoc"
"odoc" {= "2.0.2"}
"soupault" {>= "2.5.0"}
]
pin-depends: [
["odoc.2.0.0~master" "git+https://github.com/aantron/odoc.git#dbb37e20717985edfd8f734e00b9ab6f705d81a4"]
]

View File

@ -1,71 +1,78 @@
opam-version: "2.0"
depends: [
"ISO8601" {= "0.2.6"}
"astring" {= "0.8.5"}
"base-bigarray" {= "base"}
"base-bytes" {= "base"}
"base-threads" {= "base"}
"base-unix" {= "base"}
"base64" {= "3.5.0"}
"bigarray-compat" {= "1.0.0"}
"cmdliner" {= "1.0.4"}
"conf-libev" {= "4-11"}
"containers" {= "3.3"}
"cppo" {= "1.6.7"}
"base64" {= "3.5.1"}
"bigarray-compat" {= "1.1.0"}
"bos" {= "0.2.1"}
"camlp-streams" {= "5.0.1"}
"camomile" {= "1.0.2"}
"cmdliner" {= "1.1.1"}
"conf-libev" {= "4-12"}
"conf-pkg-config" {= "2"}
"containers" {= "3.11"}
"cppo" {= "1.6.9"}
"csexp" {= "1.5.1"}
"cstruct" {= "6.0.0"}
"dune" {= "2.8.5"}
"dune-configurator" {= "2.8.5"}
"ezjsonm" {= "1.2.0"}
"fileutils" {= "0.6.3"}
"fmt" {= "0.8.9"}
"cstruct" {= "6.1.1"}
"ctypes" {= "0.20.1"}
"digestif" {= "1.1.3"}
"dune" {= "3.7.0"}
"dune-configurator" {= "3.7.0"}
"either" {= "1.0.0"}
"eqaf" {= "0.9"}
"ezjsonm" {= "1.3.0"}
"fileutils" {= "0.6.4"}
"fmt" {= "0.9.0"}
"fpath" {= "0.7.3"}
"hex" {= "1.4.0"}
"jingoo" {= "1.4.3"}
"jsonm" {= "1.0.1"}
"lambdasoup" {= "0.7.2"}
"hex" {= "1.5.0"}
"integers" {= "0.7.0"}
"jingoo" {= "1.4.4"}
"jsonm" {= "1.0.2"}
"lambdasoup" {= "1.0.0"}
"logs" {= "0.7.0"}
"lua-ml" {= "0.9.2"}
"lwt" {= "5.4.0"}
"markup" {= "1.0.0-1"}
"menhir" {= "20210310"}
"menhirLib" {= "20210310"}
"menhirSdk" {= "20210310"}
"mmap" {= "1.1.0"}
"ocaml" {= "4.12.0"}
"ocaml-base-compiler" {= "4.12.0"}
"ocaml-compiler-libs" {= "v0.12.3"}
"lua-ml" {= "0.9.4"}
"lwt" {= "5.6.1"}
"markup" {= "1.0.3"}
"menhir" {= "20211128"}
"menhirLib" {= "20211128"}
"menhirSdk" {= "20211128"}
"ocaml" {= "4.14.1"}
"ocaml-base-compiler" {= "4.14.1"}
"ocaml-compiler-libs" {= "v0.12.4"}
"ocaml-config" {= "2"}
"ocaml-migrate-parsetree" {= "2.1.0"}
"ocaml-migrate-parsetree" {= "2.4.0"}
"ocaml-options-vanilla" {= "1"}
"ocaml-syntax-shims" {= "1.0.0"}
"ocamlbuild" {= "0.14.0"}
"ocamlfind" {= "1.9.1"}
"ocplib-endian" {= "1.1"}
"ocamlbuild" {= "0.14.2"}
"ocamlfind" {= "1.9.6"}
"ocplib-endian" {= "1.2"}
"odate" {= "0.6"}
"odoc" {= "2.0.0~master"}
"odoc" {= "2.0.2"}
"odoc-parser" {= "1.0.1"}
"otoml" {= "1.0.4"}
"ppx_derivers" {= "1.2.1"}
"ppx_deriving" {= "5.2.1"}
"ppxlib" {= "0.22.0"}
"re" {= "1.9.0"}
"ppxlib" {= "0.25.1"}
"re" {= "1.10.4"}
"result" {= "1.5"}
"rresult" {= "0.7.0"}
"seq" {= "base"}
"sexplib0" {= "v0.14.0"}
"soupault" {= "2.5.0"}
"spelll" {= "0.3"}
"sexplib0" {= "v0.15.1"}
"soupault" {= "4.4.0"}
"spelll" {= "0.4"}
"stdlib-shims" {= "0.3.0"}
"stringext" {= "1.6.0"}
"toml" {= "7.0.0"}
"topkg" {= "1.0.3"}
"tsort" {= "2.0.0"}
"tyxml" {= "4.4.0"}
"topkg" {= "1.0.7"}
"tsort" {= "2.1.0"}
"tyxml" {= "4.5.0"}
"uchar" {= "0.0.2"}
"uucp" {= "13.0.0"}
"uutf" {= "1.0.2"}
]
pin-depends: [
["odoc.2.0.0~master" "git+https://github.com/aantron/odoc.git#dbb37e20717985edfd8f734e00b9ab6f705d81a4"]
"uucp" {= "15.0.0"}
"uutf" {= "1.0.3"}
"yaml" {= "3.1.0"}
]
name: "web"
version: "dev"
version: "~dev"
synopsis: "Dream docs"
maintainer: "Anton Bachin <antonbachin@yahoo.com>"

View File

@ -15,33 +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"
"ke" {>= "0.5"} # Gluten.
"lwt_ssl" {>= "1.2.0"} # Gluten.
"psq" # h2.
"result" # websocket/af.
]
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
@ -56,11 +56,13 @@ depends: [
"dune" {>= "2.7.0"}
"duration"
"emile" {>= "1.1"}
"ke" {>= "0.4"} # paf.
"letsencrypt" {>= "0.3.0"}
"lwt"
"lwt_ppx" {>= "1.2.2"}
"mimic"
"mimic" {>= "0.0.5"}
"mirage-time"
"rresult"
"tcpip"
"tls-mirage"
]

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
@ -50,24 +50,27 @@ depends: [
"base-unix"
"bigarray-compat"
"camlp-streams"
"caqti" {>= "1.8.0"} # Infix operators.
"caqti-lwt"
"conf-libev" {os != "win32"}
"caqti" {>= "2.0.0"}
"caqti-lwt" {>= "2.0.0"}
("conf-libev" {os != "win32"} | "ocaml" {os = "win32"})
"cstruct" {>= "6.0.0"}
"dream-httpaf" {>= "1.0.0~alpha2"}
"digestif" {>= "0.7"} # to_raw_string.
"dream-httpaf" {>= "1.0.0~alpha4"}
"dream-pure" {>= "1.0.0~alpha2"}
"dune" {>= "2.7.0"} # --instrument-with.
"fmt" {>= "0.8.7"} # `Italic.
"graphql_parser"
"graphql-lwt"
"lambdasoup" {>= "0.6.1"}
"lwt"
"lwt_ppx" {>= "1.2.2"}
"lwt_ssl"
"logs" {>= "0.5.0"}
"magic-mime"
"markup" {>= "1.0.2"}
"mirage-clock" {>= "3.0.0"} # now_d_ps : unit -> int * int64.
"mirage-crypto" {>= "0.8.1"} # AES-256-GCM.
"mirage-crypto-rng"
"mirage-crypto" {>= "1.0.0"}
"mirage-crypto-rng" {>= "1.0.0"}
"mirage-crypto-rng-lwt"
"multipart_form" {>= "0.4.0"}
"multipart_form-lwt"
@ -83,17 +86,14 @@ depends: [
"caqti-driver-postgresql" {with-test}
"caqti-driver-sqlite3" {with-test}
"crunch" {with-test}
"html_of_jsx" {with-test}
"js_of_ocaml" {with-test}
"js_of_ocaml-ppx" {with-test}
"lambdasoup" {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"}
# Blocked until https://github.com/ocsigen/tyxml/pull/312.
# "tyxml-jsx" {with-test & >= "4.5.0"}
# "tyxml-ppx" {with-test & >= "4.5.0"}
"tyxml-jsx" {with-test}
]
build: [

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -17,21 +17,20 @@ At startup, Dream prints a message to the log, telling you where to point your
browser. Your terminal probably makes the link clickable.
<pre><code><b>$ cd example/1-hello</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./hello.exe</b>
08.03.21 21:17:21.471 Running at http://localhost:8080
08.03.21 21:17:21.471 Type Ctrl+C to stop
</code></pre>
If you go to [http://localhost:8080](http://localhost:8080), you will, of
course, see `Good morning, world!`. You can also try it in the [Dream
Playground](http://dream.as/1-hello).
course, see `Good morning, world!`.
<br>
If you'd like to copy out the server binary, you can do it like this:
<pre><code><b>$ npx esy cp '#{self.target_dir}/default/hello.exe' .
<pre><code><b>$ cp _build/default/hello.exe .
</b></code></pre>
The name will change as you go through the tutorial examples. It's always the
@ -41,19 +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-esy`**](../w-esy#files) gives more detail on the [esy](https://esy.sh/)
packaging.
- [**`w-fswatch`**](../w-fswatch#files) sets up a primitive 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

@ -1,5 +1,3 @@
(executable
(name hello)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./hello.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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
@ -19,7 +19,7 @@ let () =
However, as you can see, the more middlewares we stack on top of each other
like this, the more parentheses and indentation we will end up with! To keep
the code tidy, we use `@@`, the
[standard OCaml operator](https://caml.inria.fr/pub/docs/manual-ocaml/libref/Stdlib.html#VAL(@@)) for calling functions without parentheses. So, the [actual
[standard OCaml operator](https://v2.ocaml.org/api/Stdlib.html#VAL(@@)) for calling functions without parentheses. So, the [actual
code](https://github.com/aantron/dream/blob/master/example/2-middleware/middleware.ml)
in this example looks like this:
@ -33,15 +33,14 @@ let () =
<br>
When you run this server and visit
[http://localhost:8080](http://localhost:8080)
[[playground](http://dream.as/2-middleware)], you get much more interesting
[http://localhost:8080](http://localhost:8080), you get much more interesting
(and colorful!) output:
![Dream log example](https://raw.githubusercontent.com/aantron/dream/master/docs/asset/log-sanitized.png)
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.
@ -49,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. -->
@ -65,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

@ -1,5 +1,3 @@
(executable
(name middleware)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./middleware.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -26,15 +26,13 @@ let () =
```
<pre><code><b>$ cd example/3-router</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./router.exe</b></code></pre>
<br>
This is also our first dynamic site! A request to `/echo/foo` gets the response
`foo`, and a request to `/echo/bar` gets `bar`! Try it in the
[playground](http://dream.as/3-router/echo/foo) &mdash; once the server loads,
edit the URL in the right pane to visit `/echo/bar`.
`foo`, and a request to `/echo/bar` gets `bar`!
The syntax `:word` in a route creates a path parameter, which can be read with
[`Dream.param`](https://aantron.github.io/dream/#val-param).
@ -44,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 -->
@ -65,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

@ -1,5 +1,3 @@
(executable
(name router)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./router.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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,8 +4,7 @@
This example shows how easy it is to define a custom middleware,
`count_requests`. It exposes the request count at
[http://localhost:8080/](http://localhost:8080/)
[[playground](http://dream.as/4-counter)], in a sort of dashboard:
[http://localhost:8080/](http://localhost:8080/), in a sort of dashboard:
```ocaml
let count = ref 0
@ -24,8 +23,8 @@ let () =
]
```
<pre><code><b>$ cd example/4-counter</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./counter.exe</b></code></pre>
<br>
@ -38,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

@ -1,5 +1,3 @@
(executable
(name counter)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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
@ -41,10 +41,8 @@ let () =
```
<pre><code><b>$ cd example/5-promise</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
Try it in the [playground](http://dream.as/5-promise).
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./promise.exe</b></code></pre>
<br>
@ -93,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

@ -2,5 +2,3 @@
(name promise)
(libraries dream)
(preprocess (pps lwt_ppx)))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./promise.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -21,10 +21,8 @@ let () =
```
<pre><code><b>$ cd example/6-echo</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
...or run it in the [playground](http://dream.as/6-echo).
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./echo.exe</b></code></pre>
<br>
@ -48,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
@ -64,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

@ -2,5 +2,3 @@
(name echo)
(libraries dream)
(preprocess (pps lwt_ppx)))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./echo.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -31,8 +31,8 @@ let () =
```
<pre><code><b>$ cd example/7-template</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./template.exe</b></code></pre>
<br>
@ -54,7 +54,7 @@ file to run the template preprocessor:
<br>
The substitution, `<%s param %>`, uses
[`Printf` conversion specifications](https://caml.inria.fr/pub/docs/manual-ocaml/libref/Printf.html)
[`Printf` conversion specifications](https://v2.ocaml.org/api/Printf.html)
from the standard library. So, you can do things like this:
- `<%i my_int %>` to print an OCaml `int`.
@ -84,15 +84,11 @@ already escaped, or if it is safe for some other reason. But be careful!
To show the danger, let's launch a **script injection (XSS) attack** against
this tiny Web app! First, go to
[`template.eml.ml`](https://github.com/aantron/dream/blob/master/example/7-template/template.eml.ml#L4),
change the substitution to `<%s! param %>`, and restart the app. You can also
make the edit in the [playground](http://dream.as/7-template/foo). Then,
visit
change the substitution to `<%s! param %>`, and restart the app. Then, visit
this highly questionable URL:
[http://localhost:8080/%3Cscript%3Ealert(%22Impossible!%22)%3C%2Fscript%3E](http://localhost:8080/%3Cscript%3Ealert(%22Impossible!%22)%3C%2Fscript%3E)
If you are using the playground, change the host and port accordingly.
This URL will cause our Web app to display an alert box, which we, as the
developers, did not intend!
@ -129,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

@ -6,5 +6,3 @@
(targets template.ml)
(deps template.eml.ml)
(action (run dream_eml %{deps} --workspace %{workspace_root})))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./template.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -23,18 +23,17 @@ let () =
```
<pre><code><b>$ cd example/8-debug</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./debug.exe</b></code></pre>
<br>
The rest of the app just adds two routes for triggering two kinds of
failures that the debugger will detail. Visit
[http://localhost:8080/bad](http://localhost:8080/bad)
[[playground](http://dream.as/8-debug/bad)] to trigger a `400 Bad Request`
response, and [http://localhost:8080/fail](http://localhost:8080/fail)
[[playground](http://dream.as/8-debug/fail)] to trigger an exception. The
debugger will show reports like this:
[http://localhost:8080/bad](http://localhost:8080/bad) to trigger a
`400 Bad Request` response, and
[http://localhost:8080/fail](http://localhost:8080/fail) to trigger an
exception. The debugger will show reports like this:
```
Failure("The Web app failed!")
@ -95,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 -->
@ -105,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

@ -1,5 +1,3 @@
(executable
(name debug)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./debug.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -33,10 +33,8 @@ let () =
```
<pre><code><b>$ cd example/9-error</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
Try it in the [playground](http://dream.as/9-error).
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./error.exe</b></code></pre>
<br>
@ -65,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. -->
@ -82,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

@ -6,5 +6,3 @@
(targets error.ml)
(deps error.eml.ml)
(action (run dream_eml %{deps} --workspace %{workspace_root})))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -17,4 +17,4 @@ let my_error_template _error debug_info suggested_response =
let () =
Dream.run ~error_handler:(Dream.error_template my_error_template)
@@ Dream.logger
@@ Dream.not_found
@@ fun _ -> Dream.empty `Not_Found

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./error.exe"
}
}

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,48 +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-fswatch`**](w-fswatch#files) &nbsp;&mdash;&nbsp; sets up a development
watcher using fswatch.
- [**`w-live-reload`**](w-live-reload#files) &nbsp;&mdash;&nbsp; a simple
- [**`w-watch`**](w-watch#folders-and-files) &nbsp;&mdash;&nbsp; sets up a development
watcher.
- [**`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 reverse proxy.
- [**`w-tyxml`**](w-tyxml#files) &nbsp;&mdash;&nbsp; uses TyXML for type-checked
- [**`w-nginx`**](w-nginx#folders-and-files) &nbsp;&mdash;&nbsp; uses nginx as a
reverse proxy.
- [**`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>
@ -166,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

@ -25,13 +25,12 @@ let () =
```
<pre><code><b>$ cd example/a-log</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./log.exe</b></code></pre>
<br>
If you visit [http://localhost:8080](http://localhost:8080)
[[playground](http://dream.as/a-log)] and then
If you visit [http://localhost:8080](http://localhost:8080) and then
[http://localhost:8080/fail](http://localhost:8080/fail), you will find these
messages in the log, between the others:
@ -41,7 +40,7 @@ messages in the log, between the others:
```
Note that this is on `stderr`. As you can see, the functions take
[`Printf`-style format strings](https://caml.inria.fr/pub/docs/manual-ocaml/libref/Printf.html),
[`Printf`-style format strings](https://v2.ocaml.org/api/Printf.html),
so you can quickly print values of various types to the log.
<br>
@ -77,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>

14
example/a-log/a-log.opam Normal file
View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -1,5 +1,3 @@
(executable
(name log)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./log.exe"
}
}

View File

@ -23,13 +23,13 @@ let () =
```
<pre><code><b>$ cd example/b-session</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./session.exe</b></code></pre>
<br>
The first time you access the app [[playground](http://dream.as/b-session)], it
“logs you in” by saving you user name in a session. The session manager,
The first time you access the app, it “logs you in” by saving you user name in
a session. The session manager,
[`Dream.memory_sessions`](https://aantron.github.io/dream/#val-memory_sessions),
a middleware, adds a `dream.session` cookie to the response, containing the
session key. The next time you access the app, the session is looked up again
@ -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

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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,5 +2,3 @@
(name session)
(libraries dream)
(preprocess (pps lwt_ppx)))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./session.exe"
}
}

View File

@ -24,15 +24,14 @@ let () =
```
<pre><code><b>$ cd example/c-cookie</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./cookie.exe</b></code></pre>
<br>
The first time you access this app [[playground](http://dream.as/c-cookie)], it
sets up a language preference, `ut-OP`. This string is sent to the client in a
`ui.language` cookie. On the next request, the client sends it back. The app
retrieves and displays it.
The first time you access this app, it sets up a language preference, `ut-OP`.
This string is sent to the client in a `ui.language` cookie. On the next
request, the client sends it back. The app retrieves and displays it.
<br>
@ -97,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

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -1,5 +1,3 @@
(executable
(name cookie)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./cookie.exe"
}
}

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
@ -46,10 +46,8 @@ let () =
```
<pre><code><b>$ cd example/d-form</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
Try it in the [playground](http://dream.as/d-form).
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./form.exe</b></code></pre>
<br>
@ -102,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

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -7,5 +7,3 @@
(targets form.ml)
(deps form.eml.ml)
(action (run dream_eml %{deps} --workspace %{workspace_root})))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./form.exe"
}
}

View File

@ -10,6 +10,8 @@ converter between JSON and an OCaml data type. We then create a little server
that listens for JSON of the right shape, and echoes back its `message` field:
```ocaml
open Ppx_yojson_conv_lib.Yojson_conv.Primitives
type message_object = {
message : string;
} [@@deriving yojson]
@ -47,24 +49,21 @@ To get this working, we have to add `ppx_yojson_conv` to our
</code></pre>
and to
[`esy.json`](https://github.com/aantron/dream/blob/master/example/e-json/esy.json):
[`json.opam`](https://github.com/aantron/dream/blob/master/example/e-json/e-json.opam):
<pre><code>{
"dependencies": {
"@opam/dream": "aantron/dream:dream.opam",
"@opam/dune": "^2.0",
<b>"@opam/ppx_yojson_conv": "*",</b>
"ocaml": "4.12.x"
}
<pre><code>depends: [
"ocaml" {>= "4.08.0"}
"dream"
"dune" {>= "2.0.0"}
<b>"ppx_yojson_conv"</b>
]
</code></pre>
The build commands, as always, are:
<pre><code><b>$ cd example/e-json</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
You can try this example in the [playground](http://dream.as/e-json).
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./json.exe</b></code></pre>
<br>
@ -113,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

@ -2,5 +2,3 @@
(name json)
(libraries dream)
(preprocess (pps lwt_ppx ppx_yojson_conv)))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -0,0 +1,15 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"dream"
"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

@ -1,19 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"@opam/ppx_yojson_conv": "*",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./json.exe"
}
}

View File

@ -1,3 +1,5 @@
open Ppx_yojson_conv_lib.Yojson_conv.Primitives
type message_object = {
message : string;
} [@@deriving yojson]

View File

@ -5,8 +5,8 @@
Run this example:
<pre><code><b>$ cd example/f-static</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./static.exe</b></code></pre>
...and visit
[http://localhost:8080/static/static.ml](http://localhost:8080/static/static.ml).
@ -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

@ -1,5 +1,3 @@
(executable
(name static)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./static.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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

@ -51,13 +51,12 @@ let () =
```
<pre><code><b>$ cd example/g-upload</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./upload.exe</b></code></pre>
<br>
The page shown after uploading looks like this
[[playground](http://dream.as/g-upload)]:
The page shown after uploading looks like this:
```
foo.png, 663959 bytes
@ -75,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>
@ -85,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
@ -110,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

@ -7,5 +7,3 @@
(targets upload.ml)
(deps upload.eml.ml)
(action (run dream_eml %{deps} --workspace %{workspace_root})))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./upload.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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
@ -67,13 +67,13 @@ let () =
```
<pre><code><b>$ cd example/h-sql</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./sql.exe</b></code></pre>
<br>
Try visiting [http://localhost:8080](http://localhost:8080)
[[playground](http://dream.as/h-sql)] and leaving some comments!
Try visiting [http://localhost:8080](http://localhost:8080) and leaving some
comments!
![Comments](https://raw.githubusercontent.com/aantron/dream/master/docs/asset/sql.png)
@ -82,7 +82,7 @@ Try visiting [http://localhost:8080](http://localhost:8080)
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>
@ -118,18 +118,21 @@ We also had to make an addition to our
</pre>
...and to
[`esy.json`](https://github.com/aantron/dream/blob/master/example/h-sql/esy.json):
[`sql.opam`](https://github.com/aantron/dream/blob/master/example/h-sql/esy.json):
<pre>"dependencies": {
<b>"@opam/caqti-driver-sqlite3": "^1.7.0"</b>
}
<pre>depends: [
<b>"caqti-driver-sqlite3" {>= "1.7.0"}</b>
"ocaml" {>= "4.08.0"}
"dream"
"dune" {>= "2.0.0"}
]
</pre>
<br>
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
@ -153,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

@ -7,5 +7,3 @@
(targets sql.ml)
(deps sql.eml.ml)
(action (run dream_eml %{deps} --workspace %{workspace_root})))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,19 +0,0 @@
{
"dependencies": {
"@opam/caqti-driver-sqlite3": "^1.7.0",
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./sql.exe"
}
}

15
example/h-sql/h-sql.opam Normal file
View File

@ -0,0 +1,15 @@
opam-version: "2.0"
depends: [
"caqti-driver-sqlite3" {>= "1.7.0"}
"ocaml" {>= "4.08.0"}
"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 @@ 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

View File

@ -58,13 +58,13 @@ let () =
```
<pre><code><b>$ cd example/i-graphql</b>
<b>$ npm install esy && npx esy</b>
<b>$ npx esy start</b></code></pre>
<b>$ opam install --deps-only --yes .</b>
<b>$ dune exec --root . ./graphql.exe</b></code></pre>
<br>
Visit [http://localhost:8080](http://localhost:8080)
[[playground](http://dream.as/i-graphql)], and you can interact with the schema:
Visit [http://localhost:8080](http://localhost:8080), and you can interact with
the schema:
![GraphiQL](https://raw.githubusercontent.com/aantron/dream/master/docs/asset/graphiql.png)
@ -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

@ -1,5 +1,3 @@
(executable
(name graphql)
(libraries dream))
(data_only_dirs _esy esy.lock lib node_modules)

View File

@ -1,18 +0,0 @@
{
"dependencies": {
"@opam/conf-libssl": "3",
"@opam/dream": "1.0.0~alpha4",
"@opam/dune": "^2.0",
"ocaml": "4.12.x"
},
"devDependencies": {
"@opam/ocaml-lsp-server": "*"
},
"resolutions": {
"@opam/conf-libev": "esy-packages/libev:package.json#0b5eb6685b688649045aceac55dc559f6f21b829",
"esy-openssl": "esy-packages/esy-openssl#619ae2d46ca981ec26ab3287487ad98b157a01d1"
},
"scripts": {
"start": "dune exec --root . ./graphql.exe"
}
}

View File

@ -0,0 +1,14 @@
opam-version: "2.0"
depends: [
"ocaml" {>= "4.08.0"}
"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