generated from templates/go-generic
feat: add an ID for every request
- Add a middleware to add an ID for every request for the purpose of cross referencing requests and errors. - Add functions for handling client and server errors.
This commit is contained in:
parent
78cbc1bac5
commit
9cb1f8ed4b
2 changed files with 56 additions and 12 deletions
|
@ -2,21 +2,45 @@ package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func sendJSONResponse(w http.ResponseWriter, statusCode int, payload any) {
|
func sendResponse(writer http.ResponseWriter, statusCode int, payload any) {
|
||||||
data, err := json.Marshal(payload)
|
data, err := json.Marshal(payload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("Error marshalling the response to JSON", "error", err.Error())
|
sendServerError(
|
||||||
|
writer,
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
fmt.Errorf("error marshalling the JSON response: %w", err),
|
||||||
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writer.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(statusCode)
|
writer.WriteHeader(statusCode)
|
||||||
_, _ = w.Write(data)
|
_, _ = writer.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendClientError(writer http.ResponseWriter, statusCode int, err error) {
|
||||||
|
sendErrorResponse(
|
||||||
|
writer,
|
||||||
|
statusCode,
|
||||||
|
"Client Error: "+err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendServerError(writer http.ResponseWriter, err error) {
|
||||||
|
sendErrorResponse(
|
||||||
|
writer,
|
||||||
|
http.StatusInternalServerError,
|
||||||
|
"Server Error: "+err.Error(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendErrorResponse(writer http.ResponseWriter, statusCode int, message string) {
|
||||||
|
slog.Error(message, "request-id", writer.Header().Get("X-Request-ID"))
|
||||||
|
|
||||||
|
http.Error(writer, http.StatusText(statusCode), statusCode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"codeflow.dananglin.me.uk/apollo/indieauth-server/internal/config"
|
"codeflow.dananglin.me.uk/apollo/indieauth-server/internal/config"
|
||||||
|
@ -10,13 +13,30 @@ import (
|
||||||
func newMux(cfg config.Config) *http.ServeMux {
|
func newMux(cfg config.Config) *http.ServeMux {
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
mux.HandleFunc("GET /.well-known/oauth-authorization-server", metadataHandleFunc(cfg.Domain))
|
mux.Handle("GET /.well-known/oauth-authorization-server", setRequestID(metadataHandler(cfg.Domain)))
|
||||||
|
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
|
||||||
func metadataHandleFunc(domain string) http.HandlerFunc {
|
func setRequestID(next http.Handler) http.Handler {
|
||||||
return func(writer http.ResponseWriter, _ *http.Request) {
|
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
requestID := "UNKNOWN"
|
||||||
|
id := make([]byte, 16)
|
||||||
|
|
||||||
|
if _, err := rand.Read(id); err != nil {
|
||||||
|
slog.Error("unable to create the request ID.", "error", err.Error())
|
||||||
|
} else {
|
||||||
|
requestID = hex.EncodeToString(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.Header().Set("X-Request-ID", requestID)
|
||||||
|
|
||||||
|
next.ServeHTTP(writer, request)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func metadataHandler(domain string) http.Handler {
|
||||||
|
return http.HandlerFunc(func(writer http.ResponseWriter, _ *http.Request) {
|
||||||
metadata := struct {
|
metadata := struct {
|
||||||
Issuer string `json:"issuer"`
|
Issuer string `json:"issuer"`
|
||||||
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
||||||
|
@ -31,6 +51,6 @@ func metadataHandleFunc(domain string) http.HandlerFunc {
|
||||||
CodeChallengeMethodsSupported: []string{"S256"},
|
CodeChallengeMethodsSupported: []string{"S256"},
|
||||||
}
|
}
|
||||||
|
|
||||||
sendJSONResponse(writer, http.StatusOK, metadata)
|
sendResponse(writer, http.StatusOK, metadata)
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue