dicomweb_client/reqwest/
blocking_reqwest.rs1use 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}