junobuild_storage/
http_request.rs

1use crate::constants::{RESPONSE_STATUS_CODE_200, RESPONSE_STATUS_CODE_405};
2use crate::http::response::{
3    build_asset_response, build_redirect_raw_response, build_redirect_response, error_response,
4};
5use crate::http::types::{
6    HttpRequest, HttpResponse, StreamingCallbackHttpResponse, StreamingCallbackToken,
7};
8use crate::http::utils::create_token;
9use crate::routing::get_routing;
10use crate::strategies::{StorageCertificateStrategy, StorageStateStrategy};
11use crate::types::http_request::{
12    Routing, RoutingDefault, RoutingRedirect, RoutingRedirectRaw, RoutingRewrite,
13};
14use ic_cdk::trap;
15
16// ---------------------------------------------------------
17// Http
18// ---------------------------------------------------------
19
20pub fn http_request(
21    HttpRequest {
22        method,
23        url,
24        headers: req_headers,
25        body: _,
26        certificate_version,
27    }: HttpRequest,
28    storage_state: &impl StorageStateStrategy,
29    certificate: &impl StorageCertificateStrategy,
30) -> HttpResponse {
31    if method != "GET" {
32        return error_response(RESPONSE_STATUS_CODE_405, "Method Not Allowed.".to_string());
33    }
34
35    let result = get_routing(url, &req_headers, true, storage_state);
36
37    match result {
38        Ok(routing) => match routing {
39            Routing::Default(RoutingDefault { url, asset }) => build_asset_response(
40                url,
41                req_headers,
42                certificate_version,
43                asset,
44                None,
45                RESPONSE_STATUS_CODE_200,
46                storage_state,
47                certificate,
48            ),
49            Routing::Rewrite(RoutingRewrite {
50                url,
51                asset,
52                source,
53                status_code,
54            }) => build_asset_response(
55                url,
56                req_headers,
57                certificate_version,
58                asset,
59                Some(source),
60                status_code,
61                storage_state,
62                certificate,
63            ),
64            Routing::Redirect(RoutingRedirect {
65                url,
66                redirect,
67                iframe,
68            }) => {
69                build_redirect_response(url, certificate_version, &redirect, &iframe, certificate)
70            }
71            Routing::RedirectRaw(RoutingRedirectRaw {
72                redirect_url,
73                iframe,
74            }) => build_redirect_raw_response(&redirect_url, &iframe),
75        },
76        Err(err) => error_response(
77            RESPONSE_STATUS_CODE_405,
78            ["Permission denied. Cannot perform this operation. ", err].join(""),
79        ),
80    }
81}
82
83pub fn http_request_streaming_callback(
84    StreamingCallbackToken {
85        token,
86        headers,
87        index,
88        sha256: _,
89        full_path,
90        encoding_type,
91        memory: _,
92    }: StreamingCallbackToken,
93    storage_state: &impl StorageStateStrategy,
94) -> StreamingCallbackHttpResponse {
95    let asset = storage_state.get_public_asset(full_path, token);
96
97    match asset {
98        Some((asset, memory)) => {
99            let encoding = asset.encodings.get(&encoding_type);
100
101            match encoding {
102                Some(encoding) => {
103                    let body = storage_state.get_content_chunks(encoding, index, &memory);
104
105                    match body {
106                        Some(body) => StreamingCallbackHttpResponse {
107                            token: create_token(
108                                &asset.key,
109                                index,
110                                encoding,
111                                &encoding_type,
112                                &headers,
113                                &memory,
114                            ),
115                            body: body.clone(),
116                        },
117                        None => trap("Streamed chunks not found."),
118                    }
119                }
120                None => trap("Streamed asset encoding not found."),
121            }
122        }
123        None => trap("Streamed asset not found."),
124    }
125}