@@ -3382,18 +3382,37 @@ fn start_moq_webtransport_acceptor(
33823382
33833383 let auth_state = Arc :: clone ( & app_state. auth ) ;
33843384
3385- // Parse address for WebTransport (UDP will use the same port as HTTP/HTTPS)
3386- let addr: SocketAddr = config. server . address . parse ( ) ?;
3385+ // Parse address for WebTransport — use moq_address when set, otherwise fall back
3386+ // to the main server address (same port for HTTP and QUIC).
3387+ let addr: SocketAddr =
3388+ config. server . moq_address . as_deref ( ) . unwrap_or ( & config. server . address ) . parse ( ) ?;
3389+
3390+ // Configure TLS for MoQ WebTransport.
3391+ // Priority: moq_cert_path/moq_key_path → server cert_path/key_path (when tls=true) → self-signed.
3392+ let moq_cert = config. server . moq_cert_path . as_deref ( ) . filter ( |s| !s. is_empty ( ) ) ;
3393+ let moq_key = config. server . moq_key_path . as_deref ( ) . filter ( |s| !s. is_empty ( ) ) ;
3394+
3395+ if moq_cert. is_some ( ) != moq_key. is_some ( ) {
3396+ return Err ( format ! (
3397+ "Invalid MoQ TLS config: both moq_cert_path and moq_key_path must be set (got cert={:?}, key={:?})" ,
3398+ config. server. moq_cert_path, config. server. moq_key_path
3399+ ) . into ( ) ) ;
3400+ }
33873401
3388- // Configure TLS - use provided certificates if available, otherwise auto-generate
3389- let tls = if config. server . tls
3402+ let tls = if let ( Some ( cert) , Some ( key) ) = ( moq_cert, moq_key) {
3403+ info ! ( cert_path = %cert, key_path = %key, "Using MoQ-specific TLS certificates for WebTransport" ) ;
3404+ let mut tls = ServerTlsConfig :: default ( ) ;
3405+ tls. cert = vec ! [ std:: path:: PathBuf :: from( cert) ] ;
3406+ tls. key = vec ! [ std:: path:: PathBuf :: from( key) ] ;
3407+ tls
3408+ } else if config. server . tls
33903409 && !config. server . cert_path . is_empty ( )
33913410 && !config. server . key_path . is_empty ( )
33923411 {
33933412 info ! (
33943413 cert_path = %config. server. cert_path,
33953414 key_path = %config. server. key_path,
3396- "Using provided TLS certificates for MoQ WebTransport"
3415+ "Using server TLS certificates for MoQ WebTransport"
33973416 ) ;
33983417 let mut tls = ServerTlsConfig :: default ( ) ;
33993418 tls. cert = vec ! [ std:: path:: PathBuf :: from( & config. server. cert_path) ] ;
@@ -3410,9 +3429,26 @@ fn start_moq_webtransport_acceptor(
34103429 moq_config. bind = Some ( addr) ;
34113430 moq_config. tls = tls;
34123431
3432+ let moq_public_paths: Arc < [ String ] > = config
3433+ . auth
3434+ . moq_public_paths
3435+ . iter ( )
3436+ . filter ( |p| {
3437+ if p. is_empty ( ) {
3438+ warn ! ( "Ignoring empty string in moq_public_paths (would bypass all MoQ auth)" ) ;
3439+ false
3440+ } else {
3441+ true
3442+ }
3443+ } )
3444+ . cloned ( )
3445+ . collect :: < Vec < _ > > ( )
3446+ . into ( ) ;
3447+
34133448 info ! (
34143449 address = %addr,
3415- "Starting MoQ WebTransport acceptor on UDP (same port as HTTP server)"
3450+ moq_public_paths = ?moq_public_paths,
3451+ "Starting MoQ WebTransport acceptor on UDP"
34163452 ) ;
34173453
34183454 tokio:: spawn ( async move {
@@ -3430,14 +3466,15 @@ fn start_moq_webtransport_acceptor(
34303466 for ( i, fp) in fingerprints. iter ( ) . enumerate ( ) {
34313467 info ! ( "🔐 MoQ WebTransport certificate fingerprint #{}: {}" , i + 1 , fp) ;
34323468 }
3433- info ! ( "💡 Access fingerprints at: http://{}/ api/v1/moq/fingerprints" , addr ) ;
3469+ info ! ( "💡 Access fingerprints at: / api/v1/moq/fingerprints (served by the HTTP server)" ) ;
34343470
34353471 info ! ( "MoQ WebTransport server listening for connections" ) ;
34363472
34373473 // Accept connections in a loop
34383474 while let Some ( request) = server. accept ( ) . await {
34393475 let gateway = Arc :: clone ( & gateway) ;
34403476 let auth_state = Arc :: clone ( & auth_state) ;
3477+ let moq_public_paths = Arc :: clone ( & moq_public_paths) ;
34413478
34423479 tokio:: spawn ( async move {
34433480 // Extract URL data before consuming the request.
@@ -3458,8 +3495,12 @@ fn start_moq_webtransport_acceptor(
34583495 // SECURITY: Never log the full URL (may contain jwt)
34593496 debug ! ( path = %path, "Received MoQ connection request" ) ;
34603497
3461- // Validate MoQ auth if enabled
3462- let moq_auth = if auth_state. is_enabled ( ) {
3498+ // Validate MoQ auth if enabled (skipped for paths matching moq_public_paths).
3499+ // Segment-based: "/moq" matches "/moq" and "/moq/foo" but NOT "/moq2".
3500+ let is_public = moq_public_paths. iter ( ) . any ( |prefix| {
3501+ path == prefix. as_str ( ) || path. starts_with ( & format ! ( "{prefix}/" ) )
3502+ } ) ;
3503+ let moq_auth = if auth_state. is_enabled ( ) && !is_public {
34633504 match validate_moq_auth ( & auth_state, & path, jwt_param) . await {
34643505 Ok ( ctx) => Some ( ctx) ,
34653506 Err ( status) => {
0 commit comments