Skip to main content

turbo_tasks_fetch/
error.rs

1use anyhow::Result;
2use async_trait::async_trait;
3use turbo_rcstr::{RcStr, rcstr};
4use turbo_tasks::{ResolvedVc, Vc};
5use turbo_tasks_fs::FileSystemPath;
6use turbopack_core::issue::{Issue, IssueSeverity, IssueStage, StyledString};
7
8// Route every `reqwest::…` path in this module to the local stand-in on wasm.
9#[cfg(target_family = "wasm")]
10use crate::wasm_reqwest as reqwest;
11
12#[derive(Debug)]
13#[turbo_tasks::value(shared)]
14pub enum FetchErrorKind {
15    Connect,
16    Timeout,
17    Status(u16),
18    Other,
19}
20
21#[turbo_tasks::value(shared)]
22pub struct FetchError {
23    pub url: ResolvedVc<RcStr>,
24    pub kind: ResolvedVc<FetchErrorKind>,
25    pub detail: ResolvedVc<StyledString>,
26}
27
28impl FetchError {
29    pub(crate) fn from_reqwest_error(error: &reqwest::Error, url: &str) -> FetchError {
30        let kind = if error.is_connect() {
31            FetchErrorKind::Connect
32        } else if error.is_timeout() {
33            FetchErrorKind::Timeout
34        } else if let Some(status) = error.status() {
35            FetchErrorKind::Status(status.as_u16())
36        } else {
37            FetchErrorKind::Other
38        };
39
40        FetchError {
41            detail: StyledString::Text(error.to_string().into()).resolved_cell(),
42            url: ResolvedVc::cell(url.into()),
43            kind: kind.resolved_cell(),
44        }
45    }
46}
47
48#[turbo_tasks::value_impl]
49impl FetchError {
50    #[turbo_tasks::function]
51    pub fn to_issue(
52        &self,
53        severity: IssueSeverity,
54        issue_context: FileSystemPath,
55    ) -> Vc<FetchIssue> {
56        FetchIssue {
57            issue_context,
58            severity,
59            url: self.url,
60            kind: self.kind,
61            detail: self.detail,
62        }
63        .cell()
64    }
65}
66
67#[turbo_tasks::value(shared)]
68pub struct FetchIssue {
69    pub issue_context: FileSystemPath,
70    pub severity: IssueSeverity,
71    pub url: ResolvedVc<RcStr>,
72    pub kind: ResolvedVc<FetchErrorKind>,
73    pub detail: ResolvedVc<StyledString>,
74}
75
76#[async_trait]
77#[turbo_tasks::value_impl]
78impl Issue for FetchIssue {
79    async fn file_path(&self) -> Result<FileSystemPath> {
80        Ok(self.issue_context.clone())
81    }
82
83    fn severity(&self) -> IssueSeverity {
84        self.severity
85    }
86
87    async fn title(&self) -> Result<StyledString> {
88        Ok(StyledString::Text(rcstr!(
89            "Error while requesting resource"
90        )))
91    }
92
93    fn stage(&self) -> IssueStage {
94        IssueStage::Load
95    }
96
97    async fn description(&self) -> Result<Option<StyledString>> {
98        let url = &*self.url.await?;
99        let kind = &*self.kind.await?;
100
101        Ok(Some(match kind {
102            FetchErrorKind::Connect => StyledString::Line(vec![
103                StyledString::Text(rcstr!(
104                    "There was an issue establishing a connection while requesting "
105                )),
106                StyledString::Code(url.clone()),
107            ]),
108            FetchErrorKind::Status(status) => StyledString::Line(vec![
109                StyledString::Text(rcstr!("Received response with status ")),
110                StyledString::Code(RcStr::from(status.to_string())),
111                StyledString::Text(rcstr!(" when requesting ")),
112                StyledString::Code(url.clone()),
113            ]),
114            FetchErrorKind::Timeout => StyledString::Line(vec![
115                StyledString::Text(rcstr!("Connection timed out when requesting ")),
116                StyledString::Code(url.clone()),
117            ]),
118            FetchErrorKind::Other => StyledString::Line(vec![
119                StyledString::Text(rcstr!("There was an issue requesting ")),
120                StyledString::Code(url.clone()),
121            ]),
122        }))
123    }
124
125    async fn detail(&self) -> Result<Option<StyledString>> {
126        Ok(Some((*self.detail.await?).clone()))
127    }
128}