Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changesets/feat_cgati_coprocessor_url_overrides.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
### feat(coprocessor): Support per-stage coprocessor URLs ([PR #8384](https://github.com/apollographql/router/pull/8384))

Adds the ability to configure different coprocessor URLs for each stage of request/response processing (router, supergraph, execution, subgraph). Each stage can now specify its own `url` field that overrides the global default URL.

Changes:
- Add optional `url` field to all stage configuration structs
- Update all stage `as_service` methods to accept and resolve URLs
- Add tests for URL validation and per-stage configuration

Maintains full backward compatibility - existing configurations with a single global URL continue to work unchanged.

By [@cgati](https://github.com/cgati) in https://github.com/apollographql/router/pull/8384
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
source: apollo-router/src/configuration/tests.rs
assertion_line: 28
expression: "&schema"
snapshot_kind: text
---
{
"$schema": "http://json-schema.org/draft-07/schema#",
Expand Down Expand Up @@ -2651,7 +2651,7 @@ snapshot_kind: text
"type": "string"
},
"url": {
"description": "The url you'd like to offload processing to",
"description": "The url you'd like to offload processing to (can be overridden per-stage)",
"type": "string"
}
},
Expand Down Expand Up @@ -3465,6 +3465,14 @@ snapshot_kind: text
"default": false,
"description": "Send the SDL",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down Expand Up @@ -3500,6 +3508,14 @@ snapshot_kind: text
"default": false,
"description": "Send the HTTP status",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down Expand Up @@ -7867,6 +7883,14 @@ snapshot_kind: text
"default": false,
"description": "Send the SDL",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down Expand Up @@ -7910,6 +7934,14 @@ snapshot_kind: text
"default": false,
"description": "Send the HTTP status",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down Expand Up @@ -9365,6 +9397,14 @@ snapshot_kind: text
"default": false,
"description": "Send the subgraph URI",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down Expand Up @@ -9413,6 +9453,14 @@ snapshot_kind: text
"default": false,
"description": "Send the subgraph request id",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down Expand Up @@ -10429,6 +10477,14 @@ snapshot_kind: text
"default": false,
"description": "Send the SDL",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down Expand Up @@ -10472,6 +10528,14 @@ snapshot_kind: text
"default": false,
"description": "Send the HTTP status",
"type": "boolean"
},
"url": {
"default": null,
"description": "The coprocessor URL for this stage (overrides the global URL if specified)",
"type": [
"string",
"null"
]
}
},
"type": "object"
Expand Down
15 changes: 13 additions & 2 deletions apollo-router/src/plugins/coprocessor/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub(super) struct ExecutionRequestConf {
pub(super) method: bool,
/// Send the query plan
pub(super) query_plan: bool,
/// The coprocessor URL for this stage (overrides the global URL if specified)
pub(super) url: Option<String>,
}

/// What information is passed to a router request/response stage
Expand All @@ -49,6 +51,8 @@ pub(super) struct ExecutionResponseConf {
pub(super) sdl: bool,
/// Send the HTTP status
pub(super) status_code: bool,
/// The coprocessor URL for this stage (overrides the global URL if specified)
pub(super) url: Option<String>,
}

