dicomweb_client/reqwest/
async_reqwest.rs

1use std::convert::TryFrom;
2use std::io::Cursor;
3
4use crate::{Error, Result};
5use bytes::Buf;
6use dicom::object::{DefaultDicomObject, InMemDicomObject};
7use dicomweb_util::{dicom_from_reader, json2dicom, parse_multipart_body};
8use http::header::HeaderName;
9use http::{HeaderMap, HeaderValue};
10use reqwest::Proxy;
11use serde::de::DeserializeOwned;
12use serde::Serialize;
13use serde_json::Value;
14
15use super::{DICOMwebClientReqwest, QueryBuilderReqwest, RequestBuilderTrait};
16use super::{ReqwestClient, ReqwestClientBuilder};
17
18pub type Client = DICOMwebClientReqwest<reqwest::Client, reqwest::ClientBuilder>;
19
20pub type QueryBuilder = QueryBuilderReqwest<reqwest::RequestBuilder>;
21
22impl ReqwestClientBuilder for reqwest::ClientBuilder {
23    type Client = reqwest::Client;
24
25    fn new() -> Self {
26        Self::new()
27    }
28
29    fn proxy(self, proxy: Proxy) -> Self {
30        self.proxy(proxy)
31    }
32
33    fn default_headers(self, headers: HeaderMap) -> Self {
34        self.default_headers(headers)
35    }
36    fn build(self) -> reqwest::Result<Self::Client> {
37        self.build()
38    }
39}
40
41impl ReqwestClient for reqwest::Client {
42    type ClientBuilder = reqwest::ClientBuilder;
43    type RequestBuilder = reqwest::RequestBuilder;
44
45    fn get<U: reqwest::IntoUrl>(&self, url: U) -> Self::RequestBuilder {
46        self.get(url)
47    }
48}
49impl RequestBuilderTrait for reqwest::RequestBuilder {
50    fn header<K, V>(self, key: K, value: V) -> Self
51    where
52        HeaderName: TryFrom<K>,
53        HeaderValue: TryFrom<V>,
54        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,
55        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
56    {
57        self.header(key, value)
58    }
59
60    fn query<T: Serialize + ?Sized>(self, query: &T) -> Self {
61        self.query(query)
62    }
63}
64
65impl QueryBuilder {
66    pub async fn results(self) -> Result<Vec<InMemDicomObject>> {
67        let res = self.send().await?;
68        let content_type = res.headers()["content-type"].to_str()?;
69        println!("content-type: {}", content_type);
70
71        if !content_type.starts_with("application/dicom+json") {
72            return Err(Error::DICOMweb(
73                "invalid content type, should be application/dicom+json".to_string(),
74            ));
75        }
76
77        let json: Vec<Value> = res.json().await?;
78        Ok(json2dicom(&json)?)
79    }
80
81    pub async fn dicoms(self) -> Result<Vec<DefaultDicomObject>> {
82        let res = self.send().await?;
83        let content_type = res.headers()["content-type"].to_str().unwrap();
84        println!("content-type: {}", content_type);
85        let (_, boundary) = content_type.rsplit_once("boundary=").unwrap();
86        let boundary = String::from(boundary);
87        println!("boundary: {}", boundary);
88
89        let body = res.bytes().await?;
90        let parts = parse_multipart_body(body, &boundary)?;
91        let result = parts
92            .iter()
93            .map(|part| {
94                let reader = Cursor::new(part).reader();
95                dicom_from_reader(reader).unwrap()
96            })
97            .collect();
98        Ok(result)
99    }
100
101    pub async fn send(self) -> reqwest::Result<reqwest::Response> {
102        self.request_builder.send().await
103    }
104}