@@ -17,6 +17,7 @@ package gorules
1717
1818import (
1919 "github.com/quasilyte/go-ruleguard/dsl"
20+ "github.com/quasilyte/go-ruleguard/dsl/types"
2021)
2122
2223// Use xerrors everywhere! It provides additional stacktrace info!
@@ -238,3 +239,30 @@ func ProperRBACReturn(m dsl.Matcher) {
238239 }
239240 ` ).Report ("Must write to 'ResponseWriter' before returning'" )
240241}
242+
243+ // FullResponseWriter ensures that any overridden response writer has full
244+ // functionality. Mainly is hijackable and flushable.
245+ func FullResponseWriter (m dsl.Matcher ) {
246+ m .Match (`
247+ type $w struct {
248+ $*_
249+ http.ResponseWriter
250+ $*_
251+ }
252+ ` ).
253+ At (m ["w" ]).
254+ Where (m ["w" ].Filter (notImplementsFullResponseWriter )).
255+ Report ("ResponseWriter \" $w\" must implement http.Flusher and http.Hijacker" )
256+ }
257+
258+ // notImplementsFullResponseWriter returns false if the type does not implement
259+ // http.Flusher, http.Hijacker, and http.ResponseWriter.
260+ func notImplementsFullResponseWriter (ctx * dsl.VarFilterContext ) bool {
261+ flusher := ctx .GetInterface (`net/http.Flusher` )
262+ hijacker := ctx .GetInterface (`net/http.Hijacker` )
263+ writer := ctx .GetInterface (`net/http.ResponseWriter` )
264+ p := types .NewPointer (ctx .Type )
265+ return ! (types .Implements (p , writer ) || types .Implements (ctx .Type , writer )) ||
266+ ! (types .Implements (p , flusher ) || types .Implements (ctx .Type , flusher )) ||
267+ ! (types .Implements (p , hijacker ) || types .Implements (ctx .Type , hijacker ))
268+ }
0 commit comments