#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema)]
Expand All @@ -65,7 +69,7 @@ impl ExecutionStage {
&self,
http_client: C,
service: execution::BoxService,
coprocessor_url: String,
default_url: String,
sdl: Arc<String>,
response_validation: bool,
) -> execution::BoxService
Expand All @@ -82,7 +86,7 @@ impl ExecutionStage {
{
let request_layer = (self.request != Default::default()).then_some({
let request_config = self.request.clone();
let coprocessor_url = coprocessor_url.clone();
let coprocessor_url = request_config.url.clone().unwrap_or(default_url.clone());
let http_client = http_client.clone();
let sdl = sdl.clone();

Expand Down Expand Up @@ -123,6 +127,7 @@ impl ExecutionStage {

let response_layer = (self.response != Default::default()).then_some({
let response_config = self.response.clone();
let coprocessor_url = response_config.url.clone().unwrap_or(default_url);

MapFutureLayer::new(move |fut| {
let coprocessor_url = coprocessor_url.clone();
Expand Down Expand Up @@ -596,6 +601,7 @@ mod tests {
sdl: false,
method: false,
query_plan: false,
url: None,
},
response: Default::default(),
};
Expand Down Expand Up @@ -731,6 +737,7 @@ mod tests {
sdl: false,
method: false,
query_plan: false,
url: None,
},
response: Default::default(),
};
Expand Down Expand Up @@ -803,6 +810,7 @@ mod tests {
body: true,
sdl: true,
status_code: false,
url: None,
},
request: Default::default(),
};
Expand Down Expand Up @@ -939,6 +947,7 @@ mod tests {
body: true,
sdl: true,
status_code: false,
url: None,
},
request: Default::default(),
};
Expand Down Expand Up @@ -1050,6 +1059,7 @@ mod tests {
body: true,
sdl: true,
status_code: false,
url: None,
},
}
}
Expand Down Expand Up @@ -1081,6 +1091,7 @@ mod tests {
sdl: true,
method: true,
query_plan: true,
url: None,
},
response: Default::default(),
}
Expand Down
20 changes: 15 additions & 5 deletions apollo-router/src/plugins/coprocessor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,8 @@ pub(super) struct RouterRequestConf {
pub(super) path: bool,
/// Send the method
pub(super) method: bool,
/// The coprocessor URL for this stage (overrides the global URL if specified)
pub(super) url: Option<String>,
}

/// What information is passed to a router request/response stage
Expand All @@ -347,6 +349,8 @@ pub(super) struct RouterResponseConf {
pub(super) sdl: bool,
/// Send the HTTP status
pub(super) status_code: bool,
/// The coprocessor URL for this stage (overrides the global URL if specified)
pub(super) url: Option<String>,
}
/// What information is passed to a subgraph request/response stage
#[derive(Clone, Debug, Default, Deserialize, PartialEq, JsonSchema)]
Expand All @@ -368,6 +372,8 @@ pub(super) struct SubgraphRequestConf {
pub(super) service_name: bool,
/// Send the subgraph request id
pub(super) subgraph_request_id: bool,
/// The coprocessor URL for this stage (overrides the global URL if specified)
pub(super) url: Option<String>,
}

/// What information is passed to a subgraph request/response stage
Expand All @@ -388,14 +394,16 @@ pub(super) struct SubgraphResponseConf {
pub(super) status_code: bool,
/// Send the subgraph request id
pub(super) subgraph_request_id: bool,
/// The coprocessor URL for this stage (overrides the global URL if specified)
pub(super) url: Option<String>,
}

/// Configures the externalization plugin
#[derive(Clone, Debug, Deserialize, JsonSchema)]
#[serde(deny_unknown_fields)]
#[schemars(rename = "CoprocessorConfig")]
struct Conf {
/// The url you'd like to offload processing to
/// The url you'd like to offload processing to (can be overridden per-stage)
url: String,
client: Option<Client>,
/// The timeout for external requests
Expand Down Expand Up @@ -510,7 +518,7 @@ impl RouterStage {
&self,
http_client: C,
service: router::BoxService,
coprocessor_url: String,
default_url: String,
sdl: Arc<String>,
response_validation: bool,
) -> router::BoxService
Expand All @@ -527,7 +535,7 @@ impl RouterStage {
{
let request_layer = (self.request != Default::default()).then_some({
let request_config = self.request.clone();
let coprocessor_url = coprocessor_url.clone();
let coprocessor_url = request_config.url.clone().unwrap_or(default_url.clone());
let http_client = http_client.clone();
let sdl = sdl.clone();

Expand Down Expand Up @@ -567,6 +575,7 @@ impl RouterStage {

let response_layer = (self.response != Default::default()).then_some({
let response_config = self.response.clone();
let coprocessor_url = response_config.url.clone().unwrap_or(default_url);
MapFutureLayer::new(move |fut| {
let sdl = sdl.clone();
let coprocessor_url = coprocessor_url.clone();
Expand Down Expand Up @@ -648,7 +657,7 @@ impl SubgraphStage {
&self,
http_client: C,
service: subgraph::BoxService,
coprocessor_url: String,
default_url: String,
service_name: String,
response_validation: bool,
) -> subgraph::BoxService
Expand All @@ -666,7 +675,7 @@ impl SubgraphStage {
let request_layer = (self.request != Default::default()).then_some({
let request_config = self.request.clone();
let http_client = http_client.clone();
let coprocessor_url = coprocessor_url.clone();
let coprocessor_url = request_config.url.clone().unwrap_or(default_url.clone());
let service_name = service_name.clone();
AsyncCheckpointLayer::new(move |request: subgraph::Request| {
let http_client = http_client.clone();
Expand Down Expand Up @@ -704,6 +713,7 @@ impl SubgraphStage {

let response_layer = (self.response != Default::default()).then_some({
let response_config = self.response.clone();
let coprocessor_url = response_config.url.clone().unwrap_or(default_url);

MapFutureLayer::new(move |fut| {
let http_client = http_client.clone();
Expand Down
Loading