Files
pmg/proxy/interceptor.go
T
Sahil BansalandGitHub 31e51b10dd refactor: move proxy block message rendering to presentation layer (#364)
* refactor: move proxy block message rendering to presentation layer

* refactor: introduce ui.ProxyPresenter with injected advisory source

* feat: friendly ecosystem labels in proxy block messages

* test: cover ecosystemLabel derivation

* fix: address review feedback on block context assertions and empty reference line
2026-07-10 17:42:26 +05:30

120 lines
3.3 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package proxy
import (
"net/http"
"net/url"
"time"
packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1"
)
// ResponseAction determines how the proxy should handle a request
type ResponseAction int
const (
// ActionAllow forwards the request unchanged
ActionAllow ResponseAction = iota
// ActionBlock blocks the request with an error response
ActionBlock
// ActionModifyRequest modifies the request before forwarding
ActionModifyRequest
// ActionModifyResponse modifies the response after receiving
ActionModifyResponse
)
// RequestContext provides request information to interceptors
// This is passed to ShouldIntercept and HandleRequest methods
type RequestContext struct {
URL *url.URL
Method string
Headers http.Header
// Body is not currently used by the interceptors, but it is here for future use
Body []byte
Hostname string
RequestID string
StartTime time.Time
// Interceptor can store custom data
Data map[string]interface{}
}
// BlockReason identifies why an interceptor blocked a request
type BlockReason int
const (
BlockReasonNone BlockReason = iota
BlockReasonMalware
BlockReasonUserDeclined
BlockReasonConfirmationFailed
BlockReasonDependencyCooldown
)
// BlockContext carries the structured facts of a block decision so a
// presentation layer can render the user-facing message. Interceptors
// populate it instead of composing message text themselves.
type BlockContext struct {
Ecosystem packagev1.Ecosystem
PackageName string
PackageVersion string
// For BlockReasonMalware and BlockReasonUserDeclined
MalwareSummary string
MalwareReferenceURL string
// For BlockReasonDependencyCooldown
CooldownDays int
CooldownDaysAgo int
CooldownDaysLeft int
}
// InterceptorResponse defines how the proxy should handle the request
type InterceptorResponse struct {
// Action to take
Action ResponseAction
// For Action = Block: why and what was blocked. The proxy renders the
// response body from these via ProxyConfig.BlockMessageRenderer.
BlockReason BlockReason
BlockContext *BlockContext
// BlockMessage overrides the rendered message when non-empty
BlockMessage string
BlockCode int
// For Action = ModifyRequest: modified headers/body
ModifiedHeaders http.Header
// ModifiedBody is not currently used by the interceptors, but it is here for future use
ModifiedBody []byte
// For Action = ModifyResponse: response modification function
ResponseModifier ResponseModifierFunc
}
// ResponseModifierFunc modifies HTTP response
// It receives the status code, headers, and body, and returns modified versions
type ResponseModifierFunc func(statusCode int, headers http.Header, body []byte) (int, http.Header, []byte, error)
// Interceptor processes HTTP/HTTPS requests and can modify or block them
type Interceptor interface {
// Name returns the interceptor name for logging
Name() string
// ShouldIntercept determines if this interceptor handles the given request
ShouldIntercept(ctx *RequestContext) bool
// HandleRequest processes the request and returns response action
// Called for each request matching ShouldIntercept
HandleRequest(ctx *RequestContext) (*InterceptorResponse, error)
}
// MITMDecider is optional; implement to control whether CONNECT requests are MITMd.
type MITMDecider interface {
ShouldMITM(ctx *RequestContext) bool
}