mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-23 17:28:53 +02:00
fix proxy rules behavior and implemented a few more rules and commands, dependencies upgrade
This commit is contained in:
117
internal/route/rules/cache.go
Normal file
117
internal/route/rules/cache.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package rules
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Cache is a map of cached values for a request.
|
||||
// It prevents the same value from being parsed multiple times.
|
||||
type (
|
||||
Cache map[string]any
|
||||
UpdateFunc[T any] func(T) T
|
||||
)
|
||||
|
||||
const (
|
||||
CacheKeyQueries = "queries"
|
||||
CacheKeyCookies = "cookies"
|
||||
CacheKeyRemoteIP = "remote_ip"
|
||||
CacheKeyBasicAuth = "basic_auth"
|
||||
)
|
||||
|
||||
var cacheKeys = []string{
|
||||
CacheKeyQueries,
|
||||
CacheKeyCookies,
|
||||
CacheKeyRemoteIP,
|
||||
CacheKeyBasicAuth,
|
||||
}
|
||||
|
||||
var cachePool = &sync.Pool{
|
||||
New: func() any {
|
||||
return make(Cache)
|
||||
},
|
||||
}
|
||||
|
||||
// NewCache returns a new Cached.
|
||||
func NewCache() Cache {
|
||||
return cachePool.Get().(Cache)
|
||||
}
|
||||
|
||||
// Release clear the contents of the Cached and returns it to the pool.
|
||||
func (c Cache) Release() {
|
||||
for _, k := range cacheKeys {
|
||||
delete(c, k)
|
||||
}
|
||||
cachePool.Put(c)
|
||||
}
|
||||
|
||||
// GetQueries returns the queries.
|
||||
// If r does not have queries, an empty map is returned.
|
||||
func (c Cache) GetQueries(r *http.Request) url.Values {
|
||||
v, ok := c[CacheKeyQueries]
|
||||
if !ok {
|
||||
v = r.URL.Query()
|
||||
c[CacheKeyQueries] = v
|
||||
}
|
||||
return v.(url.Values)
|
||||
}
|
||||
|
||||
func (c Cache) UpdateQueries(r *http.Request, update func(url.Values)) {
|
||||
queries := c.GetQueries(r)
|
||||
update(queries)
|
||||
r.URL.RawQuery = queries.Encode()
|
||||
}
|
||||
|
||||
// GetCookies returns the cookies.
|
||||
// If r does not have cookies, an empty slice is returned.
|
||||
func (c Cache) GetCookies(r *http.Request) []*http.Cookie {
|
||||
v, ok := c[CacheKeyCookies]
|
||||
if !ok {
|
||||
v = r.Cookies()
|
||||
c[CacheKeyCookies] = v
|
||||
}
|
||||
return v.([]*http.Cookie)
|
||||
}
|
||||
|
||||
func (c Cache) UpdateCookies(r *http.Request, update UpdateFunc[[]*http.Cookie]) {
|
||||
cookies := update(c.GetCookies(r))
|
||||
c[CacheKeyCookies] = cookies
|
||||
r.Header.Del("Cookie")
|
||||
for _, cookie := range cookies {
|
||||
r.AddCookie(cookie)
|
||||
}
|
||||
}
|
||||
|
||||
// GetRemoteIP returns the remote ip address.
|
||||
// If r.RemoteAddr is not a valid ip address, nil is returned.
|
||||
func (c Cache) GetRemoteIP(r *http.Request) net.IP {
|
||||
v, ok := c[CacheKeyRemoteIP]
|
||||
if !ok {
|
||||
host, _, err := net.SplitHostPort(r.RemoteAddr)
|
||||
if err != nil {
|
||||
host = r.RemoteAddr
|
||||
}
|
||||
v = net.ParseIP(host)
|
||||
c[CacheKeyRemoteIP] = v
|
||||
}
|
||||
return v.(net.IP)
|
||||
}
|
||||
|
||||
// GetBasicAuth returns *Credentials the basic auth username and password.
|
||||
// If r does not have basic auth, nil is returned.
|
||||
func (c Cache) GetBasicAuth(r *http.Request) *Credentials {
|
||||
v, ok := c[CacheKeyBasicAuth]
|
||||
if !ok {
|
||||
u, p, ok := r.BasicAuth()
|
||||
if ok {
|
||||
v = &Credentials{u, []byte(p)}
|
||||
c[CacheKeyBasicAuth] = v
|
||||
} else {
|
||||
c[CacheKeyBasicAuth] = nil
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return v.(*Credentials)
|
||||
}
|
||||
Reference in New Issue
Block a user