feat(server/portforward): change route from /v1/openvpn/portforwarded to /v1/portforward

- This route has nothing to do with openvpn specifically
- Remove the `ed` in `portforwarded` to accomodate future routes such as changing the state of port forwarding
- maintaining retrocompatibility with `/v1/openvpn/portforwarded`
- maintaining retrocompatibility with `/openvpn/portforwarded`
- Moved to its own handler `/v1/portforward` instead of `/v1/vpn/portforward` to reduce the complexity of the vpn handler
This commit is contained in:
Quentin McGaw
2025-11-13 14:50:36 +00:00
parent 46ad576233
commit 3d1b6bc861
7 changed files with 81 additions and 45 deletions

View File

@@ -25,13 +25,14 @@ func newHandler(ctx context.Context, logger Logger, logging bool,
handler := &handler{} handler := &handler{}
vpn := newVPNHandler(ctx, vpnLooper, storage, ipv6Supported, logger) vpn := newVPNHandler(ctx, vpnLooper, storage, ipv6Supported, logger)
openvpn := newOpenvpnHandler(ctx, vpnLooper, pfGetter, logger) openvpn := newOpenvpnHandler(ctx, vpnLooper, logger)
dns := newDNSHandler(ctx, dnsLooper, logger) dns := newDNSHandler(ctx, dnsLooper, logger)
updater := newUpdaterHandler(ctx, updaterLooper, logger) updater := newUpdaterHandler(ctx, updaterLooper, logger)
publicip := newPublicIPHandler(publicIPLooper, logger) publicip := newPublicIPHandler(publicIPLooper, logger)
portForward := newPortForwardHandler(ctx, pfGetter, logger)
handler.v0 = newHandlerV0(ctx, logger, vpnLooper, dnsLooper, updaterLooper) handler.v0 = newHandlerV0(ctx, logger, vpnLooper, dnsLooper, updaterLooper)
handler.v1 = newHandlerV1(logger, buildInfo, vpn, openvpn, dns, updater, publicip) handler.v1 = newHandlerV1(logger, buildInfo, vpn, openvpn, dns, updater, publicip, portForward)
authMiddleware, err := auth.New(authSettings, logger) authMiddleware, err := auth.New(authSettings, logger)
if err != nil { if err != nil {

View File

@@ -52,7 +52,7 @@ func (h *handlerV0) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.logger.Warn(err.Error()) h.logger.Warn(err.Error())
} }
case "/openvpn/portforwarded": case "/openvpn/portforwarded":
http.Redirect(w, r, "/v1/openvpn/portforwarded", http.StatusPermanentRedirect) http.Redirect(w, r, "/v1/portforward", http.StatusPermanentRedirect)
case "/openvpn/settings": case "/openvpn/settings":
http.Redirect(w, r, "/v1/openvpn/settings", http.StatusPermanentRedirect) http.Redirect(w, r, "/v1/openvpn/settings", http.StatusPermanentRedirect)
case "/updater/restart": case "/updater/restart":

View File

@@ -10,7 +10,7 @@ import (
) )
func newHandlerV1(w warner, buildInfo models.BuildInformation, func newHandlerV1(w warner, buildInfo models.BuildInformation,
vpn, openvpn, dns, updater, publicip http.Handler, vpn, openvpn, dns, updater, publicip, portForward http.Handler,
) http.Handler { ) http.Handler {
return &handlerV1{ return &handlerV1{
warner: w, warner: w,
@@ -20,6 +20,7 @@ func newHandlerV1(w warner, buildInfo models.BuildInformation,
dns: dns, dns: dns,
updater: updater, updater: updater,
publicip: publicip, publicip: publicip,
portForward: portForward,
} }
} }
@@ -31,6 +32,7 @@ type handlerV1 struct {
dns http.Handler dns http.Handler
updater http.Handler updater http.Handler
publicip http.Handler publicip http.Handler
portForward http.Handler
} }
func (h *handlerV1) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *handlerV1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@@ -47,6 +49,8 @@ func (h *handlerV1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h.updater.ServeHTTP(w, r) h.updater.ServeHTTP(w, r)
case strings.HasPrefix(r.RequestURI, "/publicip"): case strings.HasPrefix(r.RequestURI, "/publicip"):
h.publicip.ServeHTTP(w, r) h.publicip.ServeHTTP(w, r)
case strings.HasPrefix(r.RequestURI, "/portforward"):
h.portForward.ServeHTTP(w, r)
default: default:
errString := fmt.Sprintf("%s %s not found", r.Method, r.RequestURI) errString := fmt.Sprintf("%s %s not found", r.Method, r.RequestURI)
http.Error(w, errString, http.StatusBadRequest) http.Error(w, errString, http.StatusBadRequest)

View File

@@ -37,6 +37,7 @@ func New(settings Settings, debugLogger DebugLogger) (
http.MethodGet + " /v1/updater/status": {}, http.MethodGet + " /v1/updater/status": {},
http.MethodPut + " /v1/updater/status": {}, http.MethodPut + " /v1/updater/status": {},
http.MethodGet + " /v1/publicip/ip": {}, http.MethodGet + " /v1/publicip/ip": {},
http.MethodGet + " /v1/portforward": {},
}, },
logger: debugLogger, logger: debugLogger,
} }

