dicomweb_client/reqwest/
async_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::{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}