{"record":{"id":"25c1910d70a7d781","repo":"AlexxIT/go2rtc","slug":"malformed-request-body","errorCode":null,"errorMessage":"malformed request body","messagePattern":"malformed request body","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"internal/onvif/onvif.go","lineNumber":70,"sourceCode":"\tlog.Debug().Msgf(\"[onvif] new uri=%s\", uri)\n\n\tif err = streams.Validate(uri); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn streams.GetProducer(uri)\n}\n\nfunc onvifDeviceService(w http.ResponseWriter, r *http.Request) {\n\tb, err := io.ReadAll(r.Body)\n\tif err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\toperation := onvif.GetRequestAction(b)\n\tif operation == \"\" {\n\t\thttp.Error(w, \"malformed request body\", http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tlog.Trace().Msgf(\"[onvif] server request %s %s:\\n%s\", r.Method, r.RequestURI, b)\n\n\tswitch operation {\n\tcase onvif.ServiceGetServiceCapabilities, // important for Hass\n\t\tonvif.DeviceGetNetworkInterfaces, // important for Hass\n\t\tonvif.DeviceGetSystemDateAndTime, // important for Hass\n\t\tonvif.DeviceSetSystemDateAndTime, // return just OK\n\t\tonvif.DeviceGetDiscoveryMode,\n\t\tonvif.DeviceGetDNS,\n\t\tonvif.DeviceGetHostname,\n\t\tonvif.DeviceGetNetworkDefaultGateway,\n\t\tonvif.DeviceGetNetworkProtocols,\n\t\tonvif.DeviceGetNTP,\n\t\tonvif.DeviceGetScopes,\n\t\tonvif.MediaGetVideoEncoderConfiguration,","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/AlexxIT/go2rtc/blob/c245815e75e2a5fd60b4290f12bfc04e55a984d3/internal/onvif/onvif.go#L52-L88","documentation":"The ONVIF device-service handler parses the SOAP body with onvif.GetRequestAction to identify which ONVIF operation the client wants. If the body yields an empty action, go2rtc cannot map the request to any known operation and returns 400 \"malformed request body\". The library expects a well-formed ONVIF SOAP envelope with a recognizable action element.","triggerScenarios":"POSTing to /onvif/ a body that is empty, not XML, lacks the SOAP action tag, or uses an encoding/namespaces the simple parser cannot read.","commonSituations":"Sending plain JSON or form data instead of SOAP; hitting the endpoint with a browser GET/health-check or curl without a body; using an ONVIF client that sends unusual namespaces; a reverse proxy stripping the body.","solutions":["Send a valid ONVIF SOAP envelope with the action element (e.g. an ONVIF Device/Media operation)","Verify with curl -d @request.xml that the POST body is non-empty XML","Enable go2rtc trace logging and compare the failing request with one from a known-good ONVIF client","Use a standard ONVIF client library instead of hand-crafted SOAP"],"exampleFix":"// before\ncurl -X POST http://server:1984/onvif/  # empty body\n// after\ncurl -X POST http://server:1984/onvif/ -H 'Content-Type: application/soap+xml' --data @get_profiles.xml","handlingStrategy":"validation","validationCode":"body, _ := io.ReadAll(respBody)\nif len(bytes.TrimSpace(body)) == 0 || !bytes.Contains(body, []byte(\"<\")) {\n    return errors.New(\"request body must be a non-empty SOAP XML envelope\")\n}","typeGuard":null,"tryCatchPattern":"resp, err := http.Post(url, \"application/soap+xml\", bytes.NewReader(soapBody))\nif err != nil { return err }\nif resp.StatusCode == http.StatusBadRequest {\n    b, _ := io.ReadAll(resp.Body)\n    if strings.Contains(string(b), \"malformed request body\") {\n        return fmt.Errorf(\"invalid SOAP envelope sent to ONVIF endpoint: %s\", b)\n    }\n}","preventionTips":["Always send Content-Type: application/soap+xml to /onvif/","Validate SOAP envelopes against a known-good ONVIF template","Never GET or POST empty bodies to the ONVIF endpoint","Compare with a captured request from a working ONVIF client"],"tags":["http","soap","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"c245815e75e2a5fd60b4290f12bfc04e55a984d3","analyzedAt":"2026-09-07T11:47:02.965Z","contentChangedAt":"2026-09-07T11:47:02.965Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}