https://github.com/krzemin/endpoints-scala-workshop
Materials for endpoints Scala library workshop
https://github.com/krzemin/endpoints-scala-workshop
endpoints scala workshop
Last synced: about 1 year ago
JSON representation
Materials for endpoints Scala library workshop
- Host: GitHub
- URL: https://github.com/krzemin/endpoints-scala-workshop
- Owner: krzemin
- Created: 2019-01-10T14:15:24.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2019-09-16T11:53:37.000Z (almost 7 years ago)
- Last Synced: 2025-04-03T07:51:19.106Z (over 1 year ago)
- Topics: endpoints, scala, workshop
- Language: Scala
- Size: 2.18 MB
- Stars: 4
- Watchers: 0
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# endpoints-scala-workshop
Materials for endpoints Scala library workshop
There are few exercises in this repository that aims to
get you familiar with Scala [endpoints](http://julienrf.github.io/endpoints/)
library.
Presentation is at https://docs.google.com/presentation/d/19ob9ZYwtm6qM5Jwg_AXHY-VGjW-DXjAHPStDvuLuyW4/edit#slide=id.p
### Pizza Store
You are given few data types that describe simple pizza store service,
where you can manage list of pizza menu entries, their ingredients
and prices, depending on their size.
```scala
case class Pizza(id: Int,
name: String,
ingredients: List[String],
variants: List[Variant])
case class Variant(size: Size,
price: Price)
sealed trait Size
case object Small extends Size
case object Medium extends Size
case object Big extends Size
case class Price(amount: BigDecimal,
currency: String)
```
Class `pizzastore.Repository` contains simple, in-memory implementation of pizza menu
that is used in this workshop.
#### Running server and test client
In order to run the server, you need to invoke `sbt run`. Api and documentation (previewed with swagger ui)
should be available at http://localhost:5000.
In order to run the [test client example program](src/test/scala/pizzastore/TestClient.scala), you need to
have server that is up. Then invoke `sbt test:run` to execute test program against the server.
### Exercise 1 - API endpoints for ingredients management
Define 3 following API endpoints:
* `GET /pizzas//ingredients` - it should return ingredients of specified pizza as JSON list
* `PUT /pizzas//ingredients` - it should upsert ingredient to specified pizza
* `DELETE /pizzas//ingredients/` - it should delete specified ingredient in specified pizza
Modify `TestClient` to make Hawai pizza ingredients update with these 3 endpoints.
### Exercise 2 - Support 404 errors correctly
Note that trying to access pizza by non-existing `id`, the exception will be thrown.
This is because `pizzastore.Repository` has some defect. You need to fix this defect, but the fix
also affects return type of few methods.
Once you modify repository type signatures, they don't match to the signatures required
by the server implementation. On the other hand, we would like to return 404 response codes
explicitly for non-existing resources (instead of 500 signalling some case not handled properly).
With endpoints, you don't control response codes from server implementation! For such use cases you need
algebra that allows you to explicitly express value optionality. Hopefully, endpoints come with
standard response operation `wheneverFound` (or `.orNotFound` extension method).
See https://github.com/julienrf/endpoints/blob/master/algebras/algebra/src/main/scala/endpoints/algebra/Responses.scala
As a part of the task, write a test using the client that demonstrates that when trying
non-existing pizzas, client returns `None`.
What about OpenAPI documentation?
### Exercise 3 - Validation algebra
Ok, let's add few requirements to our API. Adding or updating pizza with empty name is not nice.
Similarly, we shouldn't allow pizzas with empty ingredients list to be present in our store. Let's add
some validation to our `PUT /pizzas` endpoint!
The endpoint should:
- upsert only pizzas with non-empty name and ingredient list, returning 200 response code
- return json containing list of problems, with 422 response code
For example:
```
PUT /pizzas
{
"id": 6,
"name": "",
"ingredients": []
"variants": []
}
```
should return
```
HTTP/422
[
"name is empty!",
"ingredients list is empty!"
]
```
Additional validation rules are up to you :)
Write the test using generated client, that verifies your validation. Make sure
the documentation is aligned, so that it mentions 422 code as validation error.
### Exercise 4 - Authentication
It's time to secure our API!
In this task you need to make sure, that endpoints modifying content of the store
(`PUT`, `POST`, `DELETE`) are secured by HTTP Basic Authentication. To perform this
task, `endpoints.algebra.BasicAuthentication` might be useful.
As usually:
- make sure that you write test that invokes secured endpoints without
credentials and you get appropriate http status code
- make sure the docs reflect security mechanism for secured endpoints
### Solutions
If you stuck at some exercise or want to see my solution, you can view it on `exercise-n` branch.