Skip to content

Commit ac406d8

Browse files
committed
wire test script for uploading files for code dx analysis
1 parent 56c16cd commit ac406d8

1 file changed

Lines changed: 69 additions & 16 deletions

File tree

src/main.rs

Lines changed: 69 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use clap::{Arg, ArgMatches, App};
1414
use serde::de::DeserializeOwned;
1515
use std::collections::HashMap;
1616
use std::option::Option::*;
17+
use std::io::Read;
18+
use std::path::Path;
1719
use url::{Url};
1820

1921
fn main() {
@@ -48,6 +50,12 @@ fn main() {
4850
Err(e) => println!("Error querying projects: {:?}", e),
4951
}
5052

53+
println!();
54+
match client.test_upload().expect_success().expect_json::<ApiAnalysisJobResponse>() {
55+
Ok(response) => println!("wow a success response: {:?}", response),
56+
Err(e) => println!("Error uploading file: {:?}", e),
57+
}
58+
5159
println!();
5260
println!("Done.");
5361
},
@@ -73,29 +81,28 @@ struct ApiProject {
7381
parent_id: Option<u32>,
7482
}
7583

84+
#[derive(Debug, Deserialize)]
85+
struct ApiAnalysisJobResponse {
86+
#[serde(rename = "analysisId")]
87+
analysis_id: u32,
88+
#[serde(rename = "jobId")]
89+
job_id: String
90+
}
91+
7692
enum ReqBody {
93+
Form(reqwest::multipart::Form),
7794
Json(serde_json::Value),
7895
None,
79-
// TODO: support multipart forms
8096
}
8197

8298
impl From<serde_json::Value> for ReqBody {
8399
fn from(json: serde_json::Value) -> ReqBody {
84100
ReqBody::Json(json)
85101
}
86102
}
87-
88-
impl From<ReqBody> for hyper::Body {
89-
fn from(body: ReqBody) -> hyper::Body {
90-
match body {
91-
ReqBody::Json(value) => {
92-
let raw_body = serde_json::to_vec(&value).unwrap();
93-
hyper::Body::from(raw_body)
94-
},
95-
ReqBody::None => {
96-
hyper::Body::empty()
97-
}
98-
}
103+
impl From<reqwest::multipart::Form> for ReqBody {
104+
fn from(form: reqwest::multipart::Form) -> ReqBody {
105+
ReqBody::Form(form)
99106
}
100107
}
101108

@@ -107,7 +114,34 @@ struct ApiClient {
107114
#[derive(Debug)]
108115
enum ApiError {
109116
Protocol(reqwest::Error),
110-
NonSuccess(hyper::StatusCode)
117+
NonSuccess(hyper::StatusCode, ApiErrorMessage),
118+
IO(std::io::Error),
119+
}
120+
impl From<std::io::Error> for ApiError {
121+
fn from(e: std::io::Error) -> ApiError {
122+
ApiError::IO(e)
123+
}
124+
}
125+
126+
#[derive(Debug)]
127+
enum ApiErrorMessage {
128+
Nice(String),
129+
Raw(String)
130+
}
131+
impl ApiErrorMessage {
132+
fn from_body(response: &mut reqwest::Response) -> Result<ApiErrorMessage, ApiError> {
133+
let mut body = String::new();
134+
response.read_to_string(&mut body).map_err(ApiError::from).and_then(|size|{
135+
serde_json::from_str::<ErrorMessageResponse>(&body)
136+
.map(|err_body| ApiErrorMessage::Nice(err_body.error))
137+
.or_else(|_| Ok(ApiErrorMessage::Raw(body)))
138+
})
139+
}
140+
}
141+
142+
#[derive(Deserialize)]
143+
struct ErrorMessageResponse {
144+
error: String
111145
}
112146

113147
type ApiResult<T> = Result<T, ApiError>;
@@ -123,11 +157,13 @@ impl ApiResponse {
123157
}
124158

125159
fn expect_success(self) -> ApiResponse {
126-
ApiResponse(self.0.and_then(|response| {
160+
ApiResponse(self.0.and_then(move |mut response| {
127161
if response.status().is_success() {
128162
Ok(response)
129163
} else {
130-
Err(ApiError::NonSuccess(response.status()))
164+
ApiErrorMessage::from_body(&mut response).and_then(|response_msg| {
165+
Err(ApiError::NonSuccess(response.status(), response_msg))
166+
})
131167
}
132168
}))
133169
}
@@ -166,6 +202,20 @@ impl ApiClient {
166202
.expect_json()
167203
}
168204

205+
fn test_upload(&self) -> ApiResponse {
206+
let file_path = Path::new("D:/CodeDx/data-sets/webgoat-r437/src-r437.zip");
207+
// let file_path = Path::new("./Cargo.toml");
208+
let form = reqwest::multipart::Form::new()
209+
.file("file1", file_path)
210+
.map_err(|e| ApiError::IO(e));
211+
212+
let foo = form.and_then(|form| {
213+
self.api_post(&["api", "projects", "4", "analysis"], form).get()
214+
});
215+
216+
ApiResponse::from(foo)
217+
}
218+
169219
fn api_get(&self, path_segments: &[&str]) -> ApiResponse {
170220
self.api_request(hyper::Method::Get, path_segments, ReqBody::None)
171221
}
@@ -192,6 +242,9 @@ impl ApiClient {
192242
ReqBody::Json(ref json) => {
193243
request_builder.json(json);
194244
},
245+
ReqBody::Form(form) => {
246+
request_builder.multipart(form);
247+
}
195248
ReqBody::None => (),
196249
};
197250
ApiResponse::from(request_builder.send().map_err(ApiError::from))

0 commit comments

Comments
 (0)