nvd_api/
lib.rs

1//! [![github]](https://github.com/emo-crab/nvd-rs) [![crates-io]](https://crates.io/crates/nvd-api) [![docs-rs]](crate)
2//!
3//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
4//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
5//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
6//!
7use std::fmt::Display;
8
9use reqwest::{ClientBuilder, RequestBuilder};
10
11use crate::error::Error;
12use crate::pagination::ListResponse;
13
14pub mod error;
15pub mod pagination;
16pub mod v2;
17
18const BASE_URL: &str = "https://services.nvd.nist.gov/rest/json/";
19
20#[derive(Debug, Clone)]
21pub struct NVDApi {
22  base_path: String,
23  version: String,
24  client: reqwest::Client,
25}
26
27pub enum ApiVersion {
28  V2_0,
29}
30
31impl Default for ApiVersion {
32  fn default() -> Self {
33    Self::V2_0
34  }
35}
36
37impl Display for ApiVersion {
38  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
39    write!(
40      f,
41      "{}",
42      match self {
43        ApiVersion::V2_0 => String::from("2.0"),
44      }
45    )
46  }
47}
48
49impl NVDApi {
50  pub fn new(api_token: Option<String>, version: ApiVersion) -> Result<Self, Error> {
51    let mut headers = reqwest::header::HeaderMap::new();
52    if let Some(api_token) = api_token {
53      let mut auth_value = reqwest::header::HeaderValue::from_str(&format!("Bearer {api_token}"))
54        .map_err(|source| Error::InvalidApiToken { source })?;
55      auth_value.set_sensitive(true);
56      headers.insert(reqwest::header::AUTHORIZATION, auth_value);
57    }
58    let api_client = ClientBuilder::new()
59      .default_headers(headers)
60      .build()
61      .map_err(|source| Error::BuildingClient { source })?;
62    Ok(NVDApi {
63      base_path: BASE_URL.to_owned(),
64      version: version.to_string(),
65      client: api_client,
66    })
67  }
68}
69
70impl NVDApi {
71  pub async fn request(&self, request: RequestBuilder) -> Result<ListResponse, Error> {
72    let request = request.build()?;
73    let json = self
74      .client
75      .execute(request)
76      .await
77      .map_err(|source| Error::RequestFailed { source })?
78      .text()
79      .await
80      .map_err(|source| Error::ResponseIo { source })?;
81    let result = serde_json::from_str(&json).map_err(|source| Error::JsonParse { source })?;
82    Ok(result)
83  }
84}