diff --git a/CHANGELOG.md b/CHANGELOG.md index 3943ae5f..0db778a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -61,6 +61,7 @@ Making a new release? Simply add the new header with the version and date undern * Fixed the sync fallback scrambling sibling order; replacements are now re-parented ancestors-first and in their original child order. ([#1265]) * Instances that share a name and class are now robustly matched on resync by comparing their properties, instead of relying on child order alone. ([#1266]) * Rojo now reports a clear error instead of panicking in several cases, including when the `serve` port is already in use, when a synced file is read-only or locked, when the filesystem watcher can't be created, and when the working directory is inaccessible. ([#1267]) +* Rojo now returns a structured error response instead of panicking when `serve` API request bodies fail to read. ([#1276]) * Fixed `/api/serialize` returning success when a requested instance ID is missing from the serve session tree. ([#1272]) * `rojo serve` now validates the `Host`/`Origin` headers to protect the local/private server against DNS rebinding, gates `/api/open` to local clients, and warns when bound to a network-reachable address. The accepted hosts can be extended with the `--allowed-hosts` option or a project's `serveAllowedHosts` field, for example to reach a network-exposed server by hostname. ([#1270]) * Fixed syncback not removing stale `$properties` entries when Studio resets a property to its engine default. ([#1244]) @@ -79,6 +80,7 @@ Making a new release? Simply add the new header with the version and date undern [#1265]: https://github.com/rojo-rbx/rojo/pull/1265 [#1266]: https://github.com/rojo-rbx/rojo/pull/1266 [#1267]: https://github.com/rojo-rbx/rojo/pull/1267 +[#1276]: https://github.com/rojo-rbx/rojo/pull/1276 [#1272]: https://github.com/rojo-rbx/rojo/pull/1272 [#1270]: https://github.com/rojo-rbx/rojo/pull/1270 [#1244]: https://github.com/rojo-rbx/rojo/pull/1244 diff --git a/src/web/api.rs b/src/web/api.rs index 4fd21c0a..e011ae08 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -4,7 +4,10 @@ use std::{collections::HashMap, fs, net::SocketAddr, path::PathBuf, str::FromStr, sync::Arc}; use futures::{sink::SinkExt, stream::StreamExt}; -use hyper::{body, Body, Method, Request, Response, StatusCode}; +use hyper::{ + body::{self, Bytes}, + Body, Method, Request, Response, StatusCode, +}; use hyper_tungstenite::{is_upgrade_request, tungstenite::Message, upgrade, HyperWebsocket}; use opener::OpenError; use rbx_dom_weak::{ @@ -141,7 +144,10 @@ impl ApiService { let session_id = self.serve_session.session_id(); let tree_mutation_sender = self.serve_session.tree_mutation_sender(); - let body = body::to_bytes(request.into_body()).await.unwrap(); + let body = match read_request_body(request.into_body()).await { + Ok(body) => body, + Err(response) => return response, + }; let request: WriteRequest = match deserialize_msgpack(&body) { Ok(request) => request, @@ -230,7 +236,10 @@ impl ApiService { /// `Value` property set to point to the requested Instance. async fn handle_api_serialize(&self, request: Request
) -> Response { let session_id = self.serve_session.session_id(); - let body = body::to_bytes(request.into_body()).await.unwrap(); + let body = match read_request_body(request.into_body()).await { + Ok(body) => body, + Err(response) => return response, + }; let request: SerializeRequest = match deserialize_msgpack(&body) { Ok(request) => request, @@ -299,7 +308,10 @@ impl ApiService { /// endpoint is used. async fn handle_api_ref_patch(self, request: Request) -> Response { let session_id = self.serve_session.session_id(); - let body = body::to_bytes(request.into_body()).await.unwrap(); + let body = match read_request_body(request.into_body()).await { + Ok(body) => body, + Err(response) => return response, + }; let request: RefPatchRequest = match deserialize_msgpack(&body) { Ok(request) => request, @@ -456,6 +468,15 @@ impl ApiService { } } +async fn read_request_body(body: Body) -> Result