diff --git a/_overviews/toolkit/web-server-cookies-and-decorators.md b/_overviews/toolkit/web-server-cookies-and-decorators.md index a4826095f..ae4171cf0 100644 --- a/_overviews/toolkit/web-server-cookies-and-decorators.md +++ b/_overviews/toolkit/web-server-cookies-and-decorators.md @@ -11,18 +11,18 @@ next-page: ## Using cookies -Cookies are saved by adding them to the `cookies` parameter of `cask.Response` constructor. +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. +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. -Cookies can be read either with a method parameter with `cask.Cookie` type or by accessing `cask.Request` directly. -If using the former method, names of parameters have to match the names of cookies. If a cookie with 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 user logs in. +Cookies can be read either with a method parameter of `cask.Cookie` type or by accessing `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. -To delete a cookie set its `expires` parameter to an instant in the past, for example `Instant.EPOCH`. +To delete a cookie, set its `expires` parameter to an instant in the past, for example `Instant.EPOCH`. {% tabs web-server-cookies-1 class=tabs-scala-version %} {% tab 'Scala 2' %} @@ -144,7 +144,7 @@ object MyApp extends cask.MainRoutes: 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. -In this example, the `loggedIn` decorator is used for checking if user is logged in before accessing the `/decorated` +In this example, the `loggedIn` decorator is used to check if the user is logged in before accessing the `/decorated` endpoint. The decorator class can pass additional arguments to the decorated endpoint using a map. The passed arguments are available diff --git a/_overviews/toolkit/web-server-dynamic.md b/_overviews/toolkit/web-server-dynamic.md index d271ff37c..649cfed8c 100644 --- a/_overviews/toolkit/web-server-dynamic.md +++ b/_overviews/toolkit/web-server-dynamic.md @@ -39,11 +39,11 @@ object MyApp 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, returning 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 `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). -If you want an HTML output being interpreted by the browser, you else need to set the `Content-Type` header manually +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). +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. ### Running the example @@ -71,7 +71,7 @@ In the terminal, the following command will start the server: {% endtab %} {% endtabs %} -Access [the endpoint](http://localhost:8080/time). You should see a result similar to the one below. +Access the endpoint at [http://localhost:8080/time](http://localhost:8080/time). You should see a result similar to the one below. ``` Current date is: 2024-07-22T09:07:05.752534+02:00[Europe/Warsaw] @@ -79,7 +79,7 @@ Current date is: 2024-07-22T09:07:05.752534+02:00[Europe/Warsaw] ## Using path segments -Cask gives you the ability to access segments of the URL path withing the endpoint function. +Cask gives you the ability to access segments of the URL path within the endpoint function. Building on the example above, you can add a segment to specify that the endpoint should return the date and time in a given city. @@ -129,10 +129,10 @@ object MyApp extends cask.MainRoutes: {% endtabs %} In the example above, the `:city` segment in `/time/:city` is available through the `city` argument of the endpoint method. -The name of the argument must be identical to the segment name. The `getZoneIdForCity` helper method find the timezone for -a given city and then the current date and time is translated to that timezone. +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](http://localhost:8080/time/Paris) (notice the `Paris` segment in the URL) will result with: +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] ``` @@ -233,5 +233,5 @@ object MyApp extends cask.MainRoutes: {% endtab %} {% endtabs %} -Here we get the text of response and wrap it in a Scalatags template. Notice that the return type changed from `String` +Here we get the text of the response and wrap it in a Scalatags template. Notice that the return type changed from `String` to `doctype`. \ No newline at end of file diff --git a/_overviews/toolkit/web-server-input.md b/_overviews/toolkit/web-server-input.md index 61dd9d0f1..168fa6658 100644 --- a/_overviews/toolkit/web-server-input.md +++ b/_overviews/toolkit/web-server-input.md @@ -163,8 +163,8 @@ object MyApp extends cask.MainRoutes: {% endtab %} {% endtabs %} -In this example the JSON is merely converted to `String`, check the [*uPickle tutorial*](/toolkit/json-intro.html) for more information -on what can be done with `ujson.Value` type. +In this example the JSON is merely converted to `String`. Check the [*uPickle tutorial*](/toolkit/json-intro.html) for more information +on what can be done with the `ujson.Value` type. Send a POST request. ```shell @@ -180,11 +180,11 @@ The server will respond with: ## Handling JSON-encoded output -Cask endpoint can return JSON objects returned by uPickle library functions. Cask will automatically handle the `ujson.Value` +Cask endpoints can return JSON objects returned by uPickle library functions. Cask will automatically handle the `ujson.Value` type and set the `Content-Type` header to `application/json`. -In this example `TimeData` case class stores the information about the time zone and current time in a chosen -location. To serialize a case class into JSON, use type class derivation or define the serializer in its companion object in case of Scala 2. +In this example, the `TimeData` case class stores the information about the time zone and current time in a chosen +location. To serialize a case class into JSON, use type class derivation or define the serializer in its companion object in the case of Scala 2. {% tabs web-server-input-4 class=tabs-scala-version %} {% tab 'Scala 2' %} @@ -216,7 +216,7 @@ object MyApp extends cask.MainRoutes { {% tab 'Scala 3' %} ```scala object MyApp extends cask.MainRoutes { - import upickle.default.{ReadWriter, macroRW, writeJs} + import upickle.default.{ReadWriter, writeJs} case class TimeData(timezone: Option[String], time: String) derives ReadWriter private def getZoneIdForCity(city: String): Option[ZoneId] = diff --git a/_overviews/toolkit/web-server-intro.md b/_overviews/toolkit/web-server-intro.md index 653ac6c71..4154247ac 100644 --- a/_overviews/toolkit/web-server-intro.md +++ b/_overviews/toolkit/web-server-intro.md @@ -9,15 +9,15 @@ next-page: web-server-static Cask is an HTTP micro-framework, providing a simple and flexible way to build web applications. -Its main focus is on the ease of use, which makes it ideal for newcomers, at cost of eschewing some features other +Its main focus is on the ease of use, which makes it ideal for newcomers, at the cost of eschewing some features other frameworks provide, like asynchronicity. -To define an endpoint it's enough to annotate a function with an appropriate annotation, specifying the request path. -Cask allows for building the response manually using tools the Cask library provides, specifying the content, headers, -status code etc. An endpoint function can also just return a string, [uPickle](https://com-lihaoyi.github.io/upickle/) JSON type, or a [Scalatags](https://com-lihaoyi.github.io/scalatags/) +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 comes bundled with uPickle library for handling JSONs, supports WebSockets and allows for extending endpoints with +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. {% include markdown.html path="_markdown/install-cask.md" %} diff --git a/_overviews/toolkit/web-server-query-parameters.md b/_overviews/toolkit/web-server-query-parameters.md index d53d34eaf..e2576f935 100644 --- a/_overviews/toolkit/web-server-query-parameters.md +++ b/_overviews/toolkit/web-server-query-parameters.md @@ -10,11 +10,11 @@ next-page: web-server-input {% include markdown.html path="_markdown/install-cask.md" %} Query parameters are the key-value pairs coming after the question mark in a URL. They can be used for filtering, -sorting or limiting the results provided by the server. For example, in `/time?city=Paris` URL, the `city` part -is the name of a parameter and `Paris` is its value. Cask allows for reading the query parameters by defining an endpoint +sorting or limiting the results provided by the server. For example, in the `/time?city=Paris` URL, the `city` part +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 +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. {% tabs web-server-query-1 class=tabs-scala-version %} @@ -67,7 +67,7 @@ object MyApp extends cask.MainRoutes: {% endtab %} {% endtabs %} -Run the example as before and access the [endpoint](http://localhost:8080/time?city=Paris) (notice the `?city=Paris` part of the URL). +Run the example as before and access the endpoint at [http://localhost:8080/time?city=Paris](http://localhost:8080/time?city=Paris). You should get a result similar to the following one. ``` Current date is: 2024-07-22T10:08:18.218736+02:00[Europe/Paris] diff --git a/_overviews/toolkit/web-server-static.md b/_overviews/toolkit/web-server-static.md index 1d5cb1e1c..12c8e2286 100644 --- a/_overviews/toolkit/web-server-static.md +++ b/_overviews/toolkit/web-server-static.md @@ -11,13 +11,13 @@ 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 +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. -To create a static file serving endpoint we need two things: an HTML file with the page content and a function that -points out to the location of the file. +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. -Create a minimal HTML file named `hello.html` with following contents. +Create a minimal HTML file named `hello.html` with the following contents. ```html @@ -89,18 +89,18 @@ object Example extends cask.MainRoutes: {% endtab %} {% endtabs %} -In the example above, `@cask.staticFiles` instructs the server to look for files accessed at `/static` path in the +In the example above, `@cask.staticFiles` instructs the server to look for files accessed at the `/static` path in the `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. -The `Example` object inherits from `cask.MainRoutes` class, providing the main function starting the server. The `initialize()` -method call initializes the server routes, i.e. the association between URL paths and the code that handles them. +The `Example` object inherits from the `cask.MainRoutes` class, providing 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 -The `@cask.staticResources` annotation works in the same way as `@cask.staticFiles` used above with the difference that +The `@cask.staticResources` annotation works in the same way as the `@cask.staticFiles` used above, with the difference that the path returned by the endpoint method describes the location of files _inside_ the resources directory. Since the previous example conveniently used the resources directory, it can be simplified with `@cask.staticResources`. @@ -126,9 +126,9 @@ object Example extends cask.MainRoutes: {% endtab %} {% endtabs %} -In the endpoint method the location is set to `"."`, telling the server that the files are available directly in the +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 -for placing your HTML files in `static` directory inside the resources directory or use different directories to sort out +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. ## Running the example diff --git a/_overviews/toolkit/web-server-websockets.md b/_overviews/toolkit/web-server-websockets.md index b5d06bd23..d0343ad6a 100644 --- a/_overviews/toolkit/web-server-websockets.md +++ b/_overviews/toolkit/web-server-websockets.md @@ -11,11 +11,11 @@ next-page: web-server-cookies-and-decorators 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 -attempt of forming a WebSocket connection. +attempt at forming a WebSocket connection. -The connection can also be closed by sending `cask.Ws.close()` message through the WebSocket channel. +The connection can also be closed by sending a `cask.Ws.close()` message through the WebSocket channel. -Create an HTML file named `websockets.html` with the following content and place it in `resources ` directory. +Create an HTML file named `websockets.html` with the following content and place it in the `resources ` directory. ```html @@ -52,9 +52,9 @@ Create an HTML file named `websockets.html` with the following content and place ``` The JavaScript code opens a WebSocket connection using the `ws://localhost:8080/websocket` endpoint. The `ws.onmessage` -event handler is executed when server pushes a message to the browser and `ws.onclose` when the connection is closed. +event handler is executed when the server pushes a message to the browser and `ws.onclose` when the connection is closed. -Create an endpoint for serving static files using `@cask.staticResources` annotation and the endpoint for handling +Create an endpoint for serving static files using the `@cask.staticResources` annotation and an endpoint for handling the WebSocket connection. {% tabs web-server-websocket-1 class=tabs-scala-version %} @@ -109,5 +109,5 @@ def websocket(): cask.WsHandler = {% 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 a name of city and return the current time there. If server +WebSocket channel to send messages. In this example, we receive the name of a city and return the current time there. If server receives an empty message, the connection is closed. \ No newline at end of file