Update Actix crates to latest versions

This avoids a vulnerability in tokio (#3085). The major version updates
of both actix-web and actix-rt required some signficant changes. Chief
among those, it turns out we were relying on actix-rt to run the
HttpServer in a different thread from the rest of the test, so that we
could talk to it from sync code in the test thread. This no longer
works, so the sync code is now run in a dedicated thread with
`actix_rt::task::spawn_blocking`.
This commit is contained in:
Dustin J. Mitchell
2023-04-08 09:30:28 -04:00
committed by Dustin J. Mitchell
parent 33366e2f05
commit 52fdc6a877
10 changed files with 466 additions and 990 deletions

View File

@@ -19,9 +19,11 @@ const MAX_SIZE: usize = 100 * 1024 * 1024;
pub(crate) async fn service(
req: HttpRequest,
server_state: web::Data<Arc<ServerState>>,
web::Path((version_id,)): web::Path<(VersionId,)>,
path: web::Path<VersionId>,
mut payload: web::Payload,
) -> Result<HttpResponse> {
let version_id = path.into_inner();
// check content-type
if req.content_type() != SNAPSHOT_CONTENT_TYPE {
return Err(error::ErrorBadRequest("Bad content-type"));
@@ -100,8 +102,8 @@ mod test {
let uri = format!("/v1/client/add-snapshot/{}", version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header("Content-Type", "application/vnd.taskchampion.snapshot")
.header("X-Client-Key", client_key.to_string())
.insert_header(("Content-Type", "application/vnd.taskchampion.snapshot"))
.insert_header(("X-Client-Key", client_key.to_string()))
.set_payload(b"abcd".to_vec())
.to_request();
let resp = test::call_service(&mut app, req).await;
@@ -111,14 +113,14 @@ mod test {
let uri = "/v1/client/snapshot";
let req = test::TestRequest::get()
.uri(uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let mut resp = test::call_service(&mut app, req).await;
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
use futures::StreamExt;
let (bytes, _) = resp.take_body().into_future().await;
assert_eq!(bytes.unwrap().unwrap().as_ref(), b"abcd");
use actix_web::body::MessageBody;
let bytes = resp.into_body().try_into_bytes().unwrap();
assert_eq!(bytes.as_ref(), b"abcd");
Ok(())
}
@@ -143,8 +145,8 @@ mod test {
let uri = format!("/v1/client/add-snapshot/{}", version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header("Content-Type", "application/vnd.taskchampion.snapshot")
.header("X-Client-Key", client_key.to_string())
.append_header(("Content-Type", "application/vnd.taskchampion.snapshot"))
.append_header(("X-Client-Key", client_key.to_string()))
.set_payload(b"abcd".to_vec())
.to_request();
let resp = test::call_service(&mut app, req).await;
@@ -154,7 +156,7 @@ mod test {
let uri = "/v1/client/snapshot";
let req = test::TestRequest::get()
.uri(uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
@@ -172,8 +174,8 @@ mod test {
let uri = format!("/v1/client/add-snapshot/{}", version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header("Content-Type", "not/correct")
.header("X-Client-Key", client_key.to_string())
.append_header(("Content-Type", "not/correct"))
.append_header(("X-Client-Key", client_key.to_string()))
.set_payload(b"abcd".to_vec())
.to_request();
let resp = test::call_service(&mut app, req).await;
@@ -192,11 +194,11 @@ mod test {
let uri = format!("/v1/client/add-snapshot/{}", version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header(
.append_header((
"Content-Type",
"application/vnd.taskchampion.history-segment",
)
.header("X-Client-Key", client_key.to_string())
))
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

View File

@@ -27,9 +27,11 @@ const MAX_SIZE: usize = 100 * 1024 * 1024;
pub(crate) async fn service(
req: HttpRequest,
server_state: web::Data<Arc<ServerState>>,
web::Path((parent_version_id,)): web::Path<(VersionId,)>,
path: web::Path<VersionId>,
mut payload: web::Payload,
) -> Result<HttpResponse> {
let parent_version_id = path.into_inner();
// check content-type
if req.content_type() != HISTORY_SEGMENT_CONTENT_TYPE {
return Err(error::ErrorBadRequest("Bad content-type"));
@@ -80,21 +82,21 @@ pub(crate) async fn service(
Ok(match result {
AddVersionResult::Ok(version_id) => {
let mut rb = HttpResponse::Ok();
rb.header(VERSION_ID_HEADER, version_id.to_string());
rb.append_header((VERSION_ID_HEADER, version_id.to_string()));
match snap_urgency {
SnapshotUrgency::None => {}
SnapshotUrgency::Low => {
rb.header(SNAPSHOT_REQUEST_HEADER, "urgency=low");
rb.append_header((SNAPSHOT_REQUEST_HEADER, "urgency=low"));
}
SnapshotUrgency::High => {
rb.header(SNAPSHOT_REQUEST_HEADER, "urgency=high");
rb.append_header((SNAPSHOT_REQUEST_HEADER, "urgency=high"));
}
};
rb.finish()
}
AddVersionResult::ExpectedParentVersion(parent_version_id) => {
let mut rb = HttpResponse::Conflict();
rb.header(PARENT_VERSION_ID_HEADER, parent_version_id.to_string());
rb.append_header((PARENT_VERSION_ID_HEADER, parent_version_id.to_string()));
rb.finish()
}
})
@@ -128,11 +130,11 @@ mod test {
let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header(
.append_header((
"Content-Type",
"application/vnd.taskchampion.history-segment",
)
.header("X-Client-Key", client_key.to_string())
))
.append_header(("X-Client-Key", client_key.to_string()))
.set_payload(b"abcd".to_vec())
.to_request();
let resp = test::call_service(&mut app, req).await;
@@ -170,11 +172,11 @@ mod test {
let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header(
.append_header((
"Content-Type",
"application/vnd.taskchampion.history-segment",
)
.header("X-Client-Key", client_key.to_string())
))
.append_header(("X-Client-Key", client_key.to_string()))
.set_payload(b"abcd".to_vec())
.to_request();
let resp = test::call_service(&mut app, req).await;
@@ -198,8 +200,8 @@ mod test {
let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header("Content-Type", "not/correct")
.header("X-Client-Key", client_key.to_string())
.append_header(("Content-Type", "not/correct"))
.append_header(("X-Client-Key", client_key.to_string()))
.set_payload(b"abcd".to_vec())
.to_request();
let resp = test::call_service(&mut app, req).await;
@@ -218,11 +220,11 @@ mod test {
let uri = format!("/v1/client/add-version/{}", parent_version_id);
let req = test::TestRequest::post()
.uri(&uri)
.header(
.append_header((
"Content-Type",
"application/vnd.taskchampion.history-segment",
)
.header("X-Client-Key", client_key.to_string())
))
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);

View File

@@ -18,8 +18,10 @@ use std::sync::Arc;
pub(crate) async fn service(
req: HttpRequest,
server_state: web::Data<Arc<ServerState>>,
web::Path((parent_version_id,)): web::Path<(VersionId,)>,
path: web::Path<VersionId>,
) -> Result<HttpResponse> {
let parent_version_id = path.into_inner();
let mut txn = server_state.storage.txn().map_err(failure_to_ise)?;
let client_key = client_key_header(&req)?;
@@ -44,8 +46,8 @@ pub(crate) async fn service(
history_segment,
} => Ok(HttpResponse::Ok()
.content_type(HISTORY_SEGMENT_CONTENT_TYPE)
.header(VERSION_ID_HEADER, version_id.to_string())
.header(PARENT_VERSION_ID_HEADER, parent_version_id.to_string())
.append_header((VERSION_ID_HEADER, version_id.to_string()))
.append_header((PARENT_VERSION_ID_HEADER, parent_version_id.to_string()))
.body(history_segment)),
GetVersionResult::NotFound => Err(error::ErrorNotFound("no such version")),
GetVersionResult::Gone => Err(error::ErrorGone("version has been deleted")),
@@ -83,9 +85,9 @@ mod test {
let uri = format!("/v1/client/get-child-version/{}", parent_version_id);
let req = test::TestRequest::get()
.uri(&uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let mut resp = test::call_service(&mut app, req).await;
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
assert_eq!(
resp.headers().get("X-Version-Id").unwrap(),
@@ -100,9 +102,9 @@ mod test {
&"application/vnd.taskchampion.history-segment".to_string()
);
use futures::StreamExt;
let (bytes, _) = resp.take_body().into_future().await;
assert_eq!(bytes.unwrap().unwrap().as_ref(), b"abcd");
use actix_web::body::MessageBody;
let bytes = resp.into_body().try_into_bytes().unwrap();
assert_eq!(bytes.as_ref(), b"abcd");
}
#[actix_rt::test]
@@ -117,7 +119,7 @@ mod test {
let uri = format!("/v1/client/get-child-version/{}", parent_version_id);
let req = test::TestRequest::get()
.uri(&uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
@@ -144,7 +146,7 @@ mod test {
let uri = format!("/v1/client/get-child-version/{}", parent_version_id);
let req = test::TestRequest::get()
.uri(&uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::GONE);
@@ -157,7 +159,7 @@ mod test {
let uri = format!("/v1/client/get-child-version/{}", NIL_VERSION_ID);
let req = test::TestRequest::get()
.uri(&uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND);

View File

@@ -32,7 +32,7 @@ pub(crate) async fn service(
{
Ok(HttpResponse::Ok()
.content_type(SNAPSHOT_CONTENT_TYPE)
.header(VERSION_ID_HEADER, version_id.to_string())
.append_header((VERSION_ID_HEADER, version_id.to_string()))
.body(data))
} else {
Err(error::ErrorNotFound("no snapshot"))
@@ -66,7 +66,7 @@ mod test {
let uri = "/v1/client/snapshot";
let req = test::TestRequest::get()
.uri(uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
@@ -102,13 +102,13 @@ mod test {
let uri = "/v1/client/snapshot";
let req = test::TestRequest::get()
.uri(uri)
.header("X-Client-Key", client_key.to_string())
.append_header(("X-Client-Key", client_key.to_string()))
.to_request();
let mut resp = test::call_service(&mut app, req).await;
let resp = test::call_service(&mut app, req).await;
assert_eq!(resp.status(), StatusCode::OK);
use futures::StreamExt;
let (bytes, _) = resp.take_body().into_future().await;
assert_eq!(bytes.unwrap().unwrap().as_ref(), snapshot_data);
use actix_web::body::MessageBody;
let bytes = resp.into_body().try_into_bytes().unwrap();
assert_eq!(bytes.as_ref(), snapshot_data);
}
}