use crate::api::client::UploadClient;
use crate::constants::DEFAULT_FILENAME;
use crate::https::{get_https_client, tls};
use crate::models::*;
use crate::types::Result;
use std::io::{Cursor, Read};
use hyper::client::HttpConnector;
use hyper::{body::Bytes, Body as HBody, Client, Request};
use hyper_multipart::client::multipart::Form;
use hyper_multipart_rfc7578 as hyper_multipart;
use hyper_multipart_rfc7578::client::multipart::Body;
pub async fn stream_uploader_with_url(
url: &str,
client: impl Into<Option<Client<tls::HttpsConnector<HttpConnector>>>>,
) -> Result<StreamUploader<'_, Cursor<Bytes>>> {
let client = client.into().unwrap_or_else(get_https_client);
let req = Request::get(url).body(HBody::empty())?;
let resp = client.request(req).await?;
let (_, body) = resp.into_parts();
let bytes = hyper::body::to_bytes(body).await?;
let reader = std::io::Cursor::new(bytes);
StreamUploader::new(reader)
}
#[derive(Clone)]
pub struct StreamUploader<'a, R: 'static + Read + Send + Sync, B = Body> {
client: UploadClient<B>,
req: UploadStreamRequest<'a>,
reader: Option<R>,
}
impl<'a, R: 'static + Read + Send + Sync> StreamUploader<'a, R> {
pub fn new(stream: R) -> Result<Self> {
Self::with_stream_and_filename(stream, DEFAULT_FILENAME)
}
pub fn with_stream_and_filename(stream: R, file_name: &'a str) -> Result<Self> {
Ok(Self {
client: UploadClient::from_env()?,
req: UploadStreamRequest::new(file_name),
reader: Some(stream),
})
}
pub fn with_filename(file_name: &'a str) -> Result<Self> {
Ok(Self {
client: UploadClient::from_env()?,
req: UploadStreamRequest::new(file_name),
reader: None,
})
}
pub fn with_token(access_token: &str) -> Self {
Self {
client: UploadClient::from_token(access_token),
req: UploadStreamRequest::new(DEFAULT_FILENAME),
reader: None,
}
}
pub fn with_client(client: UploadClient<Body>) -> Self {
Self {
client,
req: UploadStreamRequest::new(DEFAULT_FILENAME),
reader: None,
}
}
pub fn stream(mut self, stream: R) -> Self {
self.reader = Some(stream);
self
}
pub fn project_id(mut self, project_id: &'a str) -> Self {
self.req.project_id = Some(project_id);
self
}
pub fn name(mut self, name: &'a str) -> Self {
self.req.name = Some(name);
self
}
pub fn description(mut self, description: &'a str) -> Self {
self.req.description = Some(description);
self
}
pub fn contact_id(mut self, contact_id: &'a str) -> Self {
self.req.contact_id = Some(contact_id);
self
}
pub async fn send(self) -> Result<UploadResponse> {
let params = UploadRequest {
access_token: self.client.access_token.as_str(),
url: None,
project_id: self.req.project_id,
name: self.req.name,
description: None,
contact_id: self.req.contact_id,
};
let url = UploadClient::<Body>::build_url(params)?;
let req_builder = Request::post(&url);
let mut form = Form::default();
form.add_reader_file("file", self.reader.unwrap(), self.req.file_name);
if let Some(description) = self.req.description {
form.add_text("description", description);
}
let form = form.set_body::<Body>(req_builder).unwrap();
self.client.make_request(&url, form).await
}
}