refget_client/
blocking.rs1use refget_model::{ComparisonResult, SeqCol, SeqColLevel1, SequenceMetadata, SequenceServiceInfo};
4use reqwest::StatusCode;
5use reqwest::blocking::{Client, RequestBuilder, Response};
6use serde_json::Value;
7
8use crate::error::{ClientError, ClientResult};
9use crate::response::{self, MetadataResponse};
10
11pub struct RefgetClientBlocking {
16 client: Client,
17 base_url: String,
18}
19
20impl RefgetClientBlocking {
21 pub fn new(base_url: &str) -> ClientResult<Self> {
23 let client = Client::builder().build().map_err(ClientError::Http)?;
24 Self::with_client(client, base_url)
25 }
26
27 pub fn with_client(client: Client, base_url: &str) -> ClientResult<Self> {
29 if base_url.is_empty() {
30 return Err(ClientError::InvalidUrl("base URL must not be empty".to_string()));
31 }
32 Ok(Self { client, base_url: base_url.trim_end_matches('/').to_string() })
33 }
34
35 fn send_optional(&self, req: RequestBuilder) -> ClientResult<Option<Response>> {
40 let resp = req.send()?;
41 let status = resp.status();
42 if status.is_success() {
43 Ok(Some(resp))
44 } else if status == StatusCode::NOT_FOUND {
45 Ok(None)
46 } else {
47 let body = resp.text().unwrap_or_default();
48 Err(ClientError::ServerError { status: status.as_u16(), body })
49 }
50 }
51
52 fn send_required(&self, req: RequestBuilder) -> ClientResult<Response> {
54 let resp = req.send()?;
55 if resp.status().is_success() {
56 Ok(resp)
57 } else {
58 let status = resp.status().as_u16();
59 let body = resp.text().unwrap_or_default();
60 Err(ClientError::ServerError { status, body })
61 }
62 }
63
64 pub fn get_sequence(
71 &self,
72 digest: &str,
73 start: Option<u64>,
74 end: Option<u64>,
75 ) -> ClientResult<Option<Vec<u8>>> {
76 let mut req = self.client.get(format!("{}/sequence/{digest}", self.base_url));
77 if let Some(s) = start {
78 req = req.query(&[("start", s)]);
79 }
80 if let Some(e) = end {
81 req = req.query(&[("end", e)]);
82 }
83 match self.send_optional(req)? {
84 Some(resp) => Ok(Some(resp.bytes()?.to_vec())),
85 None => Ok(None),
86 }
87 }
88
89 pub fn get_metadata(&self, digest: &str) -> ClientResult<Option<SequenceMetadata>> {
91 let req = self.client.get(format!("{}/sequence/{digest}/metadata", self.base_url));
92 match self.send_optional(req)? {
93 Some(resp) => {
94 let envelope: MetadataResponse = resp.json()?;
95 Ok(Some(envelope.metadata))
96 }
97 None => Ok(None),
98 }
99 }
100
101 pub fn get_sequence_service_info(&self) -> ClientResult<SequenceServiceInfo> {
103 let req = self.client.get(format!("{}/sequence/service-info", self.base_url));
104 let resp = self.send_required(req)?;
105 let value: Value = resp.json()?;
106 response::deserialize_sequence_service_info(value).map_err(ClientError::Deserialize)
107 }
108
109 pub fn get_collection_level0(&self, digest: &str) -> ClientResult<Option<String>> {
113 let req = self
114 .client
115 .get(format!("{}/collection/{digest}", self.base_url))
116 .query(&[("level", "0")]);
117 match self.send_optional(req)? {
118 Some(resp) => {
119 let value: Value = resp.json()?;
120 match value.as_str() {
121 Some(s) => Ok(Some(s.to_string())),
122 None => Ok(Some(value.to_string())),
123 }
124 }
125 None => Ok(None),
126 }
127 }
128
129 pub fn get_collection_level1(&self, digest: &str) -> ClientResult<Option<SeqColLevel1>> {
131 let req = self
132 .client
133 .get(format!("{}/collection/{digest}", self.base_url))
134 .query(&[("level", "1")]);
135 match self.send_optional(req)? {
136 Some(resp) => Ok(Some(resp.json()?)),
137 None => Ok(None),
138 }
139 }
140
141 pub fn get_collection_level2(&self, digest: &str) -> ClientResult<Option<SeqCol>> {
143 let req = self
144 .client
145 .get(format!("{}/collection/{digest}", self.base_url))
146 .query(&[("level", "2")]);
147 match self.send_optional(req)? {
148 Some(resp) => Ok(Some(resp.json()?)),
149 None => Ok(None),
150 }
151 }
152
153 pub fn get_collection_raw(&self, digest: &str, level: u8) -> ClientResult<Option<Value>> {
155 let req = self
156 .client
157 .get(format!("{}/collection/{digest}", self.base_url))
158 .query(&[("level", level.to_string())]);
159 match self.send_optional(req)? {
160 Some(resp) => Ok(Some(resp.json()?)),
161 None => Ok(None),
162 }
163 }
164
165 pub fn compare_collections(
167 &self,
168 digest_a: &str,
169 digest_b: &str,
170 ) -> ClientResult<ComparisonResult> {
171 let req = self.client.get(format!("{}/comparison/{digest_a}/{digest_b}", self.base_url));
172 Ok(self.send_required(req)?.json()?)
173 }
174
175 pub fn compare_collection_with(
177 &self,
178 digest: &str,
179 collection: &SeqCol,
180 ) -> ClientResult<ComparisonResult> {
181 let req =
182 self.client.post(format!("{}/comparison/{digest}", self.base_url)).json(collection);
183 Ok(self.send_required(req)?.json()?)
184 }
185
186 pub fn list_collections(
190 &self,
191 filters: &[(&str, &str)],
192 page: usize,
193 page_size: usize,
194 ) -> ClientResult<Value> {
195 let mut req = self
196 .client
197 .get(format!("{}/list/collection", self.base_url))
198 .query(&[("page", page.to_string()), ("page_size", page_size.to_string())]);
199 for (key, value) in filters {
200 req = req.query(&[(key, value)]);
201 }
202 Ok(self.send_required(req)?.json()?)
203 }
204
205 pub fn get_attribute(&self, attr: &str, digest: &str) -> ClientResult<Option<Value>> {
207 let req =
208 self.client.get(format!("{}/attribute/collection/{attr}/{digest}", self.base_url));
209 match self.send_optional(req)? {
210 Some(resp) => Ok(Some(resp.json()?)),
211 None => Ok(None),
212 }
213 }
214
215 pub fn get_seqcol_service_info(&self) -> ClientResult<Value> {
217 let req = self.client.get(format!("{}/service-info", self.base_url));
218 Ok(self.send_required(req)?.json()?)
219 }
220}