Files
phishingclub/backend/vendor/github.com/enetx/surf/middleware_request.go
T
Ronni Skansing 07c8adaf76 update vendor deps
Signed-off-by: Ronni Skansing <rskansing@gmail.com>
2025-11-06 23:31:08 +01:00

145 lines
4.5 KiB
Go

package surf
import (
"errors"
"fmt"
"math/rand"
"net/textproto"
"github.com/enetx/g"
"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 ua string
switch v := userAgent.(type) {
case string:
ua = v
case g.String:
ua = v.Std()
case []string:
if len(v) == 0 {
return &ErrUserAgentType{"cannot select a random user agent from an empty slice"}
}
ua = v[rand.Intn(len(v))]
case g.Slice[string]:
if v.Empty() {
return &ErrUserAgentType{"cannot select a random user agent from an empty slice"}
}
ua = v.Random()
case g.Slice[g.String]:
if v.Empty() {
return &ErrUserAgentType{"cannot select a random user agent from an empty slice"}
}
ua = v.Random().Std()
default:
return &ErrUserAgentType{fmt.Sprintf("'%T' %v", v, v)}
}
req.GetRequest().Header.Set(header.USER_AGENT, ua)
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.NotEmpty() {
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
authentication.Split(":").Collect().Unpack(&username, &password)
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.Empty() {
return fmt.Errorf("Content-Type is empty")
}
req.SetHeaders(g.Map[g.String, g.String]{header.CONTENT_TYPE: contentType})
return nil
}