diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 46e2bbc2..eff92a10 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -43,7 +43,7 @@ jobs: - name: Staticcheck run: | - go install honnef.co/go/tools/cmd/staticcheck@1285a6a5ec1e0ebb658f49e82b6c566a878cc3cb # v0.8.1 + go install honnef.co/go/tools/cmd/staticcheck@54455593555daf6bfcf3c480faaada7de3145357 # v0.8.2 staticcheck ./... - name: golangci-lint @@ -54,7 +54,7 @@ jobs: - name: Run Gosec Security Scanner run: | - go install github.com/securego/gosec/v2/cmd/gosec@deb54465fea23d19a77f037e11e6589021f8501d # v2.29.0 + go install github.com/securego/gosec/v2/cmd/gosec@5eb1d104ef85ff2c905c877eb600e8c1dee33a22 # v2.30.0 gosec ./... - name: Test diff --git a/doc/deployment.md b/doc/deployment.md index 10863a28..6c403f08 100644 --- a/doc/deployment.md +++ b/doc/deployment.md @@ -20,6 +20,7 @@ Oversized inbound WebSocket messages close the connection and log the read-limit error. Other transport errors ordinarily end the Request without a log report; `Debug` retains their underlying details for logging. Configure `Debug` before serving and regenerate head markup with `GenerateHeadHTML` when changing it. +Noscript probes cancel Requests without logging or incrementing `ErrorCount`. ## Authorization diff --git a/errors.go b/errors.go index 6da0f1fe..b0bc0020 100644 --- a/errors.go +++ b/errors.go @@ -93,7 +93,7 @@ var ErrReplaceNotBroadcastable = errors.New("what.Replace cannot be broadcast") // elements, or [Element.Remove] for the per-element child form. var ErrRemoveNotBroadcastable = errors.New("what.Remove cannot be broadcast") -// ErrJavascriptDisabled is returned when the noscript probe indicates JavaScript is disabled. +// ErrJavascriptDisabled identifies a Request canceled by the noscript probe. var ErrJavascriptDisabled = errors.New("javascript is disabled") // ErrWebsocketOriginMissing is returned when a WebSocket request has no Origin header. diff --git a/request.go b/request.go index 4d54dc64..9d838c91 100644 --- a/request.go +++ b/request.go @@ -1259,6 +1259,9 @@ func (rq *Request) runWebSocket(ws *websocket.Conn, idleInterval, wsTimeout time // and are not reported through [Jaws.Logger]. When [Jaws.Debug] is true, their // underlying error is retained in the Request cancellation cause, which is // passed to [Jaws.Log] instead. +// +// A noscript probe returns 204 and cancels the Request with +// [ErrJavascriptDisabled] without logging or increasing [Jaws.ErrorCount]. func (rq *Request) ServeHTTP(w http.ResponseWriter, r *http.Request) { if rq.startServe() { defer rq.stopServe() @@ -1266,7 +1269,10 @@ func (rq *Request) ServeHTTP(w http.ResponseWriter, r *http.Request) { wsTimeout := rq.Jaws.getWebSocketTimeout() if strings.HasSuffix(r.URL.Path, "/noscript") { w.WriteHeader(http.StatusNoContent) - rq.cancel(ErrJavascriptDisabled) + // The probe is expected; preserve its cause without reporting it. + rq.mu.Lock() + _ = rq.cancelLocked(ErrJavascriptDisabled) + rq.mu.Unlock() return } var err error diff --git a/request_test.go b/request_test.go index bafce7a6..39d996c3 100644 --- a/request_test.go +++ b/request_test.go @@ -5790,16 +5790,16 @@ func TestRecycleQueueRaceDoesNotLeak(t *testing.T) { } } -// TestNoscriptDuringLiveRenderRecordsJavascriptDisabled guards against re-adding a -// render-timing gate that would 404 the