|
|
|
@@ -3,6 +3,7 @@ package control |
|
|
|
import ( |
|
|
|
_ "embed" |
|
|
|
"encoding/json" |
|
|
|
"errors" |
|
|
|
"io" |
|
|
|
"mime" |
|
|
|
"net/http" |
|
|
|
@@ -56,6 +57,7 @@ const ( |
|
|
|
configContentTypeHeader = "application/json" |
|
|
|
noBodyErrMsg = "request must not include a body" |
|
|
|
audioStreamContentTypeError = "Content-Type must be application/octet-stream or audio/L16" |
|
|
|
audioStreamBodyLimitDefault = 512 << 20 // 512 MiB |
|
|
|
) |
|
|
|
|
|
|
|
var audioStreamAllowedMediaTypes = []string{ |
|
|
|
@@ -63,6 +65,8 @@ var audioStreamAllowedMediaTypes = []string{ |
|
|
|
"audio/l16", |
|
|
|
} |
|
|
|
|
|
|
|
var audioStreamBodyLimit = int64(audioStreamBodyLimitDefault) // bytes allowed per /audio/stream request; tests may override. |
|
|
|
|
|
|
|
func isJSONContentType(r *http.Request) bool { |
|
|
|
ct := strings.TrimSpace(r.Header.Get("Content-Type")) |
|
|
|
if ct == "" { |
|
|
|
@@ -284,6 +288,8 @@ func (s *Server) handleAudioStream(w http.ResponseWriter, r *http.Request) { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
r.Body = http.MaxBytesReader(w, r.Body, audioStreamBodyLimit) |
|
|
|
|
|
|
|
// Read body in chunks and push to ring buffer |
|
|
|
buf := make([]byte, 32768) |
|
|
|
totalFrames := 0 |
|
|
|
@@ -296,6 +302,11 @@ func (s *Server) handleAudioStream(w http.ResponseWriter, r *http.Request) { |
|
|
|
if err == io.EOF { |
|
|
|
break |
|
|
|
} |
|
|
|
var maxErr *http.MaxBytesError |
|
|
|
if errors.As(err, &maxErr) { |
|
|
|
http.Error(w, maxErr.Error(), http.StatusRequestEntityTooLarge) |
|
|
|
return |
|
|
|
} |
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError) |
|
|
|
return |
|
|
|
} |
|
|
|
|