Skip to content

Add Cask tutorials #3056

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Grammar fixes
  • Loading branch information
gkepka committed Oct 1, 2024
commit 4d4264f47e2113a2290135f9560dd9721c9d81d1
2 changes: 1 addition & 1 deletion _includes/_markdown/install-cask.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
{% tabs cask-install class=tabs-build-tool %}

{% tab 'Scala CLI' %}
You can declare dependency on Cask with `using` directive:
You can declare a dependency on Cask with the following `using` directive:
```scala
//> using dep "com.lihaoyi::cask::0.9.2"
```
Expand Down
8 changes: 4 additions & 4 deletions _overviews/toolkit/web-server-cookies-and-decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ next-page:
Cookies are saved by adding them to the `cookies` parameter of the `cask.Response` constructor.

In this example, we are building a rudimentary authentication service. The `getLogin` method provides a form where
username and password can be inputted. The `postLogin` reads the credentials and, if they match the expected ones, a session
identifier is generated, saved in the application state, and sends back a cookie with the identifier.
the user can enter their username and password. The `postLogin` method reads the credentials. If they match the expected ones, it generates a session
identifier is generated, saves it in the application state, and sends back a cookie with the identifier.

Cookies can be read either with a method parameter of `cask.Cookie` type or by accessing `cask.Request` directly.
Cookies can be read either with a method parameter of `cask.Cookie` type or by accessing the `cask.Request` directly.
If using the former method, the names of parameters have to match the names of cookies. If a cookie with a matching name is not
found, an error response will be returned. In the `checkLogin` function, the former method is used, as the cookie is not
present before the user logs in.
Expand Down Expand Up @@ -142,7 +142,7 @@ object Example extends cask.MainRoutes:
## Using decorators

Decorators can be used for extending endpoints functionality with validation or new parameters. They are defined by extending
`cask.RawDecorator` class and then used as annotations.
`cask.RawDecorator` class. They are used as annotations.

In this example, the `loggedIn` decorator is used to check if the user is logged in before accessing the `/decorated`
endpoint.
Expand Down
10 changes: 5 additions & 5 deletions _overviews/toolkit/web-server-dynamic.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ next-page: web-server-query-parameters

## Serving dynamically generated content

You can create an endpoint returning dynamically generated content with `@cask.get` annotation.
You can create an endpoint returning dynamically generated content with the `@cask.get` annotation.

{% tabs web-server-dynamic-1 class=tabs-scala-version %}
{% tab 'Scala 2' %}
Expand Down Expand Up @@ -39,10 +39,10 @@ object Example extends cask.MainRoutes:
{% endtab %}
{% endtabs %}

The example above creates an endpoint, returning the current date and time available at `/time`. The exact response will be
The example above creates an endpoint that returns the current date and time available at `/time`. The exact response will be
recreated every time you refresh the webpage.

