http_nu/
response.rs

1use nu_protocol::Value;
2use std::collections::HashMap;
3use std::path::PathBuf;
4
5#[derive(Clone, Debug, serde::Serialize)]
6#[serde(untagged)]
7pub enum HeaderValue {
8    Single(String),
9    Multiple(Vec<String>),
10}
11
12#[derive(Clone, Debug)]
13pub struct Response {
14    pub status: u16,
15    pub headers: HashMap<String, HeaderValue>,
16    pub body_type: ResponseBodyType,
17}
18
19#[derive(Clone, Debug)]
20pub enum ResponseBodyType {
21    Normal,
22    Static {
23        root: PathBuf,
24        path: String,
25        fallback: Option<String>,
26    },
27    ReverseProxy {
28        target_url: String,
29        headers: HashMap<String, HeaderValue>,
30        preserve_host: bool,
31        strip_prefix: Option<String>,
32        request_body: Vec<u8>,
33        query: Option<HashMap<String, String>>,
34    },
35}
36
37#[derive(Debug)]
38pub enum ResponseTransport {
39    Empty,
40    Full(Vec<u8>),
41    Stream(tokio::sync::mpsc::Receiver<Vec<u8>>),
42}
43
44pub fn value_to_json(value: &Value) -> serde_json::Value {
45    match value {
46        Value::Nothing { .. } => serde_json::Value::Null,
47        Value::Bool { val, .. } => serde_json::Value::Bool(*val),
48        Value::Int { val, .. } => serde_json::Value::Number((*val).into()),
49        Value::Float { val, .. } => serde_json::Number::from_f64(*val)
50            .map(serde_json::Value::Number)
51            .unwrap_or(serde_json::Value::Null),
52        Value::String { val, .. } => serde_json::Value::String(val.clone()),
53        Value::List { vals, .. } => {
54            serde_json::Value::Array(vals.iter().map(value_to_json).collect())
55        }
56        Value::Record { val, .. } => {
57            let mut map = serde_json::Map::new();
58            for (k, v) in val.iter() {
59                map.insert(k.clone(), value_to_json(v));
60            }
61            serde_json::Value::Object(map)
62        }
63        _ => todo!(),
64    }
65}
66
67pub fn value_to_bytes(value: Value) -> Vec<u8> {
68    match value {
69        Value::Nothing { .. } => Vec::new(),
70        Value::String { val, .. } => val.into_bytes(),
71        Value::Int { val, .. } => val.to_string().into_bytes(),
72        Value::Float { val, .. } => val.to_string().into_bytes(),
73        Value::Binary { val, .. } => val,
74        Value::Bool { val, .. } => val.to_string().into_bytes(),
75
76        // Records with __html field are unwrapped to HTML string
77        Value::Record { val, .. } if val.get("__html").is_some() => match val.get("__html") {
78            Some(Value::String { val, .. }) => val.clone().into_bytes(),
79            _ => Vec::new(),
80        },
81
82        // Both Lists and Records are encoded as JSON
83        Value::List { .. } | Value::Record { .. } => serde_json::to_string(&value_to_json(&value))
84            .unwrap_or_else(|_| String::new())
85            .into_bytes(),
86
87        _ => todo!("value_to_bytes: {:?}", value),
88    }
89}