dicomweb_client/reqwest/
blocking_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::RequestBuilderTrait;
16use super::{DICOMwebClientReqwest, QueryBuilderReqwest, ReqwestClient, ReqwestClientBuilder};
17
18pub type Client =
19    DICOMwebClientReqwest<reqwest::blocking::Client, reqwest::blocking::ClientBuilder>;
20
21pub type QueryBuilder = QueryBuilderReqwest<reqwest::blocking::RequestBuilder>;
22
23impl ReqwestClientBuilder for reqwest::blocking::ClientBuilder {
24    type Client = reqwest::blocking::Client;
25
26    fn new() -> Self {
27        Self::new()
28    }
29
30    fn proxy(self, proxy: Proxy) -> Self {
31        self.proxy(proxy)
32    }
33
34    fn default_headers(self, headers: HeaderMap) -> Self {
35        self.default_headers(headers)
36    }
37
38    fn build(self) -> reqwest::Result<Self::Client> {
39        self.build()
40    }
41}
42
43impl ReqwestClient for reqwest::blocking::Client {
44    type ClientBuilder = reqwest::blocking::ClientBuilder;
45    type RequestBuilder = reqwest::blocking::RequestBuilder;
46
47    fn get<U: reqwest::IntoUrl>(&self, url: U) -> Self::RequestBuilder {
48        self.get(url)
49    }
50}
51
52impl RequestBuilderTrait for reqwest::blocking::RequestBuilder {
53    fn header<K, V>(self, key: K, value: V) -> Self
54    where
55        HeaderName: TryFrom<K>,
56        HeaderValue: TryFrom<V>,
57        <HeaderName as TryFrom<K>>::Error: Into<http::Error>,
58        <HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
59    {
60        self.header(key, value)
61    }
62
63    fn query<T: Serialize + ?Sized>(self, query: &T) -> Self {
64        self.query(query)
65    }
66}
67
68impl QueryBuilder {
69    pub fn results(self) -> Result<Vec<InMemDicomObject>> {
70        let res = self.send()?;
71        let content_type = res
72            .headers()
73            .get("content-type")
74            .ok_or(Error::DICOMweb(
75                "no content type on response, should be application/dicom+json".to_string(),
76            ))?
77            .to_str()?;
78        println!("content-type: {}", content_type);
79
80        if !content_type.starts_with("application/dicom+json") {
81            return Err(Error::DICOMweb(
82                "invalid content type, should be application/dicom+json".to_string(),
83            ));
84        }
85
86        let json: Vec<Value> = res.json()?;
87        Ok(json2dicom(&json)?)
88    }
89
90    pub fn dicoms(self) -> Result<Vec<DefaultDicomObject>> {
91        let res = self.send()?;
92        let content_type = res
93            .headers()
94            .get("content-type")
95            .ok_or(Error::DICOMweb(
96                "no content type on response, should be multipart/related".to_string(),
97            ))?
98            .to_str()?;
99        println!("content-type: {}", content_type);
100        if !content_type.starts_with("multipart/related") {
101            return Err(Error::DICOMweb(
102                "invalid content type, should be multipart/related".to_string(),
103            ));
104        }
105        let (_, boundary) = content_type.rsplit_once("boundary=").unwrap();
106        let boundary = String::from(boundary);
107        println!("boundary: {}", boundary);
108
109        let body = res.bytes()?;
110        let parts = parse_multipart_body(body, &boundary)?;
111        let result = parts
112            .iter()
113            .map(|part| {
114                let reader = Cursor::new(part).reader();
115                dicom_from_reader(reader).unwrap()
116            })
117            .collect();
118        Ok(result)
119    }
120
121    pub fn send(self) -> reqwest::Result<reqwest::blocking::Response> {
122        self.request_builder.send()
123    }
124}