0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

外部Web APIアクセス

Last updated at Posted at 2023-09-28

今回はzio-httpのクライアントについて見ていきます。
前章で作成したAPIを利用しつつ、確認していきます。
GETメソッドの場合とPOSTメソッドの場合の二例を具体的に見ていきますが、まず最初にGETメソッドの場合です。

GETメソッド

実処理部分に対して追加と修正を行います。

ApplicationService.scala
trait ApplicationService {
(中略)
  def getApi: ZIO[Any, Throwable, Response]
}

object ApplicationService {
(中略)
  def getApi: ZIO[ApplicationService, Throwable, Response] = {
    ZIO.serviceWithZIO[ApplicationService](_.getApi)
  }
}
ApplicationServiceImpl.scala
case class ApplicationServiceImpl(client: Client) extends ApplicationService {
(中略)

  override def getApi: ZIO[Any, Throwable, Response] = for{
    uri <- ZIO.fromEither(URL.decode("http://localhost:8080/text"))
    res <- client.request(
      Request
        .default(
          Method.GET,
          uri,
          Body.empty
        )
    )
    data <- res.body.asString
  } yield Response.text(s"http://localhost:8080/text:$data")
}
object ApplicationServiceImpl {
  val layer: ZLayer[Client, Nothing, ApplicationService] =
    ZLayer{for {
      client <- ZIO.service[Client]
    } yield ApplicationServiceImpl(client)}

}

この実処理を呼び出すパスを追加します。

TestController.scala
object TestController {
  def apply(): Http[ApplicationService, Throwable, Request, Response] = Http.collectZIO[Request] {
(中略)
    case Method.GET -> Root / "getApi"          => ApplicationService.getApi
  }
}

最後にHTTPクライアントをDIします。

MainApp.scala
object MainApp extends ZIOAppDefault {
(中略)
      .provide(
        Server.default,
        ApplicationServiceImpl.layer,
        Client.default
      )
}

上記を実行し、http://localhost:8080/getApiにアクセスすると以下の出力を得られます。

http://localhost:8080/text:Hello World!

これは実際にHTTPリクエストを行い、得られた値を表示しています。

コードの内容について詳しく見ていきます。

HTTPクライアントのDI

まず最初にHTTPリクエストを行うに当たってクライアントを準備する必要があります。
そして、準備したクライアントを以下の部分でDIしています。

MainApp.scala
object MainApp extends ZIOAppDefault {
(中略)
      .provide(
        Server.default,
        ApplicationServiceImpl.layer,
        Client.default
      )
}

今回HTTPクライアントに対して特別な設定を行う必要がないため、最も基本的なClient.defaultを使っていますが、プロキシなどの設定を行うことも可能です。
このDIのため、ApplicationService,ApplicationServiceImplに対しても修正を行っています。

GETリクエスト

リクエストを行うためにまず文字列のURLをURL型に変換します。
URL.decode関数の返り値の型がEither型であるため、ZIO.fromEither関数でZIO型に変換しています。
エラー発生時を考え、ZIO型に直しています。

ApplicationServiceImpl.scala
uri <- ZIO.fromEither(URL.decode("http://localhost:8080/text"))

そして、変換したURLを使い、実際のリクエストを行います。

ApplicationServiceImpl.scala
    res <- client.request(
      Request
        .default(
          Method.GET,
          uri,
          Body.empty
        )
    )

後にも説明しますが、例えばMethod.GETの部分をMethod.POSTに変えることでPOSTリクエストを行うことが出来たりと、リクエストの条件を変えることもできます。

最後に以下の部分でHTTPレスポンスのボディを取得しています。

ApplicationServiceImpl.scala
    data <- res.body.asString

他にもres.status.textによりレスポンスステータスコードを取得するといったことが出来ます。

POSTメソッド

次にPOSTメソッドについて見ていきます。
最初に実処理部分に対して追記を行います。

ApplicationService.scala
trait ApplicationService {
(中略)
  def postApi(param:String): ZIO[Any, Throwable, Response]
}

object ApplicationService {
(中略)
  def postApi(param:String): ZIO[ApplicationService, Throwable, Response] = {
    ZIO.serviceWithZIO[ApplicationService](_.postApi(param))
  }
}
ApplicationServiceImpl.scala
case class ApplicationServiceImpl(client: Client) extends ApplicationService {
(中略)
  override def postApi(param:String): ZIO[Any, Throwable, Response] = for{
    uri <- ZIO.fromEither(URL.decode("http://localhost:8080/postTest"))
    res <- client.request(
      Request
        .default(
          Method.POST,
          uri,
          Body.fromString(
            s"userName=$param"
          )
        )
    )
    data <- res.body.asString
  } yield Response.text(s"http://localhost:8080/postTest:$data").setHeaders(Headers("Content-Type", "text/plain;charset=UTF-8")) // 文字化け対策をしています
}

パスを追加します。

TestController.scala
object TestController {
  def apply(): Http[ApplicationService, Throwable, Request, Response] = Http.collectZIO[Request] {
(中略)
    case Method.GET -> Root / "postApi" / test       => ApplicationService.postApi(test)
  }
}

上記の修正を行った後実行し、http://localhost:8080/postApi/testにアクセスると以下の出力を得られます。

http://localhost:8080/postTest:あなたの名前はtestです。

http://localhost:8080/postApi/testの末尾のtestの部分を変えると出力も変わるので確認してみてください。

POSTパラメータ

基本的にPOSTリクエストの場合もGETリクエストと変わりません。
POSTパラメータの渡し方の一例として今回は以下の部分で渡しています。

ApplicationServiceImpl.scala
          Body.fromString(
            s"userName=$param"
          )

この場合パラメータ名「userName」に対して変数paramの値を渡しています。
&で区切ることにより複数のパラメータを渡すこともできます。

終わりに

GETリクエスト、POSTリクエストの方法を今回見てきました。
次章ではzio-httpの中のMiddleware機能について見ていきます。
文字化け対策として.setHeaders(Headers("Content-Type", "text/plain;charset=UTF-8"))を付加しているResponseがいくつかありますが、このMiddlewareを使い、これを付けなくとも文字化けを起こさないように修正していきたいと思います。

前章:zio-http
次章:Middlewareについて

演習

  1. 今回のGETメソッド例について実際に動かして挙動を確かめてください。
  2. 今回のPOSTメソッド例について実際に動かして挙動を確かめてください。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?