Adds CONTENT_LENGTH workaround for CocoaHTTPServer bug
This commit is contained in:
@@ -13,7 +13,6 @@ use async_trait::async_trait;
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
|
||||
use tokio::net::TcpStream;
|
||||
use tokio_util::io::ReaderStream;
|
||||
|
||||
use futures_util::stream::{BoxStream, Stream};
|
||||
use futures_util::task::Context;
|
||||
@@ -292,32 +291,45 @@ impl<K: AuthenticationStore + Send + Sync> APIInterface for HTTPAPIClient<K> {
|
||||
|
||||
async fn upload_attachment<R>(
|
||||
&mut self,
|
||||
data: tokio::io::BufReader<R>,
|
||||
mut data: tokio::io::BufReader<R>,
|
||||
filename: &str,
|
||||
size: u64,
|
||||
) -> Result<String, Self::Error>
|
||||
where
|
||||
R: tokio::io::AsyncRead + Unpin + Send + Sync + 'static,
|
||||
{
|
||||
use tokio::io::AsyncReadExt;
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct UploadAttachmentResponse {
|
||||
#[serde(rename = "fileTransferGUID")]
|
||||
guid: String,
|
||||
}
|
||||
|
||||
// TODO: We can still use Body::wrap_stream here, but we need to make sure to plumb the CONTENT_LENGTH header,
|
||||
// otherwise CocoaHTTPServer will crash because of a bug.
|
||||
//
|
||||
// See ff03e73758f30c081a9319a8c04025cba69b8393 for what this was like before.
|
||||
let mut bytes = Vec::new();
|
||||
data.read_to_end(&mut bytes)
|
||||
.await
|
||||
.map_err(|e| Error::ClientError(e.to_string()))?;
|
||||
|
||||
let endpoint = format!("uploadAttachment?filename={}", filename);
|
||||
let mut data_opt = Some(data);
|
||||
let mut bytes_opt = Some(bytes);
|
||||
|
||||
let response: UploadAttachmentResponse = self
|
||||
.deserialized_response_with_body_retry(
|
||||
&endpoint,
|
||||
Method::POST,
|
||||
move || {
|
||||
let stream = ReaderStream::new(
|
||||
data_opt.take().expect("Stream already consumed during retry"),
|
||||
);
|
||||
Body::wrap_stream(stream)
|
||||
Body::from(
|
||||
bytes_opt
|
||||
.take()
|
||||
.expect("Body already consumed during retry"),
|
||||
)
|
||||
},
|
||||
false, // don't retry auth for streaming body
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ pub trait APIInterface {
|
||||
&mut self,
|
||||
data: tokio::io::BufReader<R>,
|
||||
filename: &str,
|
||||
size: u64,
|
||||
) -> Result<String, Self::Error>
|
||||
where
|
||||
R: tokio::io::AsyncRead + Unpin + Send + Sync + 'static;
|
||||
|
||||
@@ -132,6 +132,7 @@ impl APIInterface for TestClient {
|
||||
&mut self,
|
||||
data: tokio::io::BufReader<R>,
|
||||
filename: &str,
|
||||
size: u64,
|
||||
) -> Result<String, Self::Error>
|
||||
where
|
||||
R: tokio::io::AsyncRead + Unpin + Send + Sync + 'static,
|
||||
|
||||
@@ -195,7 +195,10 @@ impl AttachmentStore {
|
||||
let filename = incoming_path.file_name().unwrap().to_str().unwrap();
|
||||
log::trace!(target: target::ATTACHMENTS, "Uploading attachment to server: {}", &filename);
|
||||
let mut client = Daemon::get_client_impl(database).await?;
|
||||
let guid = client.upload_attachment(reader, filename).await?;
|
||||
|
||||
let metadata = std::fs::metadata(&temporary_path)?;
|
||||
let size = metadata.len();
|
||||
let guid = client.upload_attachment(reader, filename, size).await?;
|
||||
|
||||
// Delete the temporary file.
|
||||
log::debug!(target: target::ATTACHMENTS, "Upload completed with guid {}, deleting temporary file: {}", guid, temporary_path.display());
|
||||
|
||||
Reference in New Issue
Block a user