Explorar el Código

control: reject unexpected bodies on control POSTs

tags/v0.9.0
Jan Svabenik hace 1 mes
padre
commit
dd7ae483c4
Se han modificado 2 ficheros con 73 adiciones y 0 borrados
  1. +30
    -0
      internal/control/control.go
  2. +43
    -0
      internal/control/control_test.go

+ 30
- 0
internal/control/control.go Ver fichero

@@ -54,6 +54,7 @@ type Server struct {
const (
maxConfigBodyBytes = 64 << 10 // 64 KiB
configContentTypeHeader = "application/json"
noBodyErrMsg = "request must not include a body"
)

func isJSONContentType(r *http.Request) bool {
@@ -89,6 +90,26 @@ func NewServer(cfg config.Config) *Server {
return &Server{cfg: cfg}
}

func hasRequestBody(r *http.Request) bool {
if r.ContentLength > 0 {
return true
}
for _, te := range r.TransferEncoding {
if strings.EqualFold(te, "chunked") {
return true
}
}
return false
}

func rejectBody(w http.ResponseWriter, r *http.Request) bool {
if !hasRequestBody(r) {
return true
}
http.Error(w, noBodyErrMsg, http.StatusBadRequest)
return false
}

func (s *Server) SetTXController(tx TXController) {
s.mu.Lock()
s.tx = tx
@@ -200,6 +221,9 @@ func (s *Server) handleRuntimeFaultReset(w http.ResponseWriter, r *http.Request)
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !rejectBody(w, r) {
return
}
s.mu.RLock()
tx := s.tx
s.mu.RUnlock()
@@ -263,6 +287,9 @@ func (s *Server) handleTXStart(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !rejectBody(w, r) {
return
}
s.mu.RLock()
tx := s.tx
s.mu.RUnlock()
@@ -283,6 +310,9 @@ func (s *Server) handleTXStop(w http.ResponseWriter, r *http.Request) {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
if !rejectBody(w, r) {
return
}
s.mu.RLock()
tx := s.tx
s.mu.RUnlock()


+ 43
- 0
internal/control/control_test.go Ver fichero

@@ -6,6 +6,7 @@ import (
"errors"
"net/http"
"net/http/httptest"
"strings"
"testing"

"github.com/jan/fm-rds-tx/internal/audio"
@@ -288,6 +289,20 @@ func TestRuntimeFaultResetSuccess(t *testing.T) {
}
}

func TestRuntimeFaultResetRejectsBody(t *testing.T) {
srv := NewServer(cfgpkg.Default())
srv.SetTXController(&fakeTXController{})
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/runtime/fault/reset", bytes.NewReader([]byte("nope")))
srv.Handler().ServeHTTP(rec, req)
if rec.Code != http.StatusBadRequest {
t.Fatalf("expected 400 when body present, got %d", rec.Code)
}
if !strings.Contains(rec.Body.String(), "request must not include a body") {
t.Fatalf("unexpected response body: %q", rec.Body.String())
}
}

func TestAudioStreamRequiresSource(t *testing.T) {
srv := NewServer(cfgpkg.Default())
rec := httptest.NewRecorder()
@@ -349,6 +364,34 @@ func TestTXStartWithoutController(t *testing.T) {
}
}

func TestTXStartRejectsBody(t *testing.T) {
srv := NewServer(cfgpkg.Default())
srv.SetTXController(&fakeTXController{})
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/tx/start", bytes.NewReader([]byte("body")))
srv.Handler().ServeHTTP(rec, req)
if rec.Code != http.StatusBadRequest {
t.Fatalf("expected 400 when body present, got %d", rec.Code)
}
if !strings.Contains(rec.Body.String(), "request must not include a body") {
t.Fatalf("unexpected response body: %q", rec.Body.String())
}
}

func TestTXStopRejectsBody(t *testing.T) {
srv := NewServer(cfgpkg.Default())
srv.SetTXController(&fakeTXController{})
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodPost, "/tx/stop", bytes.NewReader([]byte("body")))
srv.Handler().ServeHTTP(rec, req)
if rec.Code != http.StatusBadRequest {
t.Fatalf("expected 400 when body present, got %d", rec.Code)
}
if !strings.Contains(rec.Body.String(), "request must not include a body") {
t.Fatalf("unexpected response body: %q", rec.Body.String())
}
}

func TestConfigPatchUpdatesSnapshot(t *testing.T) {
srv := NewServer(cfgpkg.Default())
srv.SetTXController(&fakeTXController{})


Cargando…
Cancelar
Guardar