mirror of
https://github.com/yusing/godoxy.git
synced 2026-01-16 15:16:48 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d712b91ff | ||
|
|
4189ffa1db | ||
|
|
e906b358fa | ||
|
|
f179de9231 |
@@ -59,12 +59,12 @@ func ParseLabels(labels map[string]string, aliases ...string) (LabelMap, gperr.E
|
||||
|
||||
func ExpandWildcard(labels map[string]string, aliases ...string) {
|
||||
// collect all explicit aliases first
|
||||
aliasSet := make(map[string]struct{}, len(labels))
|
||||
aliasSet := make(map[string]int, len(labels))
|
||||
// wildcardLabels holds mapping suffix -> value derived from wildcard label definitions
|
||||
wildcardLabels := make(map[string]string)
|
||||
|
||||
for _, alias := range aliases {
|
||||
aliasSet[alias] = struct{}{}
|
||||
for i, alias := range aliases {
|
||||
aliasSet[alias] = i
|
||||
}
|
||||
|
||||
// iterate over a copy of the keys to safely mutate the map while ranging
|
||||
@@ -89,7 +89,9 @@ func ExpandWildcard(labels map[string]string, aliases ...string) {
|
||||
continue
|
||||
}
|
||||
// explicit alias label – remember the alias
|
||||
aliasSet[alias] = struct{}{}
|
||||
if _, ok := aliasSet[alias]; !ok {
|
||||
aliasSet[alias] = len(aliasSet)
|
||||
}
|
||||
}
|
||||
|
||||
if len(aliasSet) == 0 || len(wildcardLabels) == 0 {
|
||||
@@ -98,7 +100,11 @@ func ExpandWildcard(labels map[string]string, aliases ...string) {
|
||||
|
||||
// expand collected wildcard labels for every alias
|
||||
for suffix, v := range wildcardLabels {
|
||||
for alias := range aliasSet {
|
||||
for alias, i := range aliasSet {
|
||||
// for FQDN aliases, use numeric index instead of the alias name
|
||||
if strings.Contains(alias, ".") {
|
||||
alias = fmt.Sprintf("#%d", i+1)
|
||||
}
|
||||
key := fmt.Sprintf("%s.%s.%s", NSProxy, alias, suffix)
|
||||
if suffix == "" { // this should not happen (root wildcard handled earlier) but keep safe
|
||||
key = fmt.Sprintf("%s.%s", NSProxy, alias)
|
||||
|
||||
@@ -28,6 +28,20 @@ func TestExpandWildcard(t *testing.T) {
|
||||
}, labels)
|
||||
}
|
||||
|
||||
func TestExpandWildcardWithFQDNAliases(t *testing.T) {
|
||||
labels := map[string]string{
|
||||
"proxy.c.host": "localhost",
|
||||
"proxy.*.port": "5555",
|
||||
}
|
||||
docker.ExpandWildcard(labels, "a.example.com", "b.example.com")
|
||||
require.Equal(t, map[string]string{
|
||||
"proxy.#1.port": "5555",
|
||||
"proxy.#2.port": "5555",
|
||||
"proxy.c.host": "localhost",
|
||||
"proxy.c.port": "5555",
|
||||
}, labels)
|
||||
}
|
||||
|
||||
func TestExpandWildcardYAML(t *testing.T) {
|
||||
yaml := `
|
||||
host: localhost
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/yusing/go-proxy/internal/logging/accesslog"
|
||||
gphttp "github.com/yusing/go-proxy/internal/net/gphttp"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp/middleware"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp/middleware/errorpage"
|
||||
"github.com/yusing/go-proxy/internal/route/routes"
|
||||
@@ -69,19 +68,17 @@ func (ep *Entrypoint) SetAccessLogger(parent task.Parent, cfg *accesslog.Request
|
||||
}
|
||||
|
||||
func (ep *Entrypoint) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if ep.accessLogger != nil {
|
||||
w = accesslog.NewResponseRecorder(w)
|
||||
defer ep.accessLogger.Log(r, w.(*accesslog.ResponseRecorder).Response())
|
||||
}
|
||||
mux, err := ep.findRouteFunc(r.Host)
|
||||
if err == nil {
|
||||
if ep.accessLogger != nil {
|
||||
w = gphttp.NewModifyResponseWriter(w, r, func(resp *http.Response) error {
|
||||
ep.accessLogger.Log(r, resp)
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if ep.middleware != nil {
|
||||
ep.middleware.ServeHTTP(mux.ServeHTTP, w, routes.WithRouteContext(r, mux))
|
||||
return
|
||||
} else {
|
||||
mux.ServeHTTP(w, r)
|
||||
}
|
||||
mux.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
// Why use StatusNotFound instead of StatusBadRequest or StatusBadGateway?
|
||||
|
||||
67
internal/logging/accesslog/response_recorder.go
Normal file
67
internal/logging/accesslog/response_recorder.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package accesslog
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type ResponseRecorder struct {
|
||||
w http.ResponseWriter
|
||||
|
||||
resp http.Response
|
||||
}
|
||||
|
||||
func NewResponseRecorder(w http.ResponseWriter) *ResponseRecorder {
|
||||
return &ResponseRecorder{
|
||||
w: w,
|
||||
resp: http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Header: w.Header(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (w *ResponseRecorder) Unwrap() http.ResponseWriter {
|
||||
return w.w
|
||||
}
|
||||
|
||||
func (w *ResponseRecorder) Response() *http.Response {
|
||||
return &w.resp
|
||||
}
|
||||
|
||||
func (w *ResponseRecorder) Header() http.Header {
|
||||
return w.w.Header()
|
||||
}
|
||||
|
||||
func (w *ResponseRecorder) Write(b []byte) (int, error) {
|
||||
n, err := w.w.Write(b)
|
||||
w.resp.ContentLength += int64(n)
|
||||
return n, err
|
||||
}
|
||||
|
||||
func (w *ResponseRecorder) WriteHeader(code int) {
|
||||
w.w.WriteHeader(code)
|
||||
|
||||
if code >= http.StatusContinue && code < http.StatusOK {
|
||||
return
|
||||
}
|
||||
w.resp.StatusCode = code
|
||||
}
|
||||
|
||||
// Hijack hijacks the connection.
|
||||
func (w *ResponseRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
if h, ok := w.w.(http.Hijacker); ok {
|
||||
return h.Hijack()
|
||||
}
|
||||
|
||||
return nil, nil, fmt.Errorf("not a hijacker: %T", w.w)
|
||||
}
|
||||
|
||||
// Flush sends any buffered data to the client.
|
||||
func (w *ResponseRecorder) Flush() {
|
||||
if flusher, ok := w.w.(http.Flusher); ok {
|
||||
flusher.Flush()
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,13 @@ type (
|
||||
// if no rule matches and default rule is not set,
|
||||
// the request is passed to the upstream.
|
||||
func (rules Rules) BuildHandler(caller string, up http.Handler) http.HandlerFunc {
|
||||
var defaultRule *Rule
|
||||
defaultRule := &Rule{
|
||||
Name: "default",
|
||||
Do: Command{
|
||||
raw: "pass",
|
||||
exec: BypassCommand{},
|
||||
},
|
||||
}
|
||||
|
||||
nonDefaultRules := make(Rules, 0, len(rules))
|
||||
for i, rule := range rules {
|
||||
@@ -79,6 +85,10 @@ func (rules Rules) BuildHandler(caller string, up http.Handler) http.HandlerFunc
|
||||
}
|
||||
}
|
||||
|
||||
if len(nonDefaultRules) == 0 {
|
||||
nonDefaultRules = rules
|
||||
}
|
||||
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
cache := NewCache()
|
||||
defer cache.Release()
|
||||
|
||||
@@ -47,7 +47,6 @@ echo "Using ${DOWNLOAD_TOOL} for downloads"
|
||||
REPO="yusing/godoxy"
|
||||
BRANCH=${BRANCH:-"main"}
|
||||
REPO_URL="https://github.com/$REPO"
|
||||
WIKI_URL="${REPO_URL}/wiki"
|
||||
BASE_URL="${REPO_URL}/raw/${BRANCH}"
|
||||
|
||||
# Config paths
|
||||
@@ -248,7 +247,7 @@ if [ "$ENABLE_AUTOCERT" == "y" ]; then
|
||||
read -p "Enter duckdns token: " token
|
||||
options=("token: \"$token\"")
|
||||
else
|
||||
echo "Please check Wiki for other DNS providers: ${WIKI_URL}/Supported-DNS%E2%80%9001-Providers"
|
||||
echo "Please check Wiki for other DNS providers: https://docs.godoxy.dev/DNS-01-Providers"
|
||||
echo "Skipping autocert setup"
|
||||
skip=true
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user