Rename some functions
This commit is contained in:
parent
5e8f9c7e5e
commit
8051f9a017
|
@ -1,6 +0,0 @@
|
|||
package routing
|
||||
|
||||
type ServeHeaderItem interface {
|
||||
HeaderKey() string
|
||||
HeaderValue() string
|
||||
}
|
|
@ -1,262 +0,0 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"code.mrmelon54.com/melon/summer-utils/tables/web"
|
||||
"code.mrmelon54.com/melon/summer-utils/utils"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/kjk/common/filerotate"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"sync"
|
||||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
var ErrAlreadyCompiling = errors.New("router: already compiling")
|
||||
var theIncrementor uint64
|
||||
|
||||
type TableRouter struct {
|
||||
router *mux.Router
|
||||
db *xorm.Engine
|
||||
proxy *httputil.ReverseProxy
|
||||
rLock *sync.RWMutex // lock for router
|
||||
cLock *sync.Mutex // lock for internalCompile
|
||||
accessLog *log.Logger
|
||||
fourEighteen func(rw http.ResponseWriter, req *http.Request)
|
||||
}
|
||||
|
||||
func New(db *xorm.Engine, proxy *httputil.ReverseProxy, accessLog *filerotate.File, fourEighteenError func(rw http.ResponseWriter, req *http.Request)) (*TableRouter, error) {
|
||||
r := &TableRouter{
|
||||
router: mux.NewRouter(),
|
||||
db: db,
|
||||
proxy: proxy,
|
||||
rLock: &sync.RWMutex{},
|
||||
cLock: &sync.Mutex{},
|
||||
accessLog: log.New(accessLog, "", log.LstdFlags),
|
||||
fourEighteen: fourEighteenError,
|
||||
}
|
||||
// run internalCompile inline to generate the initial router
|
||||
err := r.internalCompile(r.router)
|
||||
return r, err
|
||||
}
|
||||
|
||||
func (t *TableRouter) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
// checks the router is not locked by Compile while swapping router
|
||||
t.rLock.RLock()
|
||||
theIncrementor++
|
||||
z := theIncrementor
|
||||
r := t.router
|
||||
t.rLock.RUnlock()
|
||||
t.accessLog.Printf("[TableRouter %d] Serving '%s' - '%s'\n", z, req.Host, req.URL.String())
|
||||
r.ServeHTTP(rw, req)
|
||||
t.accessLog.Printf("[TableRouter %d] Served request\n", z)
|
||||
}
|
||||
|
||||
func (t *TableRouter) Compile() {
|
||||
// start the goroutine and leave
|
||||
go func() {
|
||||
// create a new router and call internalCompile
|
||||
router := mux.NewRouter()
|
||||
err := t.internalCompile(router)
|
||||
if err != nil {
|
||||
// log compile errors
|
||||
log.Printf("[TableRouter] Compile failed: %s\n", err)
|
||||
return
|
||||
}
|
||||
// lock while replacing the router
|
||||
t.rLock.Lock()
|
||||
t.router = router
|
||||
t.rLock.Unlock()
|
||||
}()
|
||||
}
|
||||
|
||||
func (t *TableRouter) internalCompile(router *mux.Router) error {
|
||||
if !t.cLock.TryLock() {
|
||||
return ErrAlreadyCompiling
|
||||
}
|
||||
defer t.cLock.Unlock()
|
||||
|
||||
router.NotFoundHandler = http.HandlerFunc(t.fourEighteen)
|
||||
|
||||
log.Println("[TableRouter] Pulling from database")
|
||||
var (
|
||||
apiDomain []web.ApiDomain
|
||||
apiRoute []web.ApiRoute
|
||||
httpDefaultHost []web.HttpDefaultHost
|
||||
httpRoutes []web.HttpRoute
|
||||
httpServices []web.HttpService
|
||||
httpRedirects []web.HttpRedirect
|
||||
httpRouteHeaders []web.HttpRouteHeader
|
||||
httpServiceHeaders []web.HttpServiceHeader
|
||||
)
|
||||
if err := t.db.Find(&apiDomain, web.ApiDomain{Enabled: utils.PBool(true)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.db.Find(&apiRoute, web.ApiRoute{Enabled: utils.PBool(true)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.db.Find(&httpDefaultHost); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.db.Find(&httpRoutes, web.HttpRoute{Enabled: utils.PBool(true)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.db.Find(&httpServices, web.HttpService{Enabled: utils.PBool(true)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.db.Find(&httpRedirects, web.HttpRedirect{Enabled: utils.PBool(true)}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.db.Find(&httpRouteHeaders); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := t.db.Find(&httpServiceHeaders); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("[TableRouter] Mapping default hosts")
|
||||
mapDefaultHost := make(map[string]web.HttpDefaultHost)
|
||||
for _, i := range httpDefaultHost {
|
||||
if _, ok := mapDefaultHost[i.Key]; ok {
|
||||
return fmt.Errorf("DefaultHost[%s] already exists", i.Key)
|
||||
}
|
||||
mapDefaultHost[i.Key] = i
|
||||
}
|
||||
|
||||
log.Println("[TableRouter] Mapping api routes to domains")
|
||||
mapApiRoute := make(map[uint64][]web.ApiRoute)
|
||||
for _, i := range apiRoute {
|
||||
if mapApiRoute[i.DomainId] == nil {
|
||||
mapApiRoute[i.DomainId] = make([]web.ApiRoute, 0)
|
||||
}
|
||||
mapApiRoute[i.DomainId] = append(mapApiRoute[i.DomainId], i)
|
||||
}
|
||||
|
||||
log.Println("[TableRouter] Mapping modified headers")
|
||||
mapRouteHeaders := make(map[uint64][]ServeHeaderItem)
|
||||
mapServiceHeaders := make(map[uint64][]ServeHeaderItem)
|
||||
for _, i := range httpRouteHeaders {
|
||||
if mapRouteHeaders[i.RouteId] == nil {
|
||||
mapRouteHeaders[i.RouteId] = make([]ServeHeaderItem, 0)
|
||||
}
|
||||
mapRouteHeaders[i.RouteId] = append(mapRouteHeaders[i.RouteId], i)
|
||||
}
|
||||
for _, i := range httpServiceHeaders {
|
||||
if mapServiceHeaders[i.ServiceId] == nil {
|
||||
mapServiceHeaders[i.ServiceId] = make([]ServeHeaderItem, 0)
|
||||
}
|
||||
mapServiceHeaders[i.ServiceId] = append(mapServiceHeaders[i.ServiceId], i)
|
||||
}
|
||||
|
||||
log.Println("[TableRouter] Adding api routes")
|
||||
for _, i := range apiDomain {
|
||||
routes := mapApiRoute[i.Id]
|
||||
if routes == nil {
|
||||
continue
|
||||
}
|
||||
subR := router.Host(i.Domain).Subrouter()
|
||||
for _, j := range routes {
|
||||
pre := fmt.Sprintf("/v%d/%s", j.Version, j.Route)
|
||||
hostD, portD, pathD, _, refD, err := utils.ParseSymbolicHost(j.Dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: '%s'", err, j.Dst)
|
||||
}
|
||||
|
||||
if refD {
|
||||
if err := resolveRef(mapDefaultHost, &hostD, &portD, &pathD); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
subR.PathPrefix(pre).Handler(ServeRoute{Host: hostD, Port: portD, Path: pathD, PathPre: pre, SecureMode: j.IsSecureMode(), IgnoreCert: j.IsIgnoreCert(), Proxy: t.proxy, Cors: true})
|
||||
}
|
||||
}
|
||||
|
||||
log.Println("[TableRouter] Adding redirects")
|
||||
for _, i := range httpRedirects {
|
||||
host, _, path, flags, _, err := utils.ParseSymbolicHost(i.Src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: '%s'", err, i.Src)
|
||||
}
|
||||
|
||||
hostD, portD, pathD, flagsD, _, err := utils.ParseSymbolicHost(i.Target)
|
||||
|
||||
z := router.Host(host)
|
||||
if path != "" {
|
||||
if utils.Contains[string](flags, "prefix") {
|
||||
z = z.PathPrefix(path)
|
||||
} else {
|
||||
z = z.Path(path)
|
||||
}
|
||||
} else {
|
||||
z = z.PathPrefix("/")
|
||||
}
|
||||
if portD != 0 {
|
||||
hostD = fmt.Sprintf("%s:%d", hostD, portD)
|
||||
}
|
||||
|
||||
z.Handler(ServeRedirect{Target: hostD, Path: pathD, Prefix: path, Flags: flagsD})
|
||||
}
|
||||
|
||||
log.Println("[TableRouter] Adding routes")
|
||||
for _, i := range httpRoutes {
|
||||
hostS, _, pathS, _, _, err := utils.ParseSymbolicHost(i.Src)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: '%s'", err, i.Src)
|
||||
}
|
||||
hostD, portD, pathD, _, refD, err := utils.ParseSymbolicHost(i.Dst)
|
||||
if err != nil {
|
||||
return fmt.Errorf("%w: '%s'", err, i.Dst)
|
||||
}
|
||||
|
||||
if refD {
|
||||
if err := resolveRef(mapDefaultHost, &hostD, &portD, &pathD); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
z := router.Host(hostS)
|
||||
if pathS != "" {
|
||||
z = z.Path(pathS)
|
||||
}
|
||||
z.Handler(ServeRoute{Host: hostD, Port: portD, Path: pathD, Headers: mapRouteHeaders[i.Id], AbsPath: i.IsAbsPath(), SecureMode: i.IsSecureMode(), ForwardHost: i.IsForwardHost(), IgnoreCert: i.IsIgnoreCert(), Proxy: t.proxy})
|
||||
}
|
||||
|
||||
log.Println("[TableRouter] Adding services")
|
||||
for _, i := range httpServices {
|
||||
hostD, portD, pathD, _, refD, err := utils.ParseSymbolicHost(i.Dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if refD {
|
||||
if err := resolveRef(mapDefaultHost, &hostD, &portD, &pathD); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
router.Host(i.Host).Handler(ServeRoute{Host: hostD, Port: portD, Path: pathD, Headers: mapServiceHeaders[i.Id], AbsPath: i.IsAbsPath(), SecureMode: i.IsSecureMode(), ForwardHost: i.IsForwardHost(), IgnoreCert: i.IsIgnoreCert(), Proxy: t.proxy})
|
||||
}
|
||||
|
||||
// well I guess we are done
|
||||
log.Println("[TableRouter] Finished compiling, updated routes will be available shortly")
|
||||
return nil
|
||||
}
|
||||
|
||||
func resolveRef(mapDefaultHost map[string]web.HttpDefaultHost, host *string, port *uint16, path *string) error {
|
||||
if y, ok := mapDefaultHost[(*host)[1:]]; ok {
|
||||
a1, a2, a3, _, _, err := utils.ParseSymbolicHost(y.Dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*host = a1
|
||||
if *port == 0 {
|
||||
*port = a2
|
||||
}
|
||||
if *path == "" {
|
||||
*path = a3
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"code.mrmelon54.com/melon/summer-utils/utils"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var redirectCodeMap = map[string]int{
|
||||
"temp": http.StatusTemporaryRedirect,
|
||||
"perm": http.StatusPermanentRedirect,
|
||||
}
|
||||
|
||||
type ServeRedirect struct {
|
||||
Target string
|
||||
Path string
|
||||
Prefix string
|
||||
Flags []string
|
||||
}
|
||||
|
||||
func (s ServeRedirect) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if s.Prefix == "/" {
|
||||
s.Prefix = ""
|
||||
}
|
||||
var p2 string
|
||||
if s.Path == "" {
|
||||
p2 = req.URL.Path
|
||||
} else {
|
||||
if !strings.HasPrefix(req.URL.Path, s.Prefix) {
|
||||
utils.RespondHttpStatus(rw, http.StatusExpectationFailed)
|
||||
return
|
||||
}
|
||||
p2 = path.Join(s.Path, req.URL.Path[len(s.Prefix):])
|
||||
if strings.HasSuffix(req.URL.Path, "/") && !strings.HasSuffix(p2, "/") {
|
||||
p2 += "/"
|
||||
}
|
||||
}
|
||||
if !strings.HasPrefix(p2, "/") {
|
||||
p2 = "/" + p2
|
||||
}
|
||||
u := url.URL{Scheme: "https", Host: s.Target, Path: p2}
|
||||
|
||||
// Update temp/perm status code with flag
|
||||
c := http.StatusFound
|
||||
if s.Flags != nil {
|
||||
outerLoop:
|
||||
for k, v := range redirectCodeMap {
|
||||
for _, i := range s.Flags {
|
||||
if k == i {
|
||||
c = v
|
||||
break outerLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
http.Redirect(rw, req, u.String(), c)
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
httpTest "github.com/stretchr/testify/http"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestServeRedirect_Location(t *testing.T) {
|
||||
redirectLocationCheck(t, "https://b.example.com/", "https://a.example.com", ServeRedirect{
|
||||
Target: "b.example.com",
|
||||
Path: "/",
|
||||
Prefix: "/",
|
||||
Flags: nil,
|
||||
})
|
||||
redirectLocationCheck(t, "https://b.example.com/", "https://a.example.com", ServeRedirect{
|
||||
Target: "b.example.com",
|
||||
Path: "",
|
||||
Prefix: "/",
|
||||
Flags: nil,
|
||||
})
|
||||
redirectLocationCheck(t, "https://b.example.com/world", "https://a.example.com/hello", ServeRedirect{
|
||||
Target: "b.example.com",
|
||||
Path: "/world",
|
||||
Prefix: "/hello",
|
||||
Flags: nil,
|
||||
})
|
||||
redirectLocationCheck(t, "https://b.example.com/goodbye/world", "https://a.example.com/hello/world", ServeRedirect{
|
||||
Target: "b.example.com",
|
||||
Path: "/goodbye",
|
||||
Prefix: "/hello",
|
||||
Flags: []string{"prefix"},
|
||||
})
|
||||
}
|
||||
|
||||
func TestServeRedirect_StatusCode(t *testing.T) {
|
||||
redirectCodeCheck(t, http.StatusFound, ServeRedirect{
|
||||
Target: "a.example.com",
|
||||
Path: "",
|
||||
Prefix: "",
|
||||
Flags: nil,
|
||||
})
|
||||
redirectCodeCheck(t, http.StatusFound, ServeRedirect{
|
||||
Target: "a.example.com",
|
||||
Path: "",
|
||||
Prefix: "",
|
||||
Flags: []string{},
|
||||
})
|
||||
redirectCodeCheck(t, http.StatusTemporaryRedirect, ServeRedirect{
|
||||
Target: "a.example.com",
|
||||
Path: "",
|
||||
Prefix: "",
|
||||
Flags: []string{"temp"},
|
||||
})
|
||||
redirectCodeCheck(t, http.StatusPermanentRedirect, ServeRedirect{
|
||||
Target: "a.example.com",
|
||||
Path: "",
|
||||
Prefix: "",
|
||||
Flags: []string{"perm"},
|
||||
})
|
||||
}
|
||||
|
||||
func redirectLocationCheck(t *testing.T, expected string, input string, serve ServeRedirect) {
|
||||
rw := &httpTest.TestResponseWriter{}
|
||||
req, err := http.NewRequest(http.MethodGet, input, nil)
|
||||
assert.NoError(t, err)
|
||||
serve.ServeHTTP(rw, req)
|
||||
assert.Equal(t, expected, rw.Header().Get("Location"))
|
||||
}
|
||||
|
||||
func redirectCodeCheck(t *testing.T, expected int, serve ServeRedirect) {
|
||||
rw := &httpTest.TestResponseWriter{}
|
||||
req, err := http.NewRequest(http.MethodGet, "https://example.com", nil)
|
||||
assert.NoError(t, err)
|
||||
serve.ServeHTTP(rw, req)
|
||||
assert.Equal(t, expected, rw.StatusCode)
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"code.mrmelon54.com/melon/azalea/proxy"
|
||||
"code.mrmelon54.com/melon/summer-utils/utils"
|
||||
"fmt"
|
||||
"github.com/gorilla/handlers"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var serveApiCors = handlers.CORS(
|
||||
handlers.AllowCredentials(),
|
||||
handlers.AllowedOrigins([]string{"*"}),
|
||||
handlers.AllowedHeaders([]string{"Content-Type", "Authorization"}),
|
||||
handlers.AllowedMethods([]string{
|
||||
http.MethodGet,
|
||||
http.MethodHead,
|
||||
http.MethodPost,
|
||||
http.MethodPut,
|
||||
http.MethodPatch,
|
||||
http.MethodDelete,
|
||||
http.MethodConnect,
|
||||
http.MethodOptions,
|
||||
http.MethodTrace,
|
||||
}),
|
||||
)
|
||||
|
||||
type ServeRoute struct {
|
||||
Host string
|
||||
Port uint16
|
||||
Path string
|
||||
PathPre string // prefix from http route specific call
|
||||
Headers []ServeHeaderItem
|
||||
Proxy http.Handler
|
||||
AbsPath bool
|
||||
SecureMode bool
|
||||
ForwardHost bool
|
||||
IgnoreCert bool
|
||||
Cors bool
|
||||
}
|
||||
|
||||
func (s ServeRoute) IsIgnoreCert() bool { return s.IgnoreCert }
|
||||
|
||||
func (s ServeRoute) UpdateHeaders(header http.Header) {
|
||||
for _, i := range s.Headers {
|
||||
header.Set(i.HeaderKey(), i.HeaderValue())
|
||||
}
|
||||
}
|
||||
|
||||
func (s ServeRoute) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
if s.Cors {
|
||||
serveApiCors(http.HandlerFunc(s.internalServeHTTP)).ServeHTTP(rw, req)
|
||||
} else {
|
||||
s.internalServeHTTP(rw, req)
|
||||
}
|
||||
}
|
||||
|
||||
func (s ServeRoute) internalServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
||||
scheme := "http"
|
||||
if s.SecureMode {
|
||||
scheme = "https"
|
||||
if s.Port == 0 {
|
||||
s.Port = 443
|
||||
}
|
||||
} else {
|
||||
if s.Port == 0 {
|
||||
s.Port = 80
|
||||
}
|
||||
}
|
||||
var p1 string
|
||||
if s.AbsPath {
|
||||
p1 = path.Join(s.Path)
|
||||
} else {
|
||||
if !strings.HasPrefix(req.URL.Path, s.PathPre) {
|
||||
utils.RespondHttpStatus(rw, http.StatusExpectationFailed)
|
||||
return
|
||||
}
|
||||
p1 = path.Join(s.Path, req.URL.Path[len(s.PathPre):])
|
||||
|
||||
// add suffix "/" to prevent redirect issues
|
||||
// the path.Join() above calls path.Clean() and strips the trailing slash
|
||||
// so this just adds the trailing slash back in
|
||||
if strings.HasSuffix(req.URL.Path, "/") && !strings.HasSuffix(p1, "/") {
|
||||
p1 += "/"
|
||||
}
|
||||
}
|
||||
|
||||
// If path is empty then correct to /
|
||||
if p1 == "" {
|
||||
p1 = "/"
|
||||
}
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
if req.Body != nil {
|
||||
_, _ = io.Copy(buf, req.Body)
|
||||
}
|
||||
|
||||
u := url.URL{
|
||||
Scheme: scheme,
|
||||
Host: fmt.Sprintf("%s:%d", s.Host, s.Port),
|
||||
Path: p1,
|
||||
RawQuery: req.URL.RawQuery,
|
||||
}
|
||||
req2, err := http.NewRequest(req.Method, u.String(), buf)
|
||||
if err != nil {
|
||||
log.Printf("[ServeRoute::ServerHTTP()] Error generating new request: %s\n", err)
|
||||
utils.RespondHttpStatus(rw, http.StatusBadGateway)
|
||||
return
|
||||
}
|
||||
for k, v := range req.Header {
|
||||
if k == "Host" {
|
||||
continue
|
||||
}
|
||||
req2.Header[k] = v
|
||||
}
|
||||
if s.ForwardHost {
|
||||
req2.Host = req.Host
|
||||
}
|
||||
s.Proxy.ServeHTTP(rw, proxy.SetReverseProxyHost(req2, s))
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
package routing
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
httpTest "github.com/stretchr/testify/http"
|
||||
"net/http"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var routeLoopProxy = http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.Header().Set("Location", req.URL.String())
|
||||
rw.Header().Set("Host", req.Host)
|
||||
})
|
||||
|
||||
func TestServeRoute_Location(t *testing.T) {
|
||||
// Minimal test
|
||||
routeLocationCheck(t, "http://localhost:8080/", "", "https://a.example.com", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 8080,
|
||||
})
|
||||
routeLocationCheck(t, "http://localhost:80/goodbye/world", "", "https://a.example.com/world", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 0,
|
||||
Path: "/goodbye",
|
||||
})
|
||||
|
||||
// ForwardHost test
|
||||
routeLocationCheck(t, "http://localhost:80/", "a.example.com", "https://a.example.com", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 0,
|
||||
ForwardHost: true,
|
||||
})
|
||||
routeLocationCheck(t, "http://localhost:8080/goodbye/world", "a.example.com", "https://a.example.com/world", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 8080,
|
||||
Path: "/goodbye",
|
||||
ForwardHost: true,
|
||||
})
|
||||
|
||||
// SecureMode test
|
||||
routeLocationCheck(t, "https://localhost:443/", "a.example.com", "https://a.example.com", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 0,
|
||||
ForwardHost: true,
|
||||
SecureMode: true,
|
||||
})
|
||||
routeLocationCheck(t, "https://localhost:8443/goodbye/world", "a.example.com", "https://a.example.com/world", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 8443,
|
||||
Path: "/goodbye",
|
||||
ForwardHost: true,
|
||||
SecureMode: true,
|
||||
})
|
||||
|
||||
// AbsPath test
|
||||
routeLocationCheck(t, "http://localhost:80/", "a.example.com", "https://a.example.com", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 0,
|
||||
ForwardHost: true,
|
||||
AbsPath: true,
|
||||
})
|
||||
routeLocationCheck(t, "http://localhost:8080/goodbye", "a.example.com", "https://a.example.com/world", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 8080,
|
||||
Path: "/goodbye",
|
||||
ForwardHost: true,
|
||||
AbsPath: true,
|
||||
})
|
||||
|
||||
// TrailingSlash test
|
||||
routeLocationCheck(t, "http://localhost:80/", "a.example.com", "https://a.example.com/", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 0,
|
||||
ForwardHost: true,
|
||||
})
|
||||
routeLocationCheck(t, "http://localhost:8080/goodbye/world/", "a.example.com", "https://a.example.com/world/", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 8080,
|
||||
Path: "/goodbye",
|
||||
ForwardHost: true,
|
||||
})
|
||||
|
||||
// Query test
|
||||
routeLocationCheck(t, "http://localhost:80/?raw=true", "a.example.com", "https://a.example.com/?raw=true", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 0,
|
||||
ForwardHost: true,
|
||||
})
|
||||
routeLocationCheck(t, "http://localhost:8080/goodbye/world/?raw=true", "a.example.com", "https://a.example.com/world/?raw=true", ServeRoute{
|
||||
Host: "localhost",
|
||||
Port: 8080,
|
||||
Path: "/goodbye",
|
||||
ForwardHost: true,
|
||||
})
|
||||
}
|
||||
|
||||
func routeLocationCheck(t *testing.T, expected, host, input string, serve ServeRoute) {
|
||||
serve.Proxy = routeLoopProxy
|
||||
rw := &httpTest.TestResponseWriter{}
|
||||
req, err := http.NewRequest(http.MethodGet, input, new(bytes.Buffer))
|
||||
assert.NoError(t, err)
|
||||
serve.ServeHTTP(rw, req)
|
||||
assert.Equal(t, expected, rw.Header().Get("Location"))
|
||||
}
|
|
@ -19,7 +19,7 @@ import (
|
|||
"xorm.io/xorm"
|
||||
)
|
||||
|
||||
func NewHttpsServer(listen string, db *xorm.Engine, tableRouter *routing.TableRouter, domainCheck *domainChecker.DomainChecker, faviconMap *favicons.Favicons, conf config.AzaleaConfig, fourEighteenError func(rw http.ResponseWriter, req *http.Request)) *http.Server {
|
||||
func NewHttpsServer(listen string, db *xorm.Engine, tableRouter *routing.SyncRouter, domainCheck *domainChecker.DomainChecker, faviconMap *favicons.Favicons, conf config.AzaleaConfig, fourEighteenError func(rw http.ResponseWriter, req *http.Request)) *http.Server {
|
||||
router := mux.NewRouter()
|
||||
setupHttpsRouter(router, tableRouter, domainCheck, faviconMap, conf, fourEighteenError)
|
||||
|
||||
|
@ -63,7 +63,7 @@ func NewHttpsServer(listen string, db *xorm.Engine, tableRouter *routing.TableRo
|
|||
return s
|
||||
}
|
||||
|
||||
func setupHttpsRouter(router *mux.Router, tableRouter *routing.TableRouter, domainCheck *domainChecker.DomainChecker, faviconMap *favicons.Favicons, conf config.AzaleaConfig, fourEighteenError func(rw http.ResponseWriter, req *http.Request)) {
|
||||
func setupHttpsRouter(router *mux.Router, tableRouter *routing.SyncRouter, domainCheck *domainChecker.DomainChecker, faviconMap *favicons.Favicons, conf config.AzaleaConfig, fourEighteenError func(rw http.ResponseWriter, req *http.Request)) {
|
||||
faviconColor := favicon.NewColor()
|
||||
|
||||
router.Use(setupRateLimiter(conf.RateLimit))
|
||||
|
|
3
go.mod
3
go.mod
|
@ -5,6 +5,7 @@ go 1.20
|
|||
require (
|
||||
code.mrmelon54.com/melon/certgen v0.0.0-20220830133534-0fb4cb7e67d1
|
||||
code.mrmelon54.com/melon/summer-utils v0.0.1
|
||||
github.com/gbrlsnchs/radix v1.0.0
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
github.com/kjk/common v0.0.0-20220705191345-4e210bd3860d
|
||||
|
@ -14,6 +15,7 @@ require (
|
|||
github.com/mrmelon54/png2ico v1.0.0
|
||||
github.com/sethvargo/go-limiter v0.7.2
|
||||
github.com/stretchr/testify v1.8.2
|
||||
github.com/yousuf64/shift v0.4.0
|
||||
golang.org/x/net v0.9.0
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
xorm.io/xorm v1.3.2
|
||||
|
@ -29,6 +31,7 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dsnet/compress v0.0.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.1 // indirect
|
||||
github.com/gbrlsnchs/color v0.1.0 // indirect
|
||||
github.com/go-latex/latex v0.0.0-20210823091927-c0d11ff05a81 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||
github.com/goccy/go-json v0.8.1 // indirect
|
||||
|
|
6
go.sum
6
go.sum
|
@ -111,6 +111,10 @@ github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3/go.mod h1:CzM2G82Q9BDUv
|
|||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
github.com/gbrlsnchs/color v0.1.0 h1:kqGI5bcsfjpkIhVL1g4IpuCA5DL+lnF1mFy8XZ7ffKg=
|
||||
github.com/gbrlsnchs/color v0.1.0/go.mod h1:DqmJ75IHg1obs9e8r0r7Q691hcywJBRUYtbxu/rBuWg=
|
||||
github.com/gbrlsnchs/radix v1.0.0 h1:z0HafxDLhD8mWXiVb3Zo1TB9zJerNNIKBb+BMr071PQ=
|
||||
github.com/gbrlsnchs/radix v1.0.0/go.mod h1:Rv0ueYu+grgwp1/ea0UUKeUlqMOqRXzf/3Ud2hFLB+E=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-fonts/dejavu v0.1.0 h1:JSajPXURYqpr+Cu8U9bt8K+XcACIHWqWrvWCKyeFmVQ=
|
||||
github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g=
|
||||
|
@ -497,6 +501,8 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X
|
|||
github.com/wcharczuk/go-chart/v2 v2.1.0 h1:tY2slqVQ6bN+yHSnDYwZebLQFkphK4WNrVwnt7CJZ2I=
|
||||
github.com/wcharczuk/go-chart/v2 v2.1.0/go.mod h1:yx7MvAVNcP/kN9lKXM/NTce4au4DFN99j6i1OwDclNA=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/yousuf64/shift v0.4.0 h1:jiuYPa9KGyTShM08GEcSRSaZeO2jPEIpdqaplsRtk8g=
|
||||
github.com/yousuf64/shift v0.4.0/go.mod h1:D9b+mj37s3goL48EGX2oCrYHW4rg4c3Il2w6fukjxas=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
|
|
Reference in New Issue