summaryrefslogtreecommitdiff
path: root/handlers
diff options
context:
space:
mode:
Diffstat (limited to 'handlers')
-rw-r--r--handlers/admin.go54
-rw-r--r--handlers/php_proxy.go18
-rw-r--r--handlers/proxy.go13
3 files changed, 77 insertions, 8 deletions
diff --git a/handlers/admin.go b/handlers/admin.go
index 44c36a5..61519fa 100644
--- a/handlers/admin.go
+++ b/handlers/admin.go
@@ -5,11 +5,22 @@ import (
"auth-proxy/logging"
"auth-proxy/models"
"auth-proxy/types"
+ "auth-proxy/worker"
"encoding/json"
+ "fmt"
"net/http"
"strconv"
+ "sync"
+ "time"
)
+var workerPool *types.WorkerPool
+
+// SetWorkerPool sets the package-level worker pool instance.
+func SetWorkerPool(pool *types.WorkerPool) {
+ workerPool = pool
+}
+
// AdminPageHandler serves the admin dashboard page.
func AdminPageHandler(w http.ResponseWriter, r *http.Request) {
// Fetch all users to render on the page
@@ -24,12 +35,20 @@ func AdminPageHandler(w http.ResponseWriter, r *http.Request) {
"Paths": config.Paths,
"Users": users,
}
- if err := templates.ExecuteTemplate(w, "admin.html", data); err != nil {
+ if err := templates.ExecuteTemplate(w, "admin.html", data); err != nil {
logging.AppLog.Error("Failed to execute admin template", "error", err)
}
}
-// GetUsersHandler returns a list of all users.
+// EnrichedUser is a wrapper for User with additional computed fields.
+// Note: We use pointers to the original User to avoid copying large structs.
+type EnrichedUser struct {
+ *types.User
+ TimeSinceLogin string `json:"time_since_login"`
+}
+
+// GetUsersHandler returns a list of all users with enriched information.
+// It uses a worker pool to calculate extra information for each user in parallel.
func GetUsersHandler(w http.ResponseWriter, r *http.Request) {
ip := logging.GetClientIP(r)
users, err := models.GetAllUsers()
@@ -39,8 +58,37 @@ func GetUsersHandler(w http.ResponseWriter, r *http.Request) {
return
}
+ enrichedUsers := make([]EnrichedUser, len(users))
+ var wg sync.WaitGroup
+
+ for i, user := range users {
+ wg.Add(1)
+ // Create copies of loop variables to avoid race conditions in the closure
+ index := i
+ userCopy := user
+
+ task := func() {
+ defer wg.Done()
+ // Simulate some work, e.g., calculating a value or fetching related data.
+ time.Sleep(5 * time.Millisecond)
+
+ timeSinceLogin := "N/A"
+ if userCopy.LastLoginAt.Valid {
+ timeSinceLogin = fmt.Sprintf("%.0fm ago", time.Since(userCopy.LastLoginAt.Time).Minutes())
+ }
+
+ enrichedUsers[index] = EnrichedUser{
+ User: &userCopy,
+ TimeSinceLogin: timeSinceLogin,
+ }
+ }
+ worker.Submit(workerPool, task)
+ }
+
+ wg.Wait() // Wait for all tasks to complete
+
w.Header().Set("Content-Type", "application/json")
- if err := json.NewEncoder(w).Encode(users); err != nil {
+ if err := json.NewEncoder(w).Encode(enrichedUsers); err != nil {
logging.AppLog.Error("Failed to encode users to JSON", "error", err, "ip", ip)
}
}
diff --git a/handlers/php_proxy.go b/handlers/php_proxy.go
index 98b62ba..d30f363 100644
--- a/handlers/php_proxy.go
+++ b/handlers/php_proxy.go
@@ -3,6 +3,7 @@ package handlers
import (
"auth-proxy/config"
"auth-proxy/logging"
+ "auth-proxy/worker"
"bytes"
"io"
"io/ioutil"
@@ -28,6 +29,11 @@ func NewPhpProxyHandler(scriptName string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fcgi, err := fcgiclient.Dial("unix", phpFpmSocket)
if err != nil {
+ errStr := err.Error()
+ ip := logging.GetClientIP(r)
+ worker.Submit(workerPool, func() {
+ logging.AppLog.Error("Failed to connect to php-fpm", "error", errStr, "ip", ip)
+ })
http.Error(w, "Failed to connect to php-fpm: "+err.Error(), http.StatusInternalServerError)
return
}
@@ -73,7 +79,10 @@ func NewPhpProxyHandler(scriptName string) http.Handler {
env["AUTH_ASSETS_PATH"] = config.Paths.Assets
- logging.AppLog.Debug("Proxying to PHP-FPM", "script_filename", scriptFilename, "doc_root", finalDocRoot)
+ // Asynchronously log the proxying action to avoid blocking the request.
+ worker.Submit(workerPool, func() {
+ logging.AppLog.Debug("Proxying to PHP-FPM", "script_filename", scriptFilename, "doc_root", finalDocRoot)
+ })
env["REQUEST_METHOD"] = r.Method
env["SERVER_SOFTWARE"] = "go / auth-proxy"
@@ -99,7 +108,12 @@ func NewPhpProxyHandler(scriptName string) http.Handler {
resp, err := fcgi.Request(env, body)
if err != nil {
- http.Error(w, "FastCGI request failed: "+err.Error(), http.StatusInternalServerError)
+ ip := logging.GetClientIP(r)
+ errStr := err.Error()
+ worker.Submit(workerPool, func() {
+ logging.AppLog.Error("FastCGI request failed", "error", errStr, "ip", ip)
+ })
+ http.Error(w, "FastCGI request failed: "+err.Error(), http.StatusInternalServerError)
return
}
diff --git a/handlers/proxy.go b/handlers/proxy.go
index 602fc78..d1f6def 100644
--- a/handlers/proxy.go
+++ b/handlers/proxy.go
@@ -2,6 +2,7 @@ package handlers
import (
"auth-proxy/logging"
+ "auth-proxy/worker"
"net/http"
"net/http/httputil"
"net/url"
@@ -22,15 +23,21 @@ func NewProxy(targetURL string) http.Handler {
director(req) // Run the default director
req.Host = target.Host // Set the Host header to the target's host
- // Log the proxying action
+ // Asynchronously log the proxying action to avoid blocking the request.
+ urlStr := req.URL.String()
ip := logging.GetClientIP(req)
- logging.AppLog.Info("Proxying request", "url", req.URL.String(), "ip", ip)
+ worker.Submit(workerPool, func() {
+ logging.AppLog.Info("Proxying request", "url", urlStr, "ip", ip)
+ })
}
// Custom error handler for logging
proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
ip := logging.GetClientIP(r)
- logging.AppLog.Error("Proxy error", "error", err, "ip", ip)
+ // Asynchronously log the proxy error to avoid blocking the response.
+ worker.Submit(workerPool, func() {
+ logging.AppLog.Error("Proxy error", "error", err, "ip", ip)
+ })
http.Error(w, "Proxy Error", http.StatusBadGateway)
}