Since the endpoint method has the `String` output type, the result will be sent with `text/plain` [content type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type).
Since the endpoint method has the `String` output type, the result will be sent with the `text/plain` [content type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type).
If you want an HTML output to be interpreted by the browser, you will need to set the `Content-Type` header manually
or [use the Scalatags templating library](/toolkit/web-server-dynamic.html#using-html-templates), supported by Cask.

Expand Down Expand Up @@ -132,7 +132,7 @@ In the example above, the `:city` segment in `/time/:city` is available through
The name of the argument must be identical to the segment name. The `getZoneIdForCity` helper method finds the timezone for
a given city, and then the current date and time are translated to that timezone.

Accessing the endpoint at[http://localhost:8080/time/Paris](http://localhost:8080/time/Paris) will result in:
Accessing the endpoint at [http://localhost:8080/time/Paris](http://localhost:8080/time/Paris) will result in:
```
Current date is: 2024-07-22T09:08:33.806259+02:00[Europe/Paris]
```
Expand All @@ -143,7 +143,7 @@ Consult the [documentation](https://com-lihaoyi.github.io/cask/index.html#variab

## Using HTML templates

To create an HTML response, you can combine Cask code with the [Scalatags](https://com-lihaoyi.github.io/scalatags/) templating library.
To create an HTML response, you can combine Cask with the [Scalatags](https://com-lihaoyi.github.io/scalatags/) templating library.

Import the Scalatags library:

Expand Down
14 changes: 7 additions & 7 deletions _overviews/toolkit/web-server-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ next-page: web-server-websockets

## Handling form-encoded input

To create an endpoint that handles the data provided in an HTML form, use `cask.postForm` annotation, give the endpoint method arguments
To create an endpoint that handles the data provided in an HTML form, use the `@cask.postForm` annotation. Add arguments to the endpoint method
with names corresponding to names of fields in the form and set the form method to `post`.

{% tabs web-server-input-1 class=tabs-scala-version %}
Expand Down Expand Up @@ -78,15 +78,15 @@ object Example extends cask.MainRoutes:
{% endtabs %}

In this example we create a form asking for name and surname of a user and then redirect the user to a greeting page. Notice the
use of `cask.Response`. The `cask.Response` type allows user to set the status code, headers and cookies. The default
content type in case of `String` returning endpoint method is `text/plain`, set it to `text/html` in order for browser to display the form correctly.
use of `cask.Response`. The `cask.Response` type allows the user to set the status code, headers and cookies. The default
content type for an endpoint method returning a `String` is `text/plain`. Set it to `text/html` in order for the browser to display the form correctly.

The `formEndpoint` endpoint reads the form data using `name` and `surname` parameters. The names of parameters must
The `formEndpoint` endpoint reads the form data using the `name` and `surname` parameters. The names of parameters must
be identical to the field names of the form.

## Handling JSON-encoded input

JSON fields are handled in the same way as form fields, except that `cask.PostJson` annotation is used. The fields
JSON fields are handled in the same way as form fields, except that we use the `@cask.PostJson` annotation. The fields
will be read into the endpoint method arguments.

{% tabs web-server-input-2 class=tabs-scala-version %}
Expand Down Expand Up @@ -130,9 +130,9 @@ Hello John Smith

The endpoint will accept JSONs that have only the fields with names specified as the endpoint method arguments. If there
are more fields than expected, some fields are missing or have an incorrect data type, an error message
will be returned with 400 response code.
will be returned with the response code 400.

To handle the case when the fields of the JSON are not known in advance, you can use argument with the `ujson.Value` type
To handle the case when the fields of the JSON are not known in advance, you can use an argument with the `ujson.Value` type,
from uPickle library.

{% tabs web-server-input-3 class=tabs-scala-version %}
Expand Down
6 changes: 3 additions & 3 deletions _overviews/toolkit/web-server-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ Its main focus is on the ease of use, which makes it ideal for newcomers, at the
frameworks provide, like asynchronicity.

To define an endpoint it's enough to annotate a function with an annotation specifying the request path.
Cask allows for building the response manually using tools Cask library provides, specifying the content, headers,
status code, etc. An endpoint function can also just return a string, a [uPickle](https://com-lihaoyi.github.io/upickle/) JSON type, or a [Scalatags](https://com-lihaoyi.github.io/scalatags/)
template and Cask will automatically create a response, setting all the necessary headers.
Cask allows for building the response manually using tools that the library provides, specifying the content, headers,
status code, etc. An endpoint function can also return a string, a [uPickle](https://com-lihaoyi.github.io/upickle/) JSON type, or a [Scalatags](https://com-lihaoyi.github.io/scalatags/)
template. In that case, Cask will automatically create a response with the appropriate headers.

Cask comes bundled with the uPickle library for handling JSONs, supports WebSockets and allows for extending endpoints with
decorators, which can be used to handle authentication or rate limiting.
Expand Down
4 changes: 2 additions & 2 deletions _overviews/toolkit/web-server-query-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ sorting or limiting the results provided by the server. For example, in the `<ho
is the name of a parameter, and `Paris` is its value. Cask allows for reading the query parameters by defining an endpoint
method with arguments matching the names of the expected parameters and not matching any of the URL segments.

In this example, the `city` parameter will be optional, which you specify in Cask by giving the argument `Option` type and
`None` default value. If not provided, the time for the current timezone will be returned.
In this example, we give an `Option` type and the default value `None` to the `city` parameter. This tells Cask that it is optional.
If not provided, the time for the current timezone will be returned.

{% tabs web-server-query-1 class=tabs-scala-version %}
{% tab 'Scala 2' %}
Expand Down
14 changes: 7 additions & 7 deletions _overviews/toolkit/web-server-static.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ next-page: web-server-dynamic
## Serving a static file

An endpoint is a specific URL where a particular webpage can be accessed. In Cask, an endpoint is a function returning the
webpage data together with an annotation describing the URL it's available at.
webpage data, together with an annotation describing its URL.

To create a static file serving endpoint, we need two things: an HTML file with the page content and a function that
points out the location of the file.
To create an endpoint serving static files, we need two things: an HTML file with the page content and a function that
points to that file.

Create a minimal HTML file named `hello.html` with the following contents.

Expand Down Expand Up @@ -65,7 +65,7 @@ example
{% endtabs %}

The `@cask.staticFiles` annotation specifies at which path the webpage will be available. The endpoint function returns
the location in which the file can be found.
the location of the file.

{% tabs web-server-static-2 class=tabs-scala-version %}
{% tab 'Scala 2' %}
Expand Down Expand Up @@ -93,9 +93,9 @@ In the example above, `@cask.staticFiles` instructs the server to look for files
`src/main/resources` directory. Cask will match any subpath coming after `/static` and append it to the directory path.
If you access the `/static/hello.html` file, it will serve the file available at `src/main/resources/hello.html`.
The directory path can be any path available to the server, relative or not. If the requested file cannot be found in the
specified location, a 404 response with an error message will be returned instead.
specified location, the server will return a 404 response with an error message.

The `Example` object inherits from the `cask.MainRoutes` class, providing the main function that starts the server. The `initialize()`
The `Example` object inherits from the `cask.MainRoutes` class. It provides the main function that starts the server. The `initialize()`
method call initializes the server routes, i.e., the association between URL paths and the code that handles them.

### Using the resources directory
Expand Down Expand Up @@ -127,7 +127,7 @@ object Example extends cask.MainRoutes:
{% endtabs %}

In the endpoint method, the location is set to `"."`, telling the server that the files are available directly in the
resources directory. In general, you can use any nested location within the resources directory, for instance you could opt
resources directory. In general, you can use any nested location within the resources directory. For instance, you could opt
for placing your HTML files in the `static` directory inside the resources directory or using different directories to sort out
files used by different endpoints.

Expand Down
8 changes: 4 additions & 4 deletions _overviews/toolkit/web-server-websockets.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ next-page: web-server-cookies-and-decorators

{% include markdown.html path="_markdown/install-cask.md" %}

You can create a WebSocket endpoint by using the `@cask.websocket` annotation. The endpoint method can return either a
`cask.WsHandler` instance defining how the communication should take place, or a `cask.Response`, which rejects the
You can create a WebSocket endpoint with the `@cask.websocket` annotation. The endpoint method should return a
`cask.WsHandler` instance defining how the communication should take place. It can also return a `cask.Response`, which rejects the
attempt at forming a WebSocket connection.

The connection can also be closed by sending a `cask.Ws.close()` message through the WebSocket channel.
Expand Down Expand Up @@ -113,6 +113,6 @@ initialize()
{% endtab %}
{% endtabs %}

In the `cask.WsHandler` we define a `cask.WsActor` which reacts to events (of `cask.util.Ws.Event` type) and uses
WebSocket channel to send messages. In this example, we receive the name of a city and return the current time there. If server
In the `cask.WsHandler` we define a `cask.WsActor`. It reacts to events (of type `cask.util.Ws.Event`) and uses the
WebSocket channel to send messages. In this example, we receive the name of a city and return the current time there. If the server
receives an empty message, the connection is closed.