Use msgpack for API (#1176)

This commit is contained in:
Micah
2026-02-12 18:37:24 -08:00
committed by GitHub
parent 4df2d3c5f8
commit 4deda0e155
15 changed files with 177 additions and 102 deletions

View File

@@ -13,7 +13,6 @@ use rbx_dom_weak::{
};
use crate::{
json,
serve_session::ServeSession,
snapshot::{InstanceWithMeta, PatchSet, PatchUpdate},
web::{
@@ -22,11 +21,10 @@ use crate::{
ServerInfoResponse, SocketPacket, SocketPacketBody, SocketPacketType, SubscribeMessage,
WriteRequest, WriteResponse, PROTOCOL_VERSION, SERVER_VERSION,
},
util::{json, json_ok},
util::{deserialize_msgpack, msgpack, msgpack_ok, serialize_msgpack},
},
web_api::{
BufferEncode, InstanceUpdate, RefPatchRequest, RefPatchResponse, SerializeRequest,
SerializeResponse,
InstanceUpdate, RefPatchRequest, RefPatchResponse, SerializeRequest, SerializeResponse,
},
};
@@ -42,7 +40,7 @@ pub async fn call(serve_session: Arc<ServeSession>, mut request: Request<Body>)
if is_upgrade_request(&request) {
service.handle_api_socket(&mut request).await
} else {
json(
msgpack(
ErrorResponse::bad_request(
"/api/socket must be called as a websocket upgrade request",
),
@@ -58,7 +56,7 @@ pub async fn call(serve_session: Arc<ServeSession>, mut request: Request<Body>)
}
(&Method::POST, "/api/write") => service.handle_api_write(request).await,
(_method, path) => json(
(_method, path) => msgpack(
ErrorResponse::not_found(format!("Route not found: {}", path)),
StatusCode::NOT_FOUND,
),
@@ -79,7 +77,7 @@ impl ApiService {
let tree = self.serve_session.tree();
let root_instance_id = tree.get_root_id();
json_ok(&ServerInfoResponse {
msgpack_ok(&ServerInfoResponse {
server_version: SERVER_VERSION.to_owned(),
protocol_version: PROTOCOL_VERSION,
session_id: self.serve_session.session_id(),
@@ -98,7 +96,7 @@ impl ApiService {
let input_cursor: u32 = match argument.parse() {
Ok(v) => v,
Err(err) => {
return json(
return msgpack(
ErrorResponse::bad_request(format!("Malformed message cursor: {}", err)),
StatusCode::BAD_REQUEST,
);
@@ -109,7 +107,7 @@ impl ApiService {
let (response, websocket) = match upgrade(request, None) {
Ok(result) => result,
Err(err) => {
return json(
return msgpack(
ErrorResponse::internal_error(format!("WebSocket upgrade failed: {}", err)),
StatusCode::INTERNAL_SERVER_ERROR,
);
@@ -136,10 +134,10 @@ impl ApiService {
let body = body::to_bytes(request.into_body()).await.unwrap();
let request: WriteRequest = match json::from_slice(&body) {
let request: WriteRequest = match deserialize_msgpack(&body) {
Ok(request) => request,
Err(err) => {
return json(
return msgpack(
ErrorResponse::bad_request(format!("Invalid body: {}", err)),
StatusCode::BAD_REQUEST,
);
@@ -147,7 +145,7 @@ impl ApiService {
};
if request.session_id != session_id {
return json(
return msgpack(
ErrorResponse::bad_request("Wrong session ID"),
StatusCode::BAD_REQUEST,
);
@@ -173,7 +171,7 @@ impl ApiService {
})
.unwrap();
json_ok(WriteResponse { session_id })
msgpack_ok(WriteResponse { session_id })
}
async fn handle_api_read(&self, request: Request<Body>) -> Response<Body> {
@@ -183,7 +181,7 @@ impl ApiService {
let requested_ids = match requested_ids {
Ok(ids) => ids,
Err(_) => {
return json(
return msgpack(
ErrorResponse::bad_request("Malformed ID list"),
StatusCode::BAD_REQUEST,
);
@@ -207,7 +205,7 @@ impl ApiService {
}
}
json_ok(ReadResponse {
msgpack_ok(ReadResponse {
session_id: self.serve_session.session_id(),
message_cursor,
instances,
@@ -225,10 +223,10 @@ impl ApiService {
let session_id = self.serve_session.session_id();
let body = body::to_bytes(request.into_body()).await.unwrap();
let request: SerializeRequest = match json::from_slice(&body) {
let request: SerializeRequest = match deserialize_msgpack(&body) {
Ok(request) => request,
Err(err) => {
return json(
return msgpack(
ErrorResponse::bad_request(format!("Invalid body: {}", err)),
StatusCode::BAD_REQUEST,
);
@@ -236,7 +234,7 @@ impl ApiService {
};
if request.session_id != session_id {
return json(
return msgpack(
ErrorResponse::bad_request("Wrong session ID"),
StatusCode::BAD_REQUEST,
);
@@ -269,7 +267,7 @@ impl ApiService {
response_dom.transfer_within(child_ref, object_value);
} else {
json(
msgpack(
ErrorResponse::bad_request(format!("provided id {id} is not in the tree")),
StatusCode::BAD_REQUEST,
);
@@ -280,9 +278,9 @@ impl ApiService {
let mut source = Vec::new();
rbx_binary::to_writer(&mut source, &response_dom, &[response_dom.root_ref()]).unwrap();
json_ok(SerializeResponse {
msgpack_ok(SerializeResponse {
session_id: self.serve_session.session_id(),
model_contents: BufferEncode::new(source),
model_contents: source,
})
}
@@ -294,10 +292,10 @@ impl ApiService {
let session_id = self.serve_session.session_id();
let body = body::to_bytes(request.into_body()).await.unwrap();
let request: RefPatchRequest = match json::from_slice(&body) {
let request: RefPatchRequest = match deserialize_msgpack(&body) {
Ok(request) => request,
Err(err) => {
return json(
return msgpack(
ErrorResponse::bad_request(format!("Invalid body: {}", err)),
StatusCode::BAD_REQUEST,
);
@@ -305,7 +303,7 @@ impl ApiService {
};
if request.session_id != session_id {
return json(
return msgpack(
ErrorResponse::bad_request("Wrong session ID"),
StatusCode::BAD_REQUEST,
);
@@ -338,7 +336,7 @@ impl ApiService {
}
}
json_ok(RefPatchResponse {
msgpack_ok(RefPatchResponse {
session_id: self.serve_session.session_id(),
patch: SubscribeMessage {
added: HashMap::new(),
@@ -354,7 +352,7 @@ impl ApiService {
let requested_id = match Ref::from_str(argument) {
Ok(id) => id,
Err(_) => {
return json(
return msgpack(
ErrorResponse::bad_request("Invalid instance ID"),
StatusCode::BAD_REQUEST,
);
@@ -366,7 +364,7 @@ impl ApiService {
let instance = match tree.get_instance(requested_id) {
Some(instance) => instance,
None => {
return json(
return msgpack(
ErrorResponse::bad_request("Instance not found"),
StatusCode::NOT_FOUND,
);
@@ -376,7 +374,7 @@ impl ApiService {
let script_path = match pick_script_path(instance) {
Some(path) => path,
None => {
return json(
return msgpack(
ErrorResponse::bad_request(
"No appropriate file could be found to open this script",
),
@@ -389,7 +387,7 @@ impl ApiService {
Ok(()) => {}
Err(error) => match error {
OpenError::Io(io_error) => {
return json(
return msgpack(
ErrorResponse::internal_error(format!(
"Attempting to open {} failed because of the following io error: {}",
script_path.display(),
@@ -403,7 +401,7 @@ impl ApiService {
status,
stderr,
} => {
return json(
return msgpack(
ErrorResponse::internal_error(format!(
r#"The command '{}' to open '{}' failed with the error code '{}'.
Error logs:
@@ -419,7 +417,7 @@ impl ApiService {
},
};
json_ok(OpenResponse {
msgpack_ok(OpenResponse {
session_id: self.serve_session.session_id(),
})
}
@@ -483,7 +481,7 @@ async fn handle_websocket_subscription(
match result {
Ok((new_cursor, messages)) => {
if !messages.is_empty() {
let json_message = {
let msgpack_message = {
let tree = tree_handle.lock().unwrap();
let api_messages = messages
.into_iter()
@@ -499,12 +497,12 @@ async fn handle_websocket_subscription(
}),
};
serde_json::to_string(&response)?
serialize_msgpack(response)?
};
log::debug!("Sending batch of messages over WebSocket subscription");
if websocket.send(Message::Text(json_message)).await.is_err() {
if websocket.send(Message::Binary(msgpack_message)).await.is_err() {
// Client disconnected
log::debug!("WebSocket subscription closed by client");
break;