Skip to content

Commit

Permalink
Add asset streaming via range requests
Browse files Browse the repository at this point in the history
  • Loading branch information
przydatek committed Aug 28, 2024
1 parent a1f63eb commit f5a414e
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 7 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ pocket-ic
.env

.DS_Store
.idea
8 changes: 8 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ http-body-util = "0.1"
bytes = "1"
base64 = "0.22"
lazy_static = "1"
regex = "1.10"
serde = "1"
serde_cbor = "0.11"
tokio = { version = "1", features = ["full"] }
Expand All @@ -45,6 +46,7 @@ ic-agent = "0.37"
ic-utils = "0.37"
candid = "0.10"
pocket-ic = "=3.0.0"
assert_matches = "1.5"

ic-certification = { git = "https://github.com/dfinity/response-verification" }
ic-http-certification = { git = "https://github.com/dfinity/response-verification" }
Expand Down
2 changes: 2 additions & 0 deletions packages/ic-http-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ http.workspace = true
http-body.workspace = true
http-body-util.workspace = true
bytes.workspace = true
regex.workspace = true

ic-agent.workspace = true
ic-utils.workspace = true
Expand All @@ -35,5 +36,6 @@ ic-http-certification.workspace = true
ic-response-verification.workspace = true

[dev-dependencies]
assert_matches.workspace = true
pocket-ic.workspace = true
tokio.workspace = true
1 change: 1 addition & 0 deletions packages/ic-http-gateway/src/consts.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub(crate) static CACHE_HEADER_NAME: &str = "cache-control";
pub(crate) static ACCEPT_ENCODING_HEADER_NAME: &str = "accept-encoding";
pub(crate) static CONTENT_RANGE_HEADER_NAME: &str = "content-range";

pub(crate) static DEFAULT_BOUNDARY_NODE_ENDPOINT: &str = "https://icp-api.io";
40 changes: 35 additions & 5 deletions packages/ic-http-gateway/src/protocol/handler.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::validate;
use crate::{
get_body_and_streaming_body, CanisterRequest, CanisterResponse, HttpGatewayError,
HttpGatewayResponse, HttpGatewayResponseBody, HttpGatewayResponseMetadata, HttpGatewayResult,
ACCEPT_ENCODING_HEADER_NAME, CACHE_HEADER_NAME,
get_206_stream_response_body, get_body_and_streaming_body, CanisterRequest, CanisterResponse,
HttpGatewayError, HttpGatewayResponse, HttpGatewayResponseBody, HttpGatewayResponseMetadata,
HttpGatewayResult, ACCEPT_ENCODING_HEADER_NAME, CACHE_HEADER_NAME,
};
use candid::Principal;
use http::{Response, StatusCode};
Expand Down Expand Up @@ -186,7 +186,7 @@ pub async fn process_request(
let validation_result = validate(
agent,
&canister_id,
http_request,
http_request.clone(),
HttpResponse {
status_code: agent_response.status_code,
headers: agent_response
Expand Down Expand Up @@ -299,6 +299,36 @@ pub async fn process_request(
}
}

let response_body: HttpGatewayResponseBody = if status_code == 206 {
// We got only the first chunk, turn the response into a streaming response
match get_206_stream_response_body(
agent,
&http_request,
canister_id,
&agent_response.headers,
response_body,
)
.await
{
Ok(stream_response_body) => stream_response_body,
Err(e) => {
return HttpGatewayResponse {
canister_response: create_err_response(
StatusCode::INTERNAL_SERVER_ERROR,
&format!("Failed to create streaming responsey: {}", e),
),
metadata: HttpGatewayResponseMetadata {
upgraded_to_update_call: is_update_call,
response_verification_version: None,
internal_error: Some(e.into()),
},
}
}
}
} else {
response_body
};

let response = match response_builder.body(response_body) {
Ok(response) => response,
Err(e) => {
Expand Down Expand Up @@ -326,7 +356,7 @@ pub async fn process_request(
}
}

fn handle_agent_error(error: &AgentError) -> CanisterResponse {
pub(crate) fn handle_agent_error(error: &AgentError) -> CanisterResponse {
match error {
// Turn all `DestinationInvalid`s into 404
AgentError::CertifiedReject(RejectResponse {
Expand Down
2 changes: 1 addition & 1 deletion packages/ic-http-gateway/src/protocol/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod handler;
pub(crate) mod handler;
pub(crate) use handler::*;

mod validate;
Expand Down
Loading

0 comments on commit f5a414e

Please sign in to comment.