Skip to main content

pve_api/simple/
request.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2026 Luke Harding <luke@lukeh990.io>
3
4use crate::{Pve, PveError};
5use reqwest::StatusCode;
6use serde_json::Value;
7use std::collections::HashMap;
8
9/// Build up a request. Usually this just allows you to add parameters before
10/// sending.
11#[derive(Debug)]
12pub struct RequestBuilder {
13    path: String,
14    method: RequestMethod,
15    parameters: Option<HashMap<String, String>>,
16    pve: Pve,
17}
18
19/// Describes the HTTP method in use.
20#[derive(Debug)]
21pub enum RequestMethod {
22    Get,
23    Post,
24    Put,
25    Delete,
26}
27
28impl RequestBuilder {
29    /// Creates a new [`RequestBuilder`] pulling client and base URL from
30    /// [`Pve`]. Path specifies the sub path for the endpoint.
31    pub fn new(pve: &Pve, path: String, method: RequestMethod) -> Self {
32        RequestBuilder {
33            path,
34            method,
35            parameters: None,
36            pve: pve.clone(),
37        }
38    }
39
40    /// Since this will always be encoded in www-form-urlencoded it can be
41    /// represented in a [`HashMap<String, String>`] just fine. This will
42    /// init and add to a HashMap which is encoded when [`Self::send`] is
43    /// called.
44    pub fn add_parameter<S: Into<String>>(mut self, name: S, value: S) -> Self {
45        let map = self.parameters.get_or_insert_with(HashMap::new);
46
47        map.insert(name.into(), value.into());
48
49        self
50    }
51
52    /// Create and send the HTTP request. Response will come back as a
53    /// [`serde_json::Value`] type.
54    pub async fn send(self) -> Result<Value, PveError> {
55        let url = self.pve.base_url.join(&self.path)?;
56
57        let builder = if let Some(parameters) = self.parameters {
58            match self.method {
59                RequestMethod::Get => self.pve.client.get(url).query(&parameters),
60                RequestMethod::Post => self.pve.client.post(url).form(&parameters),
61                RequestMethod::Put => self.pve.client.put(url).form(&parameters),
62                RequestMethod::Delete => self.pve.client.delete(url).query(&parameters),
63            }
64        } else {
65            match self.method {
66                RequestMethod::Get => self.pve.client.get(url),
67                RequestMethod::Post => self.pve.client.post(url),
68                RequestMethod::Put => self.pve.client.put(url),
69                RequestMethod::Delete => self.pve.client.delete(url),
70            }
71        };
72
73        let response = builder.send().await?;
74        let status = response.status();
75
76        if status == StatusCode::OK {
77            Ok(response.json().await?)
78        } else {
79            Err(Pve::process_err_resp(status, response.text().await?))
80        }
81    }
82}