From 61eab4db0550b6c02988cdb2a3714049396cbf31 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 21 Sep 2022 08:08:11 -0400 Subject: [PATCH 1/2] chore: Add linter rule to prevent breaking of sse --- scripts/rules.go | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/scripts/rules.go b/scripts/rules.go index c34ae6ed3bff3..1c0385a655eaa 100644 --- a/scripts/rules.go +++ b/scripts/rules.go @@ -8,16 +8,20 @@ // - https://pkg.go.dev/github.com/quasilyte/go-ruleguard/dsl // // You run one of the following commands to execute your go rules only: -// golangci-lint run -// golangci-lint run --disable-all --enable=gocritic +// +// golangci-lint run +// golangci-lint run --disable-all --enable=gocritic +// // Note: don't forget to run `golangci-lint cache clean`! package gorules import ( "github.com/quasilyte/go-ruleguard/dsl" + "github.com/quasilyte/go-ruleguard/dsl/types" ) // Use xerrors everywhere! It provides additional stacktrace info! +// //nolint:unused,deadcode,varnamelen func xerrors(m dsl.Matcher) { m.Import("errors") @@ -35,6 +39,7 @@ func xerrors(m dsl.Matcher) { } // databaseImport enforces not importing any database types into /codersdk. +// //nolint:unused,deadcode,varnamelen func databaseImport(m dsl.Matcher) { m.Import("github.com/coder/coder/coderd/database") @@ -46,6 +51,7 @@ func databaseImport(m dsl.Matcher) { // doNotCallTFailNowInsideGoroutine enforces not calling t.FailNow or // functions that may themselves call t.FailNow in goroutines outside // the main test goroutine. See testing.go:834 for why. +// //nolint:unused,deadcode,varnamelen func doNotCallTFailNowInsideGoroutine(m dsl.Matcher) { m.Import("testing") @@ -84,6 +90,7 @@ func doNotCallTFailNowInsideGoroutine(m dsl.Matcher) { // useStandardTimeoutsAndDelaysInTests ensures all tests use common // constants for timeouts and delays in usual scenarios, this allows us // to tweak them based on platform (important to avoid CI flakes). +// //nolint:unused,deadcode,varnamelen func useStandardTimeoutsAndDelaysInTests(m dsl.Matcher) { m.Import("github.com/stretchr/testify/require") @@ -232,3 +239,30 @@ func ProperRBACReturn(m dsl.Matcher) { } `).Report("Must write to 'ResponseWriter' before returning'") } + +// FullResponseWriter ensures that any overridden response writer has full +// functionality. Mainly is hijackable and flushable. +func FullResponseWriter(m dsl.Matcher) { + m.Match(` + type $w struct { + $*_ + http.ResponseWriter + $*_ + } + `). + At(m["w"]). + Where(m["w"].Filter(notImplementsFullResponseWriter)). + Report("ResponseWriter \"$w\" must implement http.Flusher and http.Hijacker") +} + +// notImplementsFullResponseWriter returns false if the type does not implement +// http.Flusher, http.Hijacker, and http.ResponseWriter. +func notImplementsFullResponseWriter(ctx *dsl.VarFilterContext) bool { + flusher := ctx.GetInterface(`net/http.Flusher`) + hijacker := ctx.GetInterface(`net/http.Hijacker`) + writer := ctx.GetInterface(`net/http.ResponseWriter`) + p := types.NewPointer(ctx.Type) + return !(types.Implements(types.NewPointer(ctx.Type), writer) || types.Implements(ctx.Type, writer)) || + !(types.Implements(types.NewPointer(ctx.Type), flusher) || types.Implements(ctx.Type, flusher)) || + !(types.Implements(p, hijacker) || types.Implements(ctx.Type, hijacker)) +} From e6025e30a067ae36108c42f8357146a154ed6c01 Mon Sep 17 00:00:00 2001 From: Steven Masley Date: Wed, 21 Sep 2022 08:12:22 -0400 Subject: [PATCH 2/2] Simplify slightly, reuse pointer --- scripts/rules.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/rules.go b/scripts/rules.go index 1c0385a655eaa..38abb44e8107a 100644 --- a/scripts/rules.go +++ b/scripts/rules.go @@ -262,7 +262,7 @@ func notImplementsFullResponseWriter(ctx *dsl.VarFilterContext) bool { hijacker := ctx.GetInterface(`net/http.Hijacker`) writer := ctx.GetInterface(`net/http.ResponseWriter`) p := types.NewPointer(ctx.Type) - return !(types.Implements(types.NewPointer(ctx.Type), writer) || types.Implements(ctx.Type, writer)) || - !(types.Implements(types.NewPointer(ctx.Type), flusher) || types.Implements(ctx.Type, flusher)) || + return !(types.Implements(p, writer) || types.Implements(ctx.Type, writer)) || + !(types.Implements(p, flusher) || types.Implements(ctx.Type, flusher)) || !(types.Implements(p, hijacker) || types.Implements(ctx.Type, hijacker)) } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy