Public IP endpoint with GET /ip fixing #319
This commit is contained in:
@@ -267,7 +267,7 @@ func _main(background context.Context, args []string) int { //nolint:gocognit,go
|
||||
controlServerAddress := fmt.Sprintf("0.0.0.0:%d", allSettings.ControlServer.Port)
|
||||
controlServerLogging := allSettings.ControlServer.Log
|
||||
httpServer := server.New(controlServerAddress, controlServerLogging,
|
||||
logger, buildInfo, openvpnLooper, unboundLooper, updaterLooper)
|
||||
logger, buildInfo, openvpnLooper, unboundLooper, updaterLooper, publicIPLooper)
|
||||
wg.Add(1)
|
||||
go httpServer.Run(ctx, wg)
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package publicip
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -18,6 +19,7 @@ type Looper interface {
|
||||
Stop()
|
||||
GetPeriod() (period time.Duration)
|
||||
SetPeriod(period time.Duration)
|
||||
GetPublicIP() (publicIP net.IP)
|
||||
}
|
||||
|
||||
type looper struct {
|
||||
@@ -26,6 +28,8 @@ type looper struct {
|
||||
getter IPGetter
|
||||
logger logging.Logger
|
||||
fileManager files.FileManager
|
||||
ipMutex sync.RWMutex
|
||||
ip net.IP
|
||||
ipStatusFilepath models.Filepath
|
||||
uid int
|
||||
gid int
|
||||
@@ -115,6 +119,7 @@ func (l *looper) Run(ctx context.Context, wg *sync.WaitGroup) {
|
||||
l.logAndWait(ctx, err)
|
||||
continue
|
||||
}
|
||||
l.setPublicIP(ip)
|
||||
l.logger.Info("Public IP address is %s", ip)
|
||||
const userReadWritePermissions = 0600
|
||||
err = l.fileManager.WriteLinesToFile(
|
||||
|
||||
17
internal/publicip/state.go
Normal file
17
internal/publicip/state.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package publicip
|
||||
|
||||
import "net"
|
||||
|
||||
func (l *looper) GetPublicIP() (publicIP net.IP) {
|
||||
l.ipMutex.RLock()
|
||||
defer l.ipMutex.RUnlock()
|
||||
publicIP = make(net.IP, len(l.ip))
|
||||
copy(publicIP, l.ip)
|
||||
return publicIP
|
||||
}
|
||||
|
||||
func (l *looper) setPublicIP(publicIP net.IP) {
|
||||
l.ipMutex.Lock()
|
||||
defer l.ipMutex.Unlock()
|
||||
l.ip = publicIP
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/qdm12/gluetun/internal/dns"
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/gluetun/internal/openvpn"
|
||||
"github.com/qdm12/gluetun/internal/publicip"
|
||||
"github.com/qdm12/gluetun/internal/updater"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
@@ -16,15 +17,17 @@ func newHandler(logger logging.Logger, logging bool,
|
||||
openvpnLooper openvpn.Looper,
|
||||
unboundLooper dns.Looper,
|
||||
updaterLooper updater.Looper,
|
||||
publicIPLooper publicip.Looper,
|
||||
) http.Handler {
|
||||
handler := &handler{}
|
||||
|
||||
openvpn := newOpenvpnHandler(openvpnLooper, logger)
|
||||
dns := newDNSHandler(unboundLooper, logger)
|
||||
updater := newUpdaterHandler(updaterLooper, logger)
|
||||
publicip := newPublicIPHandler(publicIPLooper, logger)
|
||||
|
||||
handler.v0 = newHandlerV0(logger, openvpnLooper, unboundLooper, updaterLooper)
|
||||
handler.v1 = newHandlerV1(logger, buildInfo, openvpn, dns, updater)
|
||||
handler.v1 = newHandlerV1(logger, buildInfo, openvpn, dns, updater, publicip)
|
||||
|
||||
handlerWithLog := withLogMiddleware(handler, logger, logging)
|
||||
handler.setLogEnabled = handlerWithLog.setEnabled
|
||||
|
||||
@@ -11,13 +11,14 @@ import (
|
||||
)
|
||||
|
||||
func newHandlerV1(logger logging.Logger, buildInfo models.BuildInformation,
|
||||
openvpn, dns, updater http.Handler) http.Handler {
|
||||
openvpn, dns, updater, publicip http.Handler) http.Handler {
|
||||
return &handlerV1{
|
||||
logger: logger,
|
||||
buildInfo: buildInfo,
|
||||
openvpn: openvpn,
|
||||
dns: dns,
|
||||
updater: updater,
|
||||
publicip: publicip,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +28,7 @@ type handlerV1 struct {
|
||||
openvpn http.Handler
|
||||
dns http.Handler
|
||||
updater http.Handler
|
||||
publicip http.Handler
|
||||
}
|
||||
|
||||
func (h *handlerV1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -39,6 +41,8 @@ func (h *handlerV1) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
h.dns.ServeHTTP(w, r)
|
||||
case strings.HasPrefix(r.RequestURI, "/updater"):
|
||||
h.updater.ServeHTTP(w, r)
|
||||
case strings.HasPrefix(r.RequestURI, "/publicip"):
|
||||
h.publicip.ServeHTTP(w, r)
|
||||
default:
|
||||
errString := fmt.Sprintf("%s %s not found", r.Method, r.RequestURI)
|
||||
http.Error(w, errString, http.StatusNotFound)
|
||||
|
||||
55
internal/server/publicip.go
Normal file
55
internal/server/publicip.go
Normal file
@@ -0,0 +1,55 @@
|
||||
//nolint:dupl
|
||||
package server
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/qdm12/gluetun/internal/publicip"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
|
||||
func newPublicIPHandler(
|
||||
looper publicip.Looper,
|
||||
logger logging.Logger) http.Handler {
|
||||
return &publicIPHandler{
|
||||
looper: looper,
|
||||
logger: logger,
|
||||
}
|
||||
}
|
||||
|
||||
type publicIPHandler struct {
|
||||
looper publicip.Looper
|
||||
logger logging.Logger
|
||||
}
|
||||
|
||||
func (h *publicIPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
r.RequestURI = strings.TrimPrefix(r.RequestURI, "/publicip")
|
||||
switch r.RequestURI {
|
||||
case "/ip":
|
||||
switch r.Method {
|
||||
case http.MethodGet:
|
||||
h.getPublicIP(w)
|
||||
default:
|
||||
http.Error(w, "", http.StatusNotFound)
|
||||
}
|
||||
default:
|
||||
http.Error(w, "", http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
type publicIPWrapper struct {
|
||||
PublicIP string `json:"public_ip"`
|
||||
}
|
||||
|
||||
func (h *publicIPHandler) getPublicIP(w http.ResponseWriter) {
|
||||
publicIP := h.looper.GetPublicIP()
|
||||
encoder := json.NewEncoder(w)
|
||||
data := publicIPWrapper{PublicIP: publicIP.String()}
|
||||
if err := encoder.Encode(data); err != nil {
|
||||
h.logger.Warn(err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/qdm12/gluetun/internal/dns"
|
||||
"github.com/qdm12/gluetun/internal/models"
|
||||
"github.com/qdm12/gluetun/internal/openvpn"
|
||||
"github.com/qdm12/gluetun/internal/publicip"
|
||||
"github.com/qdm12/gluetun/internal/updater"
|
||||
"github.com/qdm12/golibs/logging"
|
||||
)
|
||||
@@ -25,9 +26,11 @@ type server struct {
|
||||
|
||||
func New(address string, logging bool, logger logging.Logger,
|
||||
buildInfo models.BuildInformation,
|
||||
openvpnLooper openvpn.Looper, unboundLooper dns.Looper, updaterLooper updater.Looper) Server {
|
||||
openvpnLooper openvpn.Looper, unboundLooper dns.Looper,
|
||||
updaterLooper updater.Looper, publicIPLooper publicip.Looper) Server {
|
||||
serverLogger := logger.WithPrefix("http server: ")
|
||||
handler := newHandler(serverLogger, logging, buildInfo, openvpnLooper, unboundLooper, updaterLooper)
|
||||
handler := newHandler(serverLogger, logging, buildInfo,
|
||||
openvpnLooper, unboundLooper, updaterLooper, publicIPLooper)
|
||||
return &server{
|
||||
address: address,
|
||||
logger: serverLogger,
|
||||
|
||||
Reference in New Issue
Block a user