Skip to main content

framework_web/
context.rs

1use crate::{WebError, WebRequest};
2use anyhow::{Result, anyhow};
3use bytes::Bytes;
4use framework_core::MultiStringValue;
5use serde_json::{Map, Value};
6use std::future::Future;
7use std::sync::{Arc, OnceLock};
8
9pub struct WebContext {
10    request: Arc<WebRequest>,
11    body_json: OnceLock<Value>,
12    query_json: OnceLock<Value>,
13}
14
15impl WebContext {
16    pub fn new(request: Arc<WebRequest>) -> Self {
17        Self {
18            request,
19            body_json: OnceLock::new(),
20            query_json: OnceLock::new(),
21        }
22    }
23
24    pub fn request(&self) -> &WebRequest {
25        &self.request
26    }
27
28    pub fn request_arc(&self) -> Arc<WebRequest> {
29        Arc::clone(&self.request)
30    }
31
32    pub fn query(&self) -> &MultiStringValue {
33        &self.request.query
34    }
35
36    pub fn body(&self) -> Bytes {
37        self.request.body.clone()
38    }
39
40    pub fn body_json(&self) -> Result<&Value> {
41        if let Some(value) = self.body_json.get() {
42            return Ok(value);
43        }
44
45        let value = serde_json::from_slice::<Value>(&self.request.body)
46            .map_err(|error| WebError::parameter("请求体不是有效的 JSON", error))?;
47        self.body_json
48            .set(value)
49            .map_err(|_| anyhow!("请求体 JSON 缓存设置失败"))?;
50        self.body_json
51            .get()
52            .ok_or_else(|| anyhow!("请求体 JSON 缓存读取失败"))
53    }
54
55    pub fn query_json(&self) -> Result<&Value> {
56        if let Some(value) = self.query_json.get() {
57            return Ok(value);
58        }
59
60        let mut object = Map::new();
61        self.request.query.for_each(|name, values| {
62            let value = if values.len() == 1 {
63                Value::String(values[0].clone())
64            } else {
65                Value::Array(
66                    values
67                        .iter()
68                        .map(|item| Value::String(item.clone()))
69                        .collect(),
70                )
71            };
72            object.insert(name.clone(), value);
73        });
74        self.query_json
75            .set(Value::Object(object))
76            .map_err(|_| anyhow!("查询参数 JSON 缓存设置失败"))?;
77        self.query_json
78            .get()
79            .ok_or_else(|| anyhow!("查询参数 JSON 缓存读取失败"))
80    }
81}
82
83tokio::task_local! {
84    static WEB_CONTEXT: Arc<WebContext>;
85}
86
87pub async fn scope_web<F>(context: Arc<WebContext>, future: F) -> F::Output
88where
89    F: Future,
90{
91    WEB_CONTEXT.scope(context, future).await
92}
93
94pub fn use_web() -> Result<Arc<WebContext>> {
95    WEB_CONTEXT
96        .try_with(Arc::clone)
97        .map_err(|error| anyhow!("当前调用不在 Web 上下文作用域内:{error}"))
98}