-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #94 from http4s/feature/ws-client-docs
WebSocket client docs/example
- Loading branch information
Showing
7 changed files
with
153 additions
and
74 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
This file was deleted.
Oops, something went wrong.
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,6 @@ | ||
laika.navigationOrder = [ | ||
index.md | ||
fetch.md | ||
websocket.md | ||
serviceworker.md | ||
] |
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,38 @@ | ||
# Fetch Client | ||
|
||
The [`FetchClientBuilder`](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/FetchClientBuilder.html) creates a standard http4s [`Client`](https://http4s.org/v0.23/api/org/http4s/client/client) that is described in the [http4s documentation](https://http4s.org/v0.23/client/). | ||
|
||
## Example | ||
|
||
```scala mdoc:js | ||
<div style="text-align:center"> | ||
<h3 style="padding:10px"> | ||
I'm bored. | ||
</h3> | ||
<button id="button">Fetch Activity</button> | ||
<p style="padding:10px" id="activity"></p> | ||
</div> | ||
--- | ||
import cats.effect._ | ||
import cats.effect.unsafe.implicits._ | ||
import io.circe.generic.auto._ | ||
import org.http4s.circe.CirceEntityCodec._ | ||
import org.http4s.dom._ | ||
import org.scalajs.dom._ | ||
|
||
val client = FetchClientBuilder[IO].create | ||
|
||
val activityElement = document.getElementById("activity") | ||
|
||
case class Activity(activity: String) | ||
|
||
val fetchActivity: IO[Unit] = for { | ||
_ <- IO(activityElement.innerHTML = "<i>fetching...</i>") | ||
activity <- client.expect[Activity]("https://www.boredapi.com/api/activity") | ||
_ <- IO(activityElement.innerHTML = activity.activity) | ||
} yield () | ||
|
||
val button = document.getElementById("button").asInstanceOf[html.Button] | ||
|
||
button.onclick = _ => fetchActivity.unsafeRunAndForget() | ||
``` |
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,27 @@ | ||
# http4s-dom | ||
|
||
Use http4s in your browser with Scala.js! | ||
Features: | ||
|
||
* A [`Client` implementation](fetch.md) backed by [`fetch`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) | ||
* A [`WSClient` implementation](websocket.md) backed by [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket$.html) | ||
* A [`Service Worker` integration](serviceworker.md) to install your `HttpRoutes` as a [`FetchEvent` handler](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerGlobalScope/onfetch) | ||
* Encoders for [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File), [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) and [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) | ||
|
||
Notably, http4s-dom can also be used to create _serverless_ apps with [Cloudflare Workers](https://workers.cloudflare.com) which have adopted the same APIs used in the browser! | ||
|
||
## Installation | ||
|
||
[![http4s-dom Scala version support](https://index.scala-lang.org/http4s/http4s-dom/http4s-dom/latest.svg)](https://index.scala-lang.org/http4s/http4s-dom/http4s-dom) | ||
|
||
```scala | ||
// Supports http4s 0.23.x and scala-js-dom 2.x | ||
libraryDependencies += "org.http4s" %%% "http4s-dom" % "@VERSION@" | ||
|
||
// recommended, brings in the latest client module | ||
libraryDependencies += "org.http4s" %%% "http4s-client" % "@HTTP4S_VERSION@" | ||
|
||
// optional, for JSON support | ||
libraryDependencies += "org.http4s" %%% "http4s-circe" % "@HTTP4S_VERSION@" | ||
libraryDependencies += "io.circe" %%% "circe-generic" % "@CIRCE_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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Service Worker "Server" | ||
|
||
The [`ServiceWorker`](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/ServiceWorker$.html) `FetchEvent` listener integrates directly with [http4s services](https://http4s.org/v0.23/service/). You can use it to run a "proxy server" as a background process in the browser that can intercept and respond to requests made by the `FetchClient`. | ||
|
||
## Example | ||
|
||
Coming soon! |
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,70 @@ | ||
# WebSocket Client | ||
|
||
The [`WebSocketClient`](https://www.javadoc.io/doc/org.http4s/http4s-dom_sjs1_2.13/latest/org/http4s/dom/WSClient$.html) creates a standard http4s [`WSClientHighLevel`](https://http4s.org/v0.23/api/org/http4s/client/client). | ||
|
||
## Example | ||
|
||
```scala mdoc:js | ||
<div> | ||
<h3>Send Text Frame</h3> | ||
<input id="message" size="64" type="text"> | ||
<button id="button">Send</button> | ||
</div> | ||
<div style="display: flex"> | ||
<div style="flex: 50%"> | ||
<h3>Sent</h3> | ||
<div id="sent" style="width: 100%"></div> | ||
</div> | ||
<div style="flex: 50%"> | ||
<h3>Received</h3> | ||
<div id="received" style="width: 100%"></div> | ||
</div> | ||
</div> | ||
--- | ||
import cats.effect._ | ||
import cats.effect.unsafe.implicits._ | ||
import org.http4s.client.websocket._ | ||
import org.http4s.dom._ | ||
import org.http4s.syntax.all._ | ||
import org.scalajs.dom._ | ||
|
||
val message = document.getElementById("message").asInstanceOf[html.Input] | ||
val button = document.getElementById("button").asInstanceOf[html.Button] | ||
val sent = document.getElementById("sent").asInstanceOf[html.Element] | ||
val received = document.getElementById("received").asInstanceOf[html.Element] | ||
|
||
val request = WSRequest(uri"wss://ws.postman-echo.com/raw") | ||
val app = WebSocketClient[IO].connectHighLevel(request).use { conn => | ||
|
||
def log(e: html.Element, text: String): IO[Unit] = | ||
IO { | ||
val p = document.createElement("p") | ||
p.innerHTML = text | ||
e.appendChild(p) | ||
() | ||
} | ||
|
||
val sendMessage: IO[Unit] = for { | ||
text <- IO(message.value) | ||
frame = WSFrame.Text(text) | ||
_ <- conn.send(frame) | ||
_ <- log(sent, frame.toString) | ||
} yield () | ||
|
||
val receiveMessages: IO[Unit] = | ||
conn.receiveStream | ||
.evalTap(frame => log(received, frame.toString)) | ||
.compile | ||
.drain | ||
|
||
val logCloseFrame: IO[Unit] = | ||
conn.closeFrame.get.flatMap(frame => log(received, frame.toString)) | ||
|
||
val registerOnClick = IO(button.onclick = _ => sendMessage.unsafeRunAndForget()) | ||
val deregisterOnClick = IO(button.onclick = null) | ||
|
||
registerOnClick *> receiveMessages *> logCloseFrame *> deregisterOnClick | ||
} | ||
|
||
app.unsafeRunAndForget() | ||
``` |