Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
gkepka committed Sep 8, 2024
1 parent 48431b6 commit 569d5df
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 56 deletions.
40 changes: 20 additions & 20 deletions _overviews/toolkit/web-server-cookies-and-decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ To delete a cookie, set its `expires` parameter to an instant in the past, for e
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap

object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {

val sessionIds = ConcurrentHashMap.newKeySet[String]()

@cask.get("/login")
def getLogin() = {
def getLogin(): cask.Response[String] = {
val html =
"""<!doctype html>
|<html>
Expand All @@ -55,7 +55,7 @@ object MyApp extends cask.MainRoutes {
}

@cask.postForm("/login")
def postLogin(name: String, password: String) = {
def postLogin(name: String, password: String): cask.Response[String] = {
if (name == "user" && password == "password") {
val sessionId = UUID.randomUUID().toString
sessionIds.add(sessionId)
Expand All @@ -66,7 +66,7 @@ object MyApp extends cask.MainRoutes {
}

@cask.get("/check")
def checkLogin(request: cask.Request) = {
def checkLogin(request: cask.Request): String = {
val sessionId = request.cookies.get("sessionId")
if (sessionId.exists(cookie => sessionIds.contains(cookie.value))) {
"You are logged in"
Expand All @@ -90,12 +90,12 @@ object MyApp extends cask.MainRoutes {
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap

object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:

val sessionIds = ConcurrentHashMap.newKeySet[String]()

@cask.get("/login")
def getLogin() =
def getLogin(): cask.Response[String] =
val html =
"""<!doctype html>
|<html>
Expand All @@ -113,24 +113,24 @@ object MyApp extends cask.MainRoutes:
cask.Response(data = html, headers = Seq("Content-Type" -> "text/html"))

@cask.postForm("/login")
def postLogin(name: String, password: String) =
if name == "user" && password == "password":
def postLogin(name: String, password: String): cask.Response[String] =
if name == "user" && password == "password" then
val sessionId = UUID.randomUUID().toString
sessionIds.add(sessionId)
cask.Response(data = "Success!", cookies = Seq(cask.Cookie("sessionId", sessionId)))
else
cask.Response(data = "Authentication failed", statusCode = 401)

@cask.get("/check")
def checkLogin(request: cask.Request) =
val sessionId = request.cookies.get("sessionId")
if sessionId.exists(cookie => sessionIds.contains(cookie.value)):
"You are logged in"
else
"You are not logged in"
@cask.get("/check")
def checkLogin(request: cask.Request): String =
val sessionId = request.cookies.get("sessionId")
if sessionId.exists(cookie => sessionIds.contains(cookie.value)) then
"You are logged in"
else
"You are not logged in"

@cask.get("/logout")
def logout(sessionId: cask.Cookie) =
def logout(sessionId: cask.Cookie): cask.Response[String] =
sessionIds.remove(sessionId.value)
cask.Response(data = "Successfully logged out!", cookies = Seq(cask.Cookie("sessionId", "", expires = Instant.EPOCH)))

Expand All @@ -154,7 +154,7 @@ through the last argument group. Here we are passing the session identifier to a
{% tab 'Scala 2' %}
```scala
class loggedIn extends cask.RawDecorator {
override def wrapFunction(ctx: cask.Request, delegate: Delegate) = {
override def wrapFunction(ctx: cask.Request, delegate: Delegate): Result[Raw] = {
ctx.cookies.get("sessionId") match {
case Some(cookie) if sessionIds.contains(cookie.value) => delegate(Map("sessionId" -> cookie.value))
case _ => cask.router.Result.Success(cask.model.Response("You aren't logged in", 403))
Expand All @@ -164,15 +164,15 @@ class loggedIn extends cask.RawDecorator {

@loggedIn()
@cask.get("/decorated")
def decorated()(sessionId: String) = {
def decorated()(sessionId: String): String = {
s"You are logged in with id: $sessionId"
}
```
{% endtab %}
{% tab 'Scala 3' %}
```scala
class loggedIn extends cask.RawDecorator:
override def wrapFunction(ctx: cask.Request, delegate: Delegate) =
override def wrapFunction(ctx: cask.Request, delegate: Delegate): Result[Raw] =
ctx.cookies.get("sessionId") match
case Some(cookie) if sessionIds.contains(cookie.value) =>
delegate(Map("sessionId" -> cookie.value))
Expand All @@ -182,7 +182,7 @@ class loggedIn extends cask.RawDecorator:

@loggedIn()
@cask.get("/decorated")
def decorated()(sessionId: String) = s"You are logged in with id: $sessionId"
def decorated()(sessionId: String): String = s"You are logged in with id: $sessionId"
```
{% endtab %}
{% endtabs %}
16 changes: 8 additions & 8 deletions _overviews/toolkit/web-server-dynamic.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ You can create an endpoint returning dynamically generated content with `@cask.g
```scala
import java.time.ZonedDateTime

object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {
@cask.get("/time")
def dynamic(): String = s"Current date is: ${ZonedDateTime.now()}"

Expand All @@ -30,7 +30,7 @@ object MyApp extends cask.MainRoutes {
```scala
import java.time.ZonedDateTime

object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:
@cask.get("/time")
def dynamic(): String = s"Current date is: ${ZonedDateTime.now()}"

Expand Down Expand Up @@ -58,9 +58,9 @@ scala-cli run Example.scala
```
{% endtab %}
{% tab 'sbt' %}
In the sbt shell, the following command will start the server:
In the terminal, the following command will start the server:
```
sbt:example> example/run
sbt example/run
```
{% endtab %}
{% tab 'Mill' %}
Expand Down Expand Up @@ -88,7 +88,7 @@ in a given city.
```scala
import java.time.{ZoneId, ZonedDateTime}

object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {

private def getZoneIdForCity(city: String): Option[ZoneId] = {
import scala.jdk.CollectionConverters._
Expand All @@ -111,7 +111,7 @@ object MyApp extends cask.MainRoutes {
```scala
import java.time.{ZoneId, ZonedDateTime}

object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:

private def getZoneIdForCity(city: String): Option[ZoneId] =
import scala.jdk.CollectionConverters.*
Expand Down Expand Up @@ -177,7 +177,7 @@ setting the `Content-Type` header to `text/html`.
import java.time.{ZoneId, ZonedDateTime}
import scalatags.Text.all._

object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {

private def getZoneIdForCity(city: String): Option[ZoneId] = {
import scala.jdk.CollectionConverters._
Expand Down Expand Up @@ -209,7 +209,7 @@ object MyApp extends cask.MainRoutes {
import java.time.{ZoneId, ZonedDateTime}
import scalatags.Text.all.*

object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:

private def getZoneIdForCity(city: String): Option[ZoneId] =
import scala.jdk.CollectionConverters.*
Expand Down
38 changes: 22 additions & 16 deletions _overviews/toolkit/web-server-input.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ with names corresponding to names of fields in the form and set the form method
{% tabs web-server-input-1 class=tabs-scala-version %}
{% tab 'Scala 2' %}
```scala
object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {

@cask.get("/form")
def getForm(): cask.Response = {
def getForm(): cask.Response[String] = {
val html =
"""<!doctype html>
|<html>
Expand Down Expand Up @@ -48,10 +48,10 @@ object MyApp extends cask.MainRoutes {
{% endtab %}
{% tab 'Scala 3' %}
```scala
object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:

@cask.get("/form")
def getForm(): cask.Response =
def getForm(): cask.Response[String] =
val html =
"""<!doctype html>
|<html>
Expand All @@ -78,8 +78,8 @@ object MyApp 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 default returned 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 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.

The `formEndpoint` endpoint reads the form data using `name` and `surname` parameters. The names of parameters must
be identical to the field names of the form.
Expand All @@ -92,7 +92,7 @@ will be read into the endpoint method arguments.
{% tabs web-server-input-2 class=tabs-scala-version %}
{% tab 'Scala 2' %}
```scala
object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {

@cask.postJson("/json")
def jsonEndpoint(name: String, surname: String): String =
Expand All @@ -104,9 +104,9 @@ object MyApp extends cask.MainRoutes {
{% endtab %}
{% tab 'Scala 3' %}
```scala
object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:

@cask.postJson("/json")
@cask.postJson("/json")
def jsonEndpoint(name: String, surname: String): String =
"Hello " + name + " " + surname

Expand Down Expand Up @@ -138,7 +138,7 @@ from uPickle library.
{% tabs web-server-input-3 class=tabs-scala-version %}
{% tab 'Scala 2' %}
```scala
object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {

@cask.postJson("/json")
def jsonEndpoint(value: ujson.Value): String =
Expand All @@ -151,7 +151,7 @@ object MyApp extends cask.MainRoutes {
{% endtab %}
{% tab 'Scala 3' %}
```scala
object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:

@cask.postJson("/json")
def jsonEndpoint(value: ujson.Value): String =
Expand Down Expand Up @@ -189,7 +189,9 @@ location. To serialize a case class into JSON, use type class derivation or defi
{% tabs web-server-input-4 class=tabs-scala-version %}
{% tab 'Scala 2' %}
```scala
object MyApp extends cask.MainRoutes {
import java.time.{ZoneId, ZonedDateTime}

object Example extends cask.MainRoutes {
import upickle.default.{ReadWriter, macroRW, writeJs}
case class TimeData(timezone: Option[String], time: String)
object TimeData {
Expand All @@ -210,12 +212,16 @@ object MyApp extends cask.MainRoutes {
}
writeJs(TimeData(timezone.map(_.toString), time))
}

initialize()
}
```
{% endtab %}
{% tab 'Scala 3' %}
```scala
object MyApp extends cask.MainRoutes {
import java.time.{ZoneId, ZonedDateTime}

object Example extends cask.MainRoutes:
import upickle.default.{ReadWriter, writeJs}
case class TimeData(timezone: Option[String], time: String) derives ReadWriter

Expand All @@ -224,14 +230,14 @@ object MyApp extends cask.MainRoutes {
ZoneId.getAvailableZoneIds.asScala.find(_.endsWith("/" + city)).map(ZoneId.of)

@cask.get("/time_json/:city")
def timeJSON(city: String): ujson.Value = {
def timeJSON(city: String): ujson.Value =
val timezone = getZoneIdForCity(city)
val time = timezone match
case Some(zoneId)=> s"Current date is: ${ZonedDateTime.now().withZoneSameInstant(zoneId)}"
case None => s"Couldn't find time zone for city $city"
writeJs(TimeData(timezone.map(_.toString), time))
}
}

initialize()
```
{% endtab %}
{% endtabs %}
18 changes: 9 additions & 9 deletions _overviews/toolkit/web-server-query-parameters.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ In this example, the `city` parameter will be optional, which you specify in Cas
```scala
import java.time.{ZoneId, ZonedDateTime}

object MyApp extends cask.MainRoutes {
object Example extends cask.MainRoutes {

private def getZoneIdForCity(city: String): Option[ZoneId] = {
import scala.jdk.CollectionConverters._
Expand All @@ -48,19 +48,19 @@ object MyApp extends cask.MainRoutes {
```scala
import java.time.{ZoneId, ZonedDateTime}

object MyApp extends cask.MainRoutes:
object Example extends cask.MainRoutes:

private def getZoneIdForCity(city: String): Option[ZoneId] =
import scala.jdk.CollectionConverters.*
ZoneId.getAvailableZoneIds.asScala.find(_.endsWith("/" + city)).map(ZoneId.of)

@cask.get("/time")
def dynamicWithParam(city: Option[String] = None): String =
city match
case Some(value) => getZoneIdForCity(value) match
case Some(zoneId) => s"Current date is: ${ZonedDateTime.now().withZoneSameInstant(zoneId)}"
case None => s"Couldn't find time zone for city $value"
case None => s"Current date is: ${ZonedDateTime.now()}"
@cask.get("/time")
def dynamicWithParam(city: Option[String] = None): String =
city match
case Some(value) => getZoneIdForCity(value) match
case Some(zoneId) => s"Current date is: ${ZonedDateTime.now().withZoneSameInstant(zoneId)}"
case None => s"Couldn't find time zone for city $value"
case None => s"Current date is: ${ZonedDateTime.now()}"

initialize()
```
Expand Down
4 changes: 2 additions & 2 deletions _overviews/toolkit/web-server-static.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,9 @@ scala-cli run Example.scala
```
{% endtab %}
{% tab 'sbt' %}
In the sbt shell, the following command will start the server:
In the terminal, the following command will start the server:
```
sbt:example> example/run
sbt example/run
```
{% endtab %}
{% tab 'Mill' %}
Expand Down
7 changes: 6 additions & 1 deletion _overviews/toolkit/web-server-websockets.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ private def getZoneIdForCity(city: String): Option[ZoneId] = {
}

@cask.websocket("/websocket")
def websocket(): cask.WsHandler =
def websocket(): cask.WsHandler = {
cask.WsHandler { channel =>
cask.WsActor {
case cask.Ws.Text("") => channel.send(cask.Ws.Close())
Expand All @@ -81,6 +81,9 @@ def websocket(): cask.WsHandler =
channel.send(cask.Ws.Text(text))
}
}
}

initialize()
```
{% endtab %}
{% tab 'Scala 3' %}
Expand All @@ -104,6 +107,8 @@ def websocket(): cask.WsHandler =
channel.send(cask.Ws.Text(text))
}
}

initialize()
```
{% endtab %}
{% endtabs %}
Expand Down

0 comments on commit 569d5df

Please sign in to comment.