Skip to content

airframe-http: Deprecate the legacy HttpClient[F[_], Req, Resp] interface #2440

@xerial

Description

@xerial

This is a proposal to deprecate the current http client interface HttpClient[F[_], Req, Resp] that uses get[Resp], getResource[Resp], post[Resp], etc. Instead, adding a Scala-3 friendly simplified interface SyncClient/AsyncClient that consolidate these legacy methods into a simple one. For example, you can send a http request send(request: HttpMessage.Request): HttpMessage.Response method.

You can test the new interface like this:

import wvlet.airframe.http.Http

// Using Java's standard http client
val client: SyncClient = Http
  .client
  .withRequestFilter(...)
  .withConnectTimeout(...)
  .newSyncClient(baseUrl)

// Simple request and receives a raw http response
val r: Response = client.send(Http.GET("/path").withHeader(....))

// Send POST request with JSON body and read the response as an MyObj object
client.readAs[MyObj](Http.POST("/path2").withJson(...))

// Send an object data as the request body, and receive the response as ResponseType object
// JSON/MessagePack data will be transformed internally
val resp: ResponseType = client.call[RequestType, ResponseType](Http.POST("/path3"), requestDataObj) 

// When you need to use OkHttp client 
import wvlet.airframe.http.okhttp.OkHttp

// The same http interface will be used (WARNING! This is not yet implemented)
val okHttpClient: SyncClient = OkHttp
   .client
   .withXXX(...) // OkHttp specific configuration
   .newSyncClient(baseUrl)

What will be changed

What will not be changed

  • Server side interface. Finagle and gRPC servers can be used without any change

The current usage of HttpClient[F[_], Req, Resp] interface

  • airframe-okhttp (TD's conductor, td-scala-util, etc.)
  • airframe-http-finagle FinagleClient (it's frequently used in test cases)
  • airframe-http-recorder (Several test usages)

Hopefully, changing the client initialization and the request/response interface to HttpMessage.Request/Response will work for the migratin.

And unit tests that uses Finagle.client, OkHttpClient, http recorder, etc.

Background: Why does it need to be changed?

Difficulty of Scala 3 Support

The current interface HttpClient[F[_], Req, Resp] has many methods that takes TypeTag, which is no longer available in Scala 3:

airframe-http-recorder implementation is tied to Finagle because it uses Finagle as the backend. But, Finagle will not be migrated to Scala 3 in near future, so we need to find an alternative solution (e.g., implementing Netty4-based server backend)

Supporting multiple HTTP client backends becomes less important

HttpClient[F[_], Res, Resp] design was introduced to support various types of Future types (Scala Future or Twitter Future), http request/response types (Finagle's http Request/Response, OkHttp's Request/Response). Now that airframe-http has the standard HttpMessage.Request/Response classes, supporting different request/response types becomes less important. If you use RPC, directly manipulating http request and response is unnecessary other than for implementing HTTP request filters.

Since Java 9, you can use a standard Java client, which is already supported in https://github.com/wvlet/airframe/blob/master/airframe-http/.jvm/src/main/scala/wvlet/airframe/http/client/JavaClientChannel.scala
This client requires no extra dependency other than Java 9 or later.

Finagle Request are mutable

Finagle's request object is mutable. The new HttpMessage.Request is an immutable object, which is better to avoid unexpected side-effect.

Future Work

AsyncClient is currently using Scala's Future[X] interface, but it's a bit inconvenient that we always need to provide ExecutionContext for Future objects. Instead, having an Rx-based http client interface #2300, which can support Scala.js and gRPC would be ideal.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

Status

In Progress

Status

Backlog

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions