Rewrite to use fasthttp
This commit is contained in:
113
esi_sso.go
113
esi_sso.go
@@ -9,7 +9,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -20,6 +19,8 @@ import (
|
|||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
logger "git.site.quack-lab.dev/dave/cylogger"
|
logger "git.site.quack-lab.dev/dave/cylogger"
|
||||||
|
"github.com/fasthttp/router"
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -43,8 +44,7 @@ type SSO struct {
|
|||||||
scopes []string
|
scopes []string
|
||||||
db DB
|
db DB
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
server *http.Server
|
router *router.Router
|
||||||
mux *http.ServeMux
|
|
||||||
state string
|
state string
|
||||||
callbackChan chan struct {
|
callbackChan chan struct {
|
||||||
code string
|
code string
|
||||||
@@ -79,10 +79,10 @@ func NewSSO(clientID, redirectURI string, scopes []string) (*SSO, error) {
|
|||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetMuxer allows the SSO to use an existing HTTP muxer instead of creating its own server
|
// SetRouter allows the SSO to use an existing fasthttp router
|
||||||
func (s *SSO) SetMuxer(mux *http.ServeMux) {
|
func (s *SSO) SetRouter(r *router.Router) {
|
||||||
s.mux = mux
|
s.router = r
|
||||||
logger.Debug("SSO configured to use existing HTTP muxer")
|
logger.Debug("SSO configured to use existing fasthttp router")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SSO) initDB() error {
|
func (s *SSO) initDB() error {
|
||||||
@@ -181,19 +181,12 @@ func (s *SSO) startAuthFlow(ctx context.Context, characterName string) error {
|
|||||||
logger.Info("Waiting for authentication...")
|
logger.Info("Waiting for authentication...")
|
||||||
|
|
||||||
// Setup callback handling
|
// Setup callback handling
|
||||||
if s.mux != nil {
|
if s.router == nil {
|
||||||
logger.Debug("Using existing HTTP muxer for callback handling")
|
logger.Error("No router configured for callback handling")
|
||||||
|
return errors.New("no router configured for callback handling")
|
||||||
|
}
|
||||||
|
logger.Debug("Using fasthttp router for callback handling")
|
||||||
s.setupCallbackHandler()
|
s.setupCallbackHandler()
|
||||||
} else {
|
|
||||||
logger.Debug("Starting dedicated callback server")
|
|
||||||
server, err := s.startCallbackServer()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to start callback server: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
s.server = server
|
|
||||||
defer server.Shutdown(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for callback
|
// Wait for callback
|
||||||
logger.Debug("Waiting for authentication callback")
|
logger.Debug("Waiting for authentication callback")
|
||||||
@@ -251,14 +244,28 @@ func (s *SSO) setupCallbackHandler() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Debug("Setting up callback handler on path: %s", u.Path)
|
logger.Debug("Setting up callback handler on path: %s", u.Path)
|
||||||
s.mux.HandleFunc(u.Path, s.handleCallback)
|
s.router.GET(u.Path, s.handleCallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SSO) handleCallback(w http.ResponseWriter, r *http.Request) {
|
func (s *SSO) handleCallback(ctx *fasthttp.RequestCtx) {
|
||||||
logger.Debug("Received callback request: %s %s", r.Method, r.URL.String())
|
s.processCallback(
|
||||||
if r.Method != http.MethodGet {
|
ctx.IsGet(),
|
||||||
logger.Warning("Invalid callback method: %s", r.Method)
|
string(ctx.QueryArgs().Peek("code")),
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
string(ctx.QueryArgs().Peek("state")),
|
||||||
|
func(status int, body string) {
|
||||||
|
ctx.SetStatusCode(status)
|
||||||
|
ctx.WriteString(body)
|
||||||
|
},
|
||||||
|
func(contentType string) {
|
||||||
|
ctx.SetContentType(contentType)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SSO) processCallback(isGet bool, code, state string, writeResponse func(int, string), setContentType func(string)) {
|
||||||
|
if !isGet {
|
||||||
|
logger.Warning("Invalid callback method")
|
||||||
|
writeResponse(http.StatusMethodNotAllowed, "Method not allowed")
|
||||||
s.callbackChan <- struct {
|
s.callbackChan <- struct {
|
||||||
code string
|
code string
|
||||||
state string
|
state string
|
||||||
@@ -266,13 +273,10 @@ func (s *SSO) handleCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
}{"", "", errors.New("method not allowed")}
|
}{"", "", errors.New("method not allowed")}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
q := r.URL.Query()
|
|
||||||
code := q.Get("code")
|
if code == "" || state == "" || state != s.state {
|
||||||
st := q.Get("state")
|
logger.Error("Invalid SSO response: code=%s, state=%s, expected_state=%s", code, state, s.state)
|
||||||
if code == "" || st == "" || st != s.state {
|
writeResponse(http.StatusBadRequest, "Invalid SSO response")
|
||||||
logger.Error("Invalid SSO response: code=%s, state=%s, expected_state=%s", code, st, s.state)
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
_, _ = w.Write([]byte("Invalid SSO response"))
|
|
||||||
s.callbackChan <- struct {
|
s.callbackChan <- struct {
|
||||||
code string
|
code string
|
||||||
state string
|
state string
|
||||||
@@ -280,52 +284,15 @@ func (s *SSO) handleCallback(w http.ResponseWriter, r *http.Request) {
|
|||||||
}{"", "", errors.New("invalid state")}
|
}{"", "", errors.New("invalid state")}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("Received valid callback, exchanging token for code: %s", code)
|
logger.Info("Received valid callback, exchanging token for code: %s", code)
|
||||||
w.Header().Set("Content-Type", "text/html")
|
setContentType("text/html")
|
||||||
_, _ = w.Write([]byte("<html><body><h1>Login successful!</h1><p>You can close this window.</p></body></html>"))
|
writeResponse(http.StatusOK, "<html><body><h1>Login successful!</h1><p>You can close this window.</p></body></html>")
|
||||||
s.callbackChan <- struct {
|
s.callbackChan <- struct {
|
||||||
code string
|
code string
|
||||||
state string
|
state string
|
||||||
err error
|
err error
|
||||||
}{code, st, nil}
|
}{code, state, nil}
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SSO) startCallbackServer() (*http.Server, error) {
|
|
||||||
logger.Debug("Starting dedicated callback server for redirect URI: %s", s.redirectURI)
|
|
||||||
u, err := url.Parse(s.redirectURI)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to parse redirect URI: %v", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if u.Scheme != "http" && u.Scheme != "https" {
|
|
||||||
logger.Error("Invalid redirect URI scheme: %s", u.Scheme)
|
|
||||||
return nil, errors.New("redirect URI must be http(s)")
|
|
||||||
}
|
|
||||||
hostPort := u.Host
|
|
||||||
if !strings.Contains(hostPort, ":") {
|
|
||||||
if u.Scheme == "https" {
|
|
||||||
hostPort += ":443"
|
|
||||||
} else {
|
|
||||||
hostPort += ":80"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.Debug("Callback server will listen on %s", hostPort)
|
|
||||||
mux := http.NewServeMux()
|
|
||||||
mux.HandleFunc(u.Path, s.handleCallback)
|
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", hostPort)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to listen on %s: %v", hostPort, err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
server := &http.Server{Handler: mux}
|
|
||||||
go func() {
|
|
||||||
logger.Debug("Callback server started successfully")
|
|
||||||
_ = server.Serve(ln)
|
|
||||||
}()
|
|
||||||
return server, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SSO) waitForCallback() (code, state string, err error) {
|
func (s *SSO) waitForCallback() (code, state string, err error) {
|
||||||
|
|||||||
18
go.mod
18
go.mod
@@ -1,23 +1,31 @@
|
|||||||
module go-eve-pi
|
module go-eve-pi
|
||||||
|
|
||||||
go 1.23.6
|
go 1.24.0
|
||||||
|
|
||||||
|
toolchain go1.24.8
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.site.quack-lab.dev/dave/cylogger v1.4.0
|
git.site.quack-lab.dev/dave/cylogger v1.4.0
|
||||||
|
github.com/fasthttp/router v1.5.4
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
|
github.com/valyala/fasthttp v1.67.0
|
||||||
gorm.io/driver/sqlite v1.6.0
|
gorm.io/driver/sqlite v1.6.0
|
||||||
gorm.io/gorm v1.31.0
|
gorm.io/gorm v1.31.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/andybalholm/brotli v1.2.0 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/hexops/valast v1.5.0 // indirect
|
github.com/hexops/valast v1.5.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
|
github.com/klauspost/compress v1.18.0 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
golang.org/x/mod v0.17.0 // indirect
|
github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 // indirect
|
||||||
golang.org/x/sync v0.9.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
golang.org/x/text v0.20.0 // indirect
|
golang.org/x/mod v0.27.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/sync v0.17.0 // indirect
|
||||||
|
golang.org/x/text v0.29.0 // indirect
|
||||||
|
golang.org/x/tools v0.36.0 // indirect
|
||||||
mvdan.cc/gofumpt v0.4.0 // indirect
|
mvdan.cc/gofumpt v0.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
30
go.sum
30
go.sum
@@ -1,5 +1,9 @@
|
|||||||
git.site.quack-lab.dev/dave/cylogger v1.4.0 h1:3Ca7V5JWvruARJd5S8xDFwW9LnZ9QInqkYLRdrEFvuY=
|
git.site.quack-lab.dev/dave/cylogger v1.4.0 h1:3Ca7V5JWvruARJd5S8xDFwW9LnZ9QInqkYLRdrEFvuY=
|
||||||
git.site.quack-lab.dev/dave/cylogger v1.4.0/go.mod h1:wctgZplMvroA4X6p8f4B/LaCKtiBcT1Pp+L14kcS8jk=
|
git.site.quack-lab.dev/dave/cylogger v1.4.0/go.mod h1:wctgZplMvroA4X6p8f4B/LaCKtiBcT1Pp+L14kcS8jk=
|
||||||
|
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
|
||||||
|
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
|
||||||
|
github.com/fasthttp/router v1.5.4 h1:oxdThbBwQgsDIYZ3wR1IavsNl6ZS9WdjKukeMikOnC8=
|
||||||
|
github.com/fasthttp/router v1.5.4/go.mod h1:3/hysWq6cky7dTfzaaEPZGdptwjwx0qzTgFCKEWRjgc=
|
||||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
@@ -16,6 +20,8 @@ github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
|||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
@@ -24,14 +30,22 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o
|
|||||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38 h1:D0vL7YNisV2yqE55+q0lFuGse6U8lxlg7fYTctlT5Gc=
|
||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
github.com/savsgio/gotils v0.0.0-20240704082632-aef3928b8a38/go.mod h1:sM7Mt7uEoCeFSCBM+qBrqvEo+/9vdmj19wzp3yzUhmg=
|
||||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
github.com/valyala/fasthttp v1.67.0 h1:tqKlJMUP6iuNG8hGjK/s9J4kadH7HLV4ijEcPGsezac=
|
||||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
github.com/valyala/fasthttp v1.67.0/go.mod h1:qYSIpqt/0XNmShgo/8Aq8E3UYWVVwNS2QYmzd8WIEPM=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
|
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||||
|
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||||
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
|
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||||
|
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||||
|
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||||
|
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||||
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ=
|
||||||
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8=
|
||||||
gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
|
gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY=
|
||||||
|
|||||||
68
main.go
68
main.go
@@ -4,14 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
logger "git.site.quack-lab.dev/dave/cylogger"
|
logger "git.site.quack-lab.dev/dave/cylogger"
|
||||||
|
|
||||||
|
"github.com/fasthttp/router"
|
||||||
"github.com/joho/godotenv"
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/valyala/fasthttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
@@ -46,62 +47,55 @@ func main() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup HTTP server
|
// Setup fasthttp router
|
||||||
mux := http.NewServeMux()
|
r := router.New()
|
||||||
|
|
||||||
// Configure SSO to use existing muxer
|
// Configure SSO to use existing fasthttp router
|
||||||
sso.SetMuxer(mux)
|
sso.SetRouter(r)
|
||||||
|
|
||||||
// Add your own routes
|
// Add your own routes
|
||||||
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
r.GET("/", func(ctx *fasthttp.RequestCtx) {
|
||||||
w.WriteHeader(http.StatusOK)
|
ctx.SetStatusCode(fasthttp.StatusOK)
|
||||||
w.Write([]byte("EVE PI Server Running"))
|
ctx.WriteString("EVE PI Server Running")
|
||||||
})
|
})
|
||||||
|
|
||||||
server := &http.Server{
|
r.GET("/login/{character}", func(ctx *fasthttp.RequestCtx) {
|
||||||
Addr: ":3000",
|
charName := ctx.UserValue("character")
|
||||||
Handler: mux,
|
charNameStr, ok := charName.(string)
|
||||||
|
if !ok || charNameStr == "" {
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusBadRequest)
|
||||||
|
ctx.WriteString("Missing character parameter")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
logger.Info("Login requested for character %s", charNameStr)
|
||||||
|
// Trigger the auth flow (will register callback if needed)
|
||||||
|
token, err := sso.GetToken(context.Background(), charNameStr)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Failed to authenticate character %s: %v", charNameStr, err)
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusInternalServerError)
|
||||||
|
ctx.WriteString("Authentication failed")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
logger.Info("Successfully authenticated character %s", charNameStr)
|
||||||
|
ctx.SetContentType("text/plain")
|
||||||
|
ctx.SetStatusCode(fasthttp.StatusOK)
|
||||||
|
ctx.WriteString("Authenticated! Access token: " + token)
|
||||||
|
})
|
||||||
|
|
||||||
logger.Info("Starting web server on :3000")
|
logger.Info("Starting web server on :3000")
|
||||||
go func() {
|
go func() {
|
||||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
if err := fasthttp.ListenAndServe(":3000", r.Handler); err != nil {
|
||||||
logger.Error("Server failed: %v", err)
|
logger.Error("Server failed: %v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
mux.HandleFunc("/login", func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
charName := r.URL.Query().Get("character")
|
|
||||||
if charName == "" {
|
|
||||||
http.Error(w, "Missing character parameter", http.StatusBadRequest)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger.Info("Login requested for character %s", charName)
|
|
||||||
// Trigger the auth flow (will register callback if needed)
|
|
||||||
token, err := sso.GetToken(r.Context(), charName)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("Failed to authenticate character %s: %v", charName, err)
|
|
||||||
http.Error(w, "Authentication failed", http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger.Info("Successfully authenticated character %s", charName)
|
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write([]byte("Authenticated! Access token: " + token))
|
|
||||||
})
|
|
||||||
|
|
||||||
// Listen for SIGINT and gracefully shut down the server
|
// Listen for SIGINT and gracefully shut down the server
|
||||||
sigCh := make(chan os.Signal, 1)
|
sigCh := make(chan os.Signal, 1)
|
||||||
signal.Notify(sigCh, os.Interrupt)
|
signal.Notify(sigCh, os.Interrupt)
|
||||||
<-sigCh
|
<-sigCh
|
||||||
logger.Info("SIGINT received, shutting down web server gracefully...")
|
logger.Info("SIGINT received, shutting down web server gracefully...")
|
||||||
|
|
||||||
if err := server.Shutdown(context.Background()); err != nil {
|
|
||||||
logger.Error("Error shutting down server: %v", err)
|
|
||||||
} else {
|
|
||||||
logger.Info("Web server shut down cleanly")
|
logger.Info("Web server shut down cleanly")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func LoadOptions() (Options, error) {
|
func LoadOptions() (Options, error) {
|
||||||
// Load environment variables strictly from .env file (fail if there's an error loading)
|
// Load environment variables strictly from .env file (fail if there's an error loading)
|
||||||
|
|||||||
Reference in New Issue
Block a user