-
Notifications
You must be signed in to change notification settings - Fork 310
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
21 changed files
with
1,262 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,7 @@ core/native/local.sbt | |
|
||
.metals/ | ||
.bloop/ | ||
project/metals.sbt | ||
metals.sbt | ||
.bsp/ | ||
.java-version | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
# Pekko backend | ||
|
||
This backend is based on [pekko-http](https://pekko.apache.org/docs/pekko-http/current/). To use, add the following dependency to your project: | ||
|
||
``` | ||
"com.softwaremill.sttp.client3" %% "pekko-http-backend" % "@VERSION@" | ||
``` | ||
|
||
A fully **asynchronous** backend. Uses the `Future` effect to return responses. There are also [other `Future`-based backends](future.md), which don't depend on Pekko. | ||
|
||
Note that you'll also need an explicit dependency on pekko-streams, as pekko-http doesn't depend on any specific pekko-streams version. So you'll also need to add, for example: | ||
|
||
``` | ||
"org.apache.pekko" %% "pekko-stream" % "@PEKKO_STREAM_VERSION@" | ||
``` | ||
|
||
Next you'll need to add create the backend instance: | ||
|
||
```scala mdoc:compile-only | ||
import sttp.client3.pekkohttp._ | ||
val backend = PekkoHttpBackend() | ||
``` | ||
|
||
or, if you'd like to use an existing actor system: | ||
|
||
```scala mdoc:compile-only | ||
import sttp.client3.pekkohttp._ | ||
import org.apache.pekko.actor.ActorSystem | ||
|
||
val actorSystem: ActorSystem = ??? | ||
val backend = PekkoHttpBackend.usingActorSystem(actorSystem) | ||
``` | ||
|
||
This backend supports sending and receiving [pekko-streams](https://pekko.apache.org/docs/pekko/current/stream/index.html) streams. The streams capability is represented as `sttp.client3.pekkohttp.PekkoStreams`. | ||
|
||
To set the request body as a stream: | ||
|
||
```scala mdoc:compile-only | ||
import sttp.capabilities.pekko.PekkoStreams | ||
import sttp.client3._ | ||
|
||
import org.apache.pekko | ||
import pekko.stream.scaladsl.Source | ||
import pekko.util.ByteString | ||
|
||
val source: Source[ByteString, Any] = ??? | ||
|
||
basicRequest | ||
.post(uri"...") | ||
.streamBody(PekkoStreams)(source) | ||
``` | ||
|
||
To receive the response body as a stream: | ||
|
||
```scala mdoc:compile-only | ||
import scala.concurrent.Future | ||
import sttp.capabilities.pekko.PekkoStreams | ||
import sttp.client3._ | ||
import sttp.client3.pekkohttp.PekkoHttpBackend | ||
|
||
import org.apache.pekko | ||
import pekko.stream.scaladsl.Source | ||
import pekko.util.ByteString | ||
|
||
val backend = PekkoHttpBackend() | ||
|
||
val response: Future[Response[Either[String, Source[ByteString, Any]]]] = | ||
basicRequest | ||
.post(uri"...") | ||
.response(asStreamUnsafe(PekkoStreams)) | ||
.send(backend) | ||
``` | ||
|
||
The pekko-http backend support both regular and streaming [websockets](../websockets.md). | ||
|
||
## Testing | ||
|
||
Apart from testing using [the stub](../testing.md), you can create a backend using any `HttpRequest => Future[HttpResponse]` function, or an pekko-http `Route`. | ||
|
||
That way, you can "mock" a server that the backend will talk to, without starting any actual server or making any HTTP calls. | ||
|
||
If your application provides a client library for its dependants to use, this is a great way to ensure that the client actually matches the routes exposed by your application: | ||
|
||
```scala mdoc:compile-only | ||
import sttp.client3.pekkohttp._ | ||
import org.apache.pekko | ||
import pekko.http.scaladsl.server.Route | ||
import pekko.actor.ActorSystem | ||
|
||
val route: Route = ??? | ||
implicit val system: ActorSystem = ??? | ||
|
||
val backend = PekkoHttpBackend.usingClient(system, http = PekkoHttpClient.stubFromRoute(route)) | ||
``` | ||
|
||
## WebSockets | ||
|
||
Non-standard behavior: | ||
|
||
* pekko always automatically responds with a `Pong` to a `Ping` message | ||
* `WebSocketFrame.Ping` and `WebSocketFrame.Pong` frames are ignored; instead, you can configure automatic [keep-alive pings](https://pekko.apache.org/docs/pekko-http/current/client-side/websocket-support.html#automatic-keep-alive-ping-support) | ||
|
||
## Server-sent events | ||
|
||
Received data streams can be parsed to a stream of server-sent events (SSE): | ||
|
||
```scala mdoc:compile-only | ||
import scala.concurrent.Future | ||
|
||
import org.apache.pekko.stream.scaladsl.Source | ||
|
||
import sttp.capabilities.pekko.PekkoStreams | ||
import sttp.client3.pekkohttp.PekkoHttpServerSentEvents | ||
import sttp.model.sse.ServerSentEvent | ||
import sttp.client3._ | ||
|
||
def processEvents(source: Source[ServerSentEvent, Any]): Future[Unit] = ??? | ||
|
||
basicRequest | ||
.get(uri"...") | ||
.response(asStream(PekkoStreams)(stream => | ||
processEvents(stream.via(PekkoHttpServerSentEvents.parse)))) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
examples/src/main/scala/sttp/client3/examples/WebSocketPekko.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package sttp.client3.examples | ||
|
||
import sttp.client3._ | ||
import sttp.client3.pekkohttp.PekkoHttpBackend | ||
import sttp.ws.WebSocket | ||
|
||
import scala.concurrent.ExecutionContext.Implicits.global | ||
import scala.concurrent.Future | ||
|
||
object WebSocketPekko extends App { | ||
def useWebSocket(ws: WebSocket[Future]): Future[Unit] = { | ||
def send(i: Int) = ws.sendText(s"Hello $i!") | ||
def receive() = ws.receiveText().map(t => println(s"RECEIVED: $t")) | ||
for { | ||
_ <- send(1) | ||
_ <- send(2) | ||
_ <- receive() | ||
_ <- receive() | ||
} yield () | ||
} | ||
|
||
val backend = PekkoHttpBackend() | ||
|
||
basicRequest | ||
.get(uri"wss://ws.postman-echo.com/raw") | ||
.response(asWebSocket(useWebSocket)) | ||
.send(backend) | ||
.onComplete(_ => backend.close()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.