Skip to content

Commit 2aba7e5

Browse files
authored
Merge pull request #16 from fastly/kats/simple-forward
Update into a simple "fanout forward" starter kit
2 parents b2557a4 + 47da89d commit 2aba7e5

File tree

4 files changed

+77
-8
lines changed

4 files changed

+77
-8
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ publish = false
1010
debug = 1
1111

1212
[dependencies]
13-
fastly = "0.10.0"
13+
fastly = "0.11.0"

README.md

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,50 @@
22

33
[![Deploy to Fastly](https://deploy.edgecompute.app/button)](https://deploy.edgecompute.app/deploy)
44

5-
Learn about Fastly Compute with Fanout using a basic starter that sends connections through the Fanout GRIP proxy to a backend.
5+
Learn about [Fastly Compute with Fanout](https://www.fastly.com/documentation/guides/concepts/real-time-messaging/fanout/) using a basic starter that sends connections through the Fanout GRIP proxy to a backend.
66

77
**For more details about this and other starter kits for Compute, see the [Fastly Documentation Hub](https://www.fastly.com/documentation/solutions/starters/)**.
88

99
## Setup
1010

1111
The app expects a configured backend named "origin" that points to an origin server. For example, if the server is available at domain `example.com`, then you'll need to create a backend on your Compute service named "origin" with the destination host set to `example.com` and port `443`. Also set `Override Host` to the same host value.
1212

13-
After deploying the app and setting up the backend configuration, all connections received by the service will be passed through the Fanout proxy to the origin. If WebSocket-over-HTTP mode is enabled on your service, then client WebSocket activity will be converted into HTTP when sending to the origin.
13+
You'll also need to [enable Fanout](https://www.fastly.com/documentation/guides/concepts/real-time-messaging/fanout/#enable-fanout) on your Fastly service to run this application. To enable Fanout on your service, type:
1414

15-
## Note
15+
```shell
16+
fastly products --enable=fanout
17+
```
1618

17-
This app is not currently supported in Fastly's [local development server](https://www.fastly.com/documentation/guides/compute/testing/#running-a-local-testing-server), as the development server does not support Fanout features. To experiment with Fanout, you will need to publish this project to your Fastly Compute service. using the `fastly compute publish` command.
19+
> [!NOTE]
20+
> This app is not currently supported in Fastly's [local development server](https://www.fastly.com/documentation/guides/compute/testing/#running-a-local-testing-server), as the development server does not support Fanout features. To experiment with Fanout, you will need to publish this project to your Fastly Compute service. using the `fastly compute publish` command.
21+
22+
## Running the application
23+
24+
After deploying the app and setting up the backend configuration, incoming HTTP and WebSocket requests that arrive at the service will be processed by the fetch handler:
25+
26+
1. WebSocket connections will be handed off to Fanout to reach the backend server. Fanout maintains a long-lived connection with the client, and uses the [WebSocket-over-HTTP protocol](https://pushpin.org/docs/protocols/websocket-over-http/) to transform the messages to and from the backend server.
27+
28+
2. HTTP GET and HEAD requests will be handed off to Fanout to reach the backend server. The backend can include [GRIP control messages](https://pushpin.org/docs/protocols/grip/) in its response, instructing Fanout to maintain a long-lived connection with the client.
29+
30+
## Next Steps
31+
32+
The starter kit is written to send all WebSocket and HTTP GET (and HEAD) traffic to Fanout. In an actual app we would be selective about which requests are handed off to Fanout, because requests that are handed off to Fanout do not pass through the Fastly cache.
33+
34+
For details, see [What to hand off to Fanout](https://www.fastly.com/documentation/guides/concepts/real-time-messaging/fanout/#what-to-hand-off-to-fanout) in the Developer Documentation.
35+
36+
The starter kit code contains a TODO section where you may insert additional conditions to check before setting the `use_fanout` variable to `true`.
37+
38+
For example, to check the request for the existence of a certain header:
39+
40+
```rust
41+
if let Some(_) = req.get_header("fanout") {
42+
use_fanout = true;
43+
}
44+
```
45+
46+
## Notes
47+
48+
The code in this starter kit cannot be used with the [`fastly::main` attribute](https://docs.rs/fastly/0.11.2/fastly/attr.main.html) on the `main()` entry point. This is because a function decorated with `fastly::main` is expected to return a response, but handing off to Fanout is an action that does not create a response. Use an undecorated `main()` function instead, and use `Request::from_client()` and `Response::send_to_client()` as needed.
1849

1950
## Security issues
2051

fastly.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1+
# This file describes a Fastly Compute package. To learn more visit:
2+
# https://www.fastly.com/documentation/reference/compute/fastly-toml
3+
14
authors = ["<[email protected]>"]
25
description = "Enables Fanout on a service, forwarding to a backend."
36
language = "rust"
4-
manifest_version = 2
5-
name = "Fanout forwarding"
7+
manifest_version = 3
8+
name = "Fanout forwarding starter kit for Rust"
69

710
[scripts]
811
build = "cargo build --bin fastly-compute-project --release --target wasm32-wasi --color always"

src/main.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use fastly::{Error, Request};
2+
use fastly::http::{HeaderValue, Method};
23

34
fn main() -> Result<(), Error> {
45
// Log service version.
@@ -9,5 +10,39 @@ fn main() -> Result<(), Error> {
910

1011
let req = Request::from_client();
1112

12-
Ok(req.handoff_fanout("origin")?)
13+
let mut use_fanout = false;
14+
15+
if req.get_method() == &Method::GET &&
16+
req.get_header_all("upgrade")
17+
.collect()
18+
.contains(&&HeaderValue::from_static("websocket"))
19+
{
20+
// If a GET request contains "Upgrade: websocket" in its headers, then hand off to Fanout
21+
// to handle as WebSocket-over-HTTP.
22+
// For details on WebSocket-over-HTTP, see https://pushpin.org/docs/protocols/websocket-over-http/
23+
use_fanout = true;
24+
} else if req.get_method() == &Method::GET || req.get_method() == &Method::HEAD {
25+
// If it's a GET or HEAD request, then hand off to Fanout.
26+
// The backend response can include GRIP control messages to specify connection behavior.
27+
// For details on GRIP, see https://pushpin.org/docs/protocols/grip/.
28+
29+
// NOTE: In an actual app we would be selective about which requests are handed off to Fanout,
30+
// because requests that are handed off to Fanout do not pass through the Fastly cache.
31+
// For example, we may examine the request path or the existence of certain headers.
32+
// See https://www.fastly.com/documentation/guides/concepts/real-time-messaging/fanout/#what-to-hand-off-to-fanout
33+
34+
// TODO: add any additional conditions before setting use_fanout to true
35+
36+
use_fanout = true;
37+
}
38+
39+
if use_fanout {
40+
// Hand off the request through Fanout to the specified backend.
41+
req.handoff_fanout("origin")?
42+
} else {
43+
// Send the request to the specified backend normally.
44+
req.send("origin")?.send_to_client()
45+
}
46+
47+
Ok(())
1348
}

0 commit comments

Comments
 (0)