-
Notifications
You must be signed in to change notification settings - Fork 89
Closed
Description
We've seen some issues making requests of specific server implementations when using smithy4s and @simpleRestJson, and I think it's because smithy4s isn't setting the Accept header when making requests. I was able to demonstrate this using this Smithy spec:
$version: "2"
namespace echo.headers
use alloy#simpleRestJson
map RequestHeaders {
key: String
value: String
}
structure Response {
@required
value: RequestHeaders
}
@http(method: "GET", uri: "/", code: 200)
operation GetRoot {
input: Unit,
output: Response
}
@simpleRestJson
service EchoHeaders {
operations: [GetRoot]
}and demo app:
package echo.headers
import cats._
import cats.data.OptionT
import cats.effect.{Trace => _, _}
import cats.mtl.Local
import cats.syntax.all._
import com.comcast.ip4s._
import org.http4s.ember.client.EmberClientBuilder
import org.http4s.ember.server.EmberServerBuilder
import org.http4s.server.Server
import org.http4s.syntax.all._
import org.http4s.{Headers, HttpRoutes, Uri}
import smithy4s.http4s.SimpleRestJsonBuilder
class EchoHeadersImpl[F[_] : Functor](requestHeaders: F[Headers]) extends EchoHeaders[F] {
override def getRoot(): F[Response] =
requestHeaders
.map {
_.headers
.map { h =>
h.name.toString -> h.value
}
.toMap
}
.map(Response(_))
}
class RequestHeaderProvidingMiddleware[F[_] : Monad](implicit L: Local[F, Headers]) extends (HttpRoutes[F] => HttpRoutes[F]) {
override def apply(routes: HttpRoutes[F]): HttpRoutes[F] =
HttpRoutes[F] { request =>
Local[OptionT[F, *], Headers].scope {
routes(request)
}(request.headers)
}
}
object EchoHeadersApp extends IOApp.Simple {
private def server: Resource[IO, Server] =
IO.local(Headers.empty)
.toResource
.flatMap { implicit l: Local[IO, Headers] =>
SimpleRestJsonBuilder
.routes(new EchoHeadersImpl(l.ask))
.resource
.map(new RequestHeaderProvidingMiddleware[IO])
}
.map(_.orNotFound)
.flatMap {
EmberServerBuilder
.default[IO]
.withHost(host"localhost")
.withPort(port"0")
.withHttpApp(_)
.build
}
private def client(uri: Uri): Resource[IO, EchoHeaders[IO]] =
EmberClientBuilder
.default[IO]
.build
.flatMap {
SimpleRestJsonBuilder(echo.headers.EchoHeaders)
.client(_)
.uri(uri)
.resource
}
override def run: IO[Unit] =
server
.map(_.baseUri)
.flatMap(client)
.use(_.getRoot().flatMap(IO.println))
}Running the app emits the following to the console:
15:09:46.674 [io-compute-1] INFO org.http4s.ember.server.EmberServerBuilderCompanionPlatform -- Ember-Server service bound to address: 127.0.0.1:49462
Response(Map(Host -> 127.0.0.1:49462, Date -> Tue, 16 Dec 2025 21:09:46 GMT, Connection -> keep-alive, User-Agent -> http4s-ember/0.23.33))
Note the absence of an Accept header, which I was expecting to be present and set to Accept: application/json.
This doesn't cause issues when using a smithy4s server, but some servers are stricter and refuse to handle requests without content negotiation via the Accept header.
Tested with Smithy4s 0.18.45.
lewisjkl
Metadata
Metadata
Assignees
Labels
No labels