-
Notifications
You must be signed in to change notification settings - Fork 273
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
uses cache-control headers from subgraphs to determine an overally cache-control policy partially addresses #326
- Loading branch information
1 parent
cc615c8
commit 6e71900
Showing
11 changed files
with
306 additions
and
24 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 |
---|---|---|
@@ -0,0 +1,5 @@ | ||
### Add cache-control response header management example in Rhai | ||
|
||
This recreates some of the behavior of Apollo Gateway's cache-control header behavior and partially addresses #326. | ||
|
||
By [@lennyburdette](https://github.com/lennyburdette) in https://github.com/apollographql/router/pull/2759 |
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
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
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,13 @@ | ||
[package] | ||
name = "cache-control" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
[dependencies] | ||
anyhow = "1" | ||
apollo-router = { path = "../../../apollo-router" } | ||
http = "0.2" | ||
serde_json = "1" | ||
tokio = { version = "1", features = ["full"] } | ||
tower = { version = "0.4", features = ["full"] } |
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,9 @@ | ||
# Rhai script | ||
|
||
Demonstrates header and context manipulation via Rhai script. | ||
|
||
Usage: | ||
|
||
```bash | ||
cargo run -- -s ../../graphql/supergraph.graphql -c ./router.yaml | ||
``` |
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,3 @@ | ||
rhai: | ||
scripts: src | ||
main: cache_control.rhai |
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,80 @@ | ||
fn subgraph_service(service, subgraph) { | ||
// collect the max-age and scope values from cache-control headers and store | ||
// on the context for use in supergraph_service | ||
service.map_response(|response| { | ||
let cache_control = response.headers.values("cache-control").get(0); | ||
|
||
// if a subgraph response is uncacheable, the whole response is uncacheable | ||
if cache_control == () { | ||
response.context.cache_control_uncacheable = true; | ||
return; | ||
} | ||
|
||
let max_age = get_max_age(cache_control); | ||
|
||
// use the smallest max age | ||
response.context.upsert("cache_control_max_age", |current| { | ||
if current == () { | ||
max_age | ||
} else if max_age < current { | ||
max_age | ||
} else { | ||
current | ||
} | ||
}); | ||
|
||
let scope = if cache_control.contains("public") { | ||
"public" | ||
} else { | ||
"private" | ||
}; | ||
|
||
// if the scope is ever private, it cannot become public | ||
response.context.upsert("cache_control_scope", |current| { | ||
if current == "private" || scope == "private" { | ||
"private" | ||
} else { | ||
scope | ||
} | ||
}); | ||
}); | ||
} | ||
|
||
fn supergraph_service(service) { | ||
// attach the cache-control header if enough data is available | ||
service.map_response(|response| { | ||
let uncacheable = response.context.cache_control_uncacheable; | ||
let max_age = response.context.cache_control_max_age; | ||
let scope = response.context.cache_control_scope; | ||
|
||
if uncacheable != true && max_age != () && scope != () { | ||
response.headers["cache-control"] = `max-age=${max_age}, ${scope}`; | ||
} | ||
}); | ||
} | ||
|
||
// find the the max-age= part and parse the value into an integer | ||
fn get_max_age(str) { | ||
let max_age = 0; | ||
|
||
for part in str.split(",") { | ||
part.remove(" "); | ||
|
||
if part.starts_with("max-age=") { | ||
let num = part.split("=").get(1); | ||
|
||
if num == () || num == "" { | ||
break; | ||
} | ||
|
||
try { | ||
max_age = num.parse_int(); | ||
} catch (err) { | ||
log_error(`error parsing max-age from "${str}": ${err}`); | ||
} | ||
break; | ||
} | ||
} | ||
|
||
max_age | ||
} |
Oops, something went wrong.