You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
5.0 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package wow.doge.http4sdemo
  2. import cats.effect.Sync
  3. import cats.implicits._
  4. import fs2.interop.reactivestreams._
  5. import io.circe.Codec
  6. import io.circe.generic.semiauto._
  7. import monix.bio.IO
  8. import monix.bio.Task
  9. import monix.bio.UIO
  10. import org.http4s.HttpRoutes
  11. import org.http4s.dsl.Http4sDsl
  12. import wow.doge.http4sdemo.dto.Book
  13. import wow.doge.http4sdemo.dto.BookSearchMode
  14. import wow.doge.http4sdemo.dto.BookUpdate
  15. import wow.doge.http4sdemo.dto.NewBook
  16. import wow.doge.http4sdemo.services.LibraryService
  17. object Http4sdemoRoutes {
  18. def jokeRoutes[F[_]: Sync](J: Jokes[F]): HttpRoutes[F] = {
  19. val dsl = Http4sDsl[F]
  20. import dsl._
  21. HttpRoutes.of[F] { case GET -> Root / "joke" =>
  22. for {
  23. joke <- J.get
  24. resp <- Ok(joke)
  25. } yield resp
  26. }
  27. }
  28. def helloWorldRoutes[F[_]: Sync](H: HelloWorld[F]): HttpRoutes[F] = {
  29. val dsl = new Http4sDsl[F] {}
  30. import dsl._
  31. HttpRoutes.of[F] { case GET -> Root / "hello" / name =>
  32. for {
  33. greeting <- H.hello(HelloWorld.Name(name))
  34. resp <- Ok(greeting)
  35. r2 <- BadRequest("Bad request")
  36. } yield r2
  37. }
  38. }
  39. def libraryRoutes(libraryService: LibraryService): HttpRoutes[Task] = {
  40. val dsl = Http4sDsl[Task]
  41. import dsl._
  42. object Value extends QueryParamDecoderMatcher[String]("value")
  43. HttpRoutes.of[Task] {
  44. case GET -> Root / "api" / "get" / "book" :?
  45. BookSearchMode.Matcher(mode) +& Value(value) =>
  46. import org.http4s.circe.streamJsonArrayEncoder
  47. import io.circe.syntax._
  48. IO.deferAction(implicit s =>
  49. for {
  50. books <- IO.pure(
  51. libraryService
  52. .searchBook(mode, value)
  53. .toReactivePublisher
  54. .toStream[Task]
  55. )
  56. res <- Ok(books.map(_.asJson))
  57. } yield res
  58. )
  59. case GET -> Root / "api" / "get" / "books" =>
  60. import org.http4s.circe.streamJsonArrayEncoder
  61. import io.circe.syntax._
  62. Task.deferAction(implicit s =>
  63. for {
  64. books <- IO.pure(
  65. libraryService.getBooks.toReactivePublisher
  66. .toStream[Task]
  67. )
  68. res <- Ok(books.map(_.asJson))
  69. // res <- Ok(streamJsonArrayEncoderOf[Task, Book].(books))
  70. } yield res
  71. )
  72. case GET -> Root / "blah" => Ok().hideErrors
  73. case GET -> Root / "api" / "get" / "book" / IntVar(id) =>
  74. import org.http4s.circe.CirceEntityCodec._
  75. // import org.http4s.circe.jsonEncoder
  76. // import io.circe.syntax._
  77. for {
  78. bookJson <- libraryService.getBookById(id)
  79. res <- Ok(bookJson)
  80. } yield res
  81. case req @ POST -> Root / "api" / "post" / "book" =>
  82. import org.http4s.circe.CirceEntityCodec._
  83. for {
  84. newBook <- req.as[NewBook]
  85. // .onErrorHandleWith {
  86. // case ParseF
  87. // }
  88. res <- libraryService
  89. .insertBook(newBook)
  90. .flatMap(book => Created(book).hideErrors)
  91. .mapErrorPartialWith {
  92. case LibraryService.EntityDoesNotExist(message) =>
  93. BadRequest(message).hideErrors
  94. case LibraryService.EntityAlreadyExists(message) =>
  95. BadRequest(message).hideErrors
  96. // case LibraryService.MyError2(_) => Ok().hideErrors
  97. // case C3 => Ok().hideErrors
  98. }
  99. } yield res
  100. case req @ PATCH -> Root / "api" / "update" / "book" / IntVar(id) =>
  101. import org.http4s.circe.CirceEntityCodec._
  102. for {
  103. updateData <- req.as[BookUpdate]
  104. res <- libraryService
  105. .updateBook(id, updateData)
  106. .flatMap(_ => Ok().hideErrors)
  107. .tapError(err => UIO(println(s"Handled -> ${err.toString}")))
  108. .mapErrorPartialWith {
  109. case e @ LibraryService.EntityDoesNotExist(message) =>
  110. BadRequest(e: LibraryService.Error).hideErrors
  111. // case LibraryService.MyError2(_) => Ok().hideErrors
  112. // case C3 => Ok().hideErrors
  113. }
  114. } yield res
  115. case req @ DELETE -> Root / "api" / "delete" / "book" / IntVar(id) =>
  116. for {
  117. _ <- libraryService.deleteBook(id)
  118. res <- Ok()
  119. } yield res
  120. case req @ POST -> Root / "api" / "post" / "books" / "read" =>
  121. import org.http4s.circe.CirceEntityCodec.circeEntityDecoder
  122. for {
  123. newBook <- req.as[List[Book]]
  124. // book <- libraryService.insertBook(newBook)
  125. res <- Ok("blah")
  126. } yield res
  127. }
  128. }
  129. }
  130. final case class User(id: String, email: String)
  131. object User {
  132. val tupled = (this.apply _).tupled
  133. // implicit val decoder: Decoder[User] = deriveDecoder
  134. // implicit def entityDecoder[F[_]: Sync]: EntityDecoder[F, User] =
  135. // jsonOf
  136. // implicit val encoder: Encoder[User] = deriveEncoder
  137. // implicit def entityEncoder[F[_]: Applicative]: EntityEncoder[F, User] =
  138. // jsonEncoderOf
  139. implicit val codec: Codec[User] = deriveCodec
  140. }