fix(http): reject unsupported codecs with 415 and the codec as body

This commit is contained in:
2026-08-08 13:42:08 +01:00
parent aa1d4e8f67
commit 7d9b3b6285
4 changed files with 35 additions and 31 deletions
+4 -7
View File
@@ -63,7 +63,7 @@ pub struct ServerInfo {
pub struct HttpServer {
pub offer_tx: Sender<(i32, i32, String)>,
pub accept_rx: async_broadcast::InactiveReceiver<(i32, Option<String>)>,
pub accept_rx: async_broadcast::InactiveReceiver<(i32, Result<String, String>)>,
pub appstate: Arc<Mutex<AppState>>,
pub request_count: AtomicI32,
pub db: DatabaseConnection,
@@ -456,18 +456,15 @@ async fn stream_handler(
})
.await
{
Ok(Some(Some(reply))) => {
Ok(Some(Ok(reply))) => {
return Ok(Response::builder()
.status(StatusCode::CREATED)
.header("content-type", "application/sdp")
.body(reply)
.unwrap());
}
Ok(Some(None)) => {
return Ok(Response::builder()
.status(StatusCode::UNSUPPORTED_MEDIA_TYPE)
.body(String::new())
.unwrap());
Ok(Some(Err(codec))) => {
return Err(HttpError::WhepCodecError(codec));
}
Ok(None) => {
info!(
+11 -6
View File
@@ -25,6 +25,8 @@ pub enum HttpError {
Unprocessable(String),
#[error("not acceptable: {0}")]
NotAcceptable(String),
#[error("unsupported codec: {0}")]
WhepCodecError(String),
#[error("internal error")]
Internal,
}
@@ -40,6 +42,7 @@ impl HttpError {
Self::BadRequest(_) => StatusCode::BAD_REQUEST,
Self::Unprocessable(_) => StatusCode::UNPROCESSABLE_ENTITY,
Self::NotAcceptable(_) => StatusCode::NOT_ACCEPTABLE,
Self::WhepCodecError(_) => StatusCode::UNSUPPORTED_MEDIA_TYPE,
}
}
}
@@ -47,12 +50,14 @@ impl HttpError {
impl IntoResponse for HttpError {
fn into_response(self) -> Response<Body> {
let status = self.status();
// Only surface a message body for client (4xx) errors; keep an empty
// body for 5xx so internal details aren't leaked.
let body = if status.is_client_error() {
self.to_string()
} else {
String::new()
let body = match self {
// The WHEP client (frontend) reads this body as the rejected
// codec, so send it bare rather than the full error string.
Self::WhepCodecError(codec) => codec,
// Only surface a message body for client (4xx) errors; keep an
// empty body for 5xx so internal details aren't leaked.
e if status.is_client_error() => e.to_string(),
_ => String::new(),
};
(status, body).into_response()
}
+1 -1
View File
@@ -102,7 +102,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
// String_Label,
// Offer_body
let (answer_tx, answer_rx) = broadcast::<(i32, Option<String>)>(64);
let (answer_tx, answer_rx) = broadcast::<(i32, Result<String, String>)>(64);
// Request_Id,
// Answer_body
+11 -9
View File
@@ -19,7 +19,7 @@ use crate::{
pub struct Webrtc {
pub offer_rx: Receiver<(i32, i32, String)>,
pub accept_tx: async_broadcast::Sender<(i32, Option<String>)>,
pub accept_tx: async_broadcast::Sender<(i32, Result<String, String>)>,
pub sessions_ref: Arc<DashMap<i32, StreamSession>>,
pub proxy: Arc<WebrtcProxy>,
pub db: DatabaseConnection,
@@ -40,7 +40,7 @@ impl Webrtc {
request_id,
stream_id, "stream key not found in DB, rejecting offer"
);
self.accept_tx.broadcast((request_id, None)).await.unwrap();
self.accept_tx.broadcast((request_id, Err(String::new()))).await.unwrap();
continue;
}
if let Err(ref e) = stream_key {
@@ -48,7 +48,7 @@ impl Webrtc {
request_id,
stream_id, "DB error looking up stream key: {:?}", e
);
self.accept_tx.broadcast((request_id, None)).await.unwrap();
self.accept_tx.broadcast((request_id, Err(String::new()))).await.unwrap();
continue;
}
@@ -134,7 +134,7 @@ impl Webrtc {
Ok(sdp) => sdp,
Err(e) => {
warn!(request_id, stream_id, "malformed SDP offer: {:?}", e);
self.accept_tx.broadcast((request_id, None)).await.unwrap();
self.accept_tx.broadcast((request_id, Err(String::new()))).await.unwrap();
continue;
}
};
@@ -179,7 +179,10 @@ impl Webrtc {
"no video codec negotiated — browser likely doesn't support {:?}; rejecting offer",
stream_codec
);
self.accept_tx.broadcast((request_id, None)).await.unwrap();
self.accept_tx
.broadcast((request_id, Err(format!("{:?}", stream_codec))))
.await
.unwrap();
continue;
}
@@ -193,7 +196,7 @@ impl Webrtc {
debug!(request_id, "sending answer back");
self.accept_tx
.broadcast((request_id, Some(answer_sdp)))
.broadcast((request_id, Ok(answer_sdp)))
.await
.unwrap();
@@ -310,8 +313,8 @@ impl Webrtc {
}
_ => {}
},
Err(e) => {
error!("poll_output error (connection closing): {:?}", e);
Err(_e) => {
// error!("poll_output error (connection closing): {:?}", e);
return;
}
}
@@ -489,4 +492,3 @@ impl Webrtc {
}
}
}