View File

@@ -35,6 +35,7 @@ func (s *Settings) SetDefaults() {
http.MethodGet + " /v1/updater/status", http.MethodGet + " /v1/updater/status",
http.MethodPut + " /v1/updater/status", http.MethodPut + " /v1/updater/status",
http.MethodGet + " /v1/publicip/ip", http.MethodGet + " /v1/publicip/ip",
http.MethodGet + " /v1/portforward",
}, },
}}) }})
} }
@@ -131,4 +132,5 @@ var validRoutes = map[string]struct{}{ //nolint:gochecknoglobals
http.MethodGet + " /v1/updater/status": {}, http.MethodGet + " /v1/updater/status": {},
http.MethodPut + " /v1/updater/status": {}, http.MethodPut + " /v1/updater/status": {},
http.MethodGet + " /v1/publicip/ip": {}, http.MethodGet + " /v1/publicip/ip": {},
http.MethodGet + " /v1/portforward": {},
} }

View File

@@ -10,13 +10,10 @@ import (
"github.com/qdm12/gluetun/internal/constants/vpn" "github.com/qdm12/gluetun/internal/constants/vpn"
) )
func newOpenvpnHandler(ctx context.Context, looper VPNLooper, func newOpenvpnHandler(ctx context.Context, looper VPNLooper, w warner) http.Handler {
pfGetter PortForwardedGetter, w warner,
) http.Handler {
return &openvpnHandler{ return &openvpnHandler{
ctx: ctx, ctx: ctx,
looper: looper, looper: looper,
pf: pfGetter,
warner: w, warner: w,
} }
} }
@@ -24,7 +21,6 @@ func newOpenvpnHandler(ctx context.Context, looper VPNLooper,
type openvpnHandler struct { type openvpnHandler struct {
ctx context.Context //nolint:containedctx ctx context.Context //nolint:containedctx
looper VPNLooper looper VPNLooper
pf PortForwardedGetter
warner warner warner warner
} }
@@ -47,10 +43,10 @@ func (h *openvpnHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
default: default:
errMethodNotSupported(w, r.Method) errMethodNotSupported(w, r.Method)
} }
case "/portforwarded": case "/portforwarded": // TODO v4 remove
switch r.Method { switch r.Method {
case http.MethodGet: case http.MethodGet:
h.getPortForwarded(w) http.Redirect(w, r, "/v1/portforward", http.StatusMovedPermanently)
default: default:
errMethodNotSupported(w, r.Method) errMethodNotSupported(w, r.Method)
} }
@@ -122,23 +118,3 @@ func (h *openvpnHandler) getSettings(w http.ResponseWriter) {
return return
} }
} }
func (h *openvpnHandler) getPortForwarded(w http.ResponseWriter) {
ports := h.pf.GetPortsForwarded()
encoder := json.NewEncoder(w)
var data any
switch len(ports) {
case 0:
data = portWrapper{Port: 0} // TODO v4 change to portsWrapper
case 1:
data = portWrapper{Port: ports[0]} // TODO v4 change to portsWrapper
default:
data = portsWrapper{Ports: ports}
}
err := encoder.Encode(data)
if err != nil {
h.warner.Warn(err.Error())
w.WriteHeader(http.StatusInternalServerError)
}
}

View File

@@ -0,0 +1,52 @@
package server
import (
"context"
"encoding/json"
"net/http"
)
func newPortForwardHandler(ctx context.Context,
portForward PortForwardedGetter, warner warner,
) http.Handler {
return &portForwardHandler{
ctx: ctx,
portForward: portForward,
warner: warner,
}
}
type portForwardHandler struct {
ctx context.Context //nolint:containedctx
portForward PortForwardedGetter
warner warner
}
func (h *portForwardHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
h.getPortForwarded(w)
default:
errMethodNotSupported(w, r.Method)
}
}
func (h *portForwardHandler) getPortForwarded(w http.ResponseWriter) {
ports := h.portForward.GetPortsForwarded()
encoder := json.NewEncoder(w)
var data any
switch len(ports) {
case 0:
data = portWrapper{Port: 0} // TODO v4 change to portsWrapper
case 1:
data = portWrapper{Port: ports[0]} // TODO v4 change to portsWrapper
default:
data = portsWrapper{Ports: ports}
}
err := encoder.Encode(data)
if err != nil {
h.warner.Warn(err.Error())
w.WriteHeader(http.StatusInternalServerError)
}
}