Files
phishingclub/backend/vendor/github.com/enetx/surf/middleware_request.go
T

144 lines
4.5 KiB
Go

package surf
import (
"errors"
"fmt"
"net/textproto"
"github.com/enetx/g"
"github.com/enetx/g/rand"
"github.com/enetx/http/httptrace"
"github.com/enetx/surf/header"
)
// defaultUserAgentMW sets the default User-Agent header for surf requests.
// Only sets the header if no User-Agent is already present in the request.
// Uses the predefined _userAgent constant as the default value.
func defaultUserAgentMW(req *Request) error {
if headers := req.GetRequest().Header; headers.Get(header.USER_AGENT) == "" {
// Set the default user-agent header.
headers.Set(header.USER_AGENT, _userAgent)
}
return nil
}
// userAgentMW configures a custom User-Agent header for HTTP requests.
// Supports various input types for flexibility:
// - string or g.String: Uses the value directly
// - []string or g.Slice[string]: Randomly selects from the slice (useful for rotation)
// - g.Slice[g.String]: Randomly selects from g.String slice
// Returns an error for unsupported types or empty slices.
func userAgentMW(req *Request, userAgent any) error {
var pool []g.String
switch v := userAgent.(type) {
case string:
pool = []g.String{g.String(v)}
case g.String:
pool = []g.String{v}
case []string:
pool = g.TransformSlice(v, g.NewString)
case g.Slice[string]:
pool = g.TransformSlice(v, g.NewString)
case g.Slice[g.String]:
pool = v
default:
return &ErrUserAgentType{fmt.Sprintf("'%T' %v", v, v)}
}
ua := rand.Choice(pool)
if ua.IsNone() {
return &ErrUserAgentType{"cannot select a random user agent from an empty slice"}
}
req.GetRequest().Header.Set(header.USER_AGENT, ua.Some().Std())
return nil
}
// got101ResponseMW configures request tracing to handle HTTP 101 Switching Protocols responses.
// Sets up client trace callbacks to detect and handle protocol switching responses.
// Returns an error specifically for HTTP 101 responses to allow special handling of protocol upgrades.
// Other 1xx responses are ignored and allowed to proceed normally.
func got101ResponseMW(req *Request) error {
req.WithContext(httptrace.WithClientTrace(req.GetRequest().Context(),
&httptrace.ClientTrace{
Got1xxResponse: func(code int, _ textproto.MIMEHeader) error {
if code != 101 {
return nil
}
return &Err101ResponseCode{
fmt.Sprintf(`%s "%s" error:`, req.request.Method, req.request.URL.String()),
}
},
},
))
return nil
}
// remoteAddrMW configures request tracing to capture the remote server address.
// Sets up client trace callbacks to extract and store the remote address
// of the server connection for later access. This information can be useful
// for logging, debugging, or connection analysis purposes.
func remoteAddrMW(req *Request) error {
req.WithContext(httptrace.WithClientTrace(req.GetRequest().Context(),
&httptrace.ClientTrace{
GotConn: func(info httptrace.GotConnInfo) { req.remoteAddr = info.Conn.RemoteAddr() },
},
))
return nil
}
// bearerAuthMW configures Bearer token authentication for HTTP requests.
// Adds an Authorization header with the Bearer token format if a token is provided.
// Only sets the header if the token is not empty, allowing conditional authentication.
func bearerAuthMW(req *Request, token g.String) error {
if !token.IsEmpty() {
req.AddHeaders(g.Map[g.String, g.String]{header.AUTHORIZATION: "Bearer " + token})
}
return nil
}
// basicAuthMW configures HTTP Basic Authentication for requests.
// Expects authentication string in "username:password" format.
// Skips setting auth if Authorization header already exists.
// Returns an error if username or password fields are empty.
func basicAuthMW(req *Request, authentication g.String) error {
if req.GetRequest().Header.Get(header.AUTHORIZATION) != "" {
return nil
}
var username, password g.String
if idx := authentication.Index(":"); idx != -1 {
username = authentication[:idx]
password = authentication[idx+1:]
}
if username == "" || password == "" {
return errors.New("basic authorization fields cannot be empty")
}
req.GetRequest().SetBasicAuth(username.Std(), password.Std())
return nil
}
// contentTypeMW configures the Content-Type header for HTTP requests.
// Sets the MIME type of the request body content to inform the server
// how to interpret the request data. Returns an error if contentType is empty.
func contentTypeMW(req *Request, contentType g.String) error {
if contentType.IsEmpty() {
return fmt.Errorf("Content-Type is empty")
}
req.SetHeaders(g.Map[g.String, g.String]{header.CONTENT_TYPE: contentType})
return nil
}