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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"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)
|
||||
if err != nil {
|
||||
slog.Error("Error marshalling the response to JSON", "error", err.Error())
|
||||
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
sendServerError(
|
||||
writer,
|
||||
fmt.Errorf("error marshalling the JSON response: %w", err),
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(statusCode)
|
||||
_, _ = w.Write(data)
|
||||
writer.Header().Set("Content-Type", "application/json")
|
||||
writer.WriteHeader(statusCode)
|
||||
_, _ = 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
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"codeflow.dananglin.me.uk/apollo/indieauth-server/internal/config"
|
||||
|
@ -10,13 +13,30 @@ import (
|
|||
func newMux(cfg config.Config) *http.ServeMux {
|
||||
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
|
||||
}
|
||||
|
||||
func metadataHandleFunc(domain string) http.HandlerFunc {
|
||||
return func(writer http.ResponseWriter, _ *http.Request) {
|
||||
func setRequestID(next http.Handler) http.Handler {
|
||||
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 {
|
||||
Issuer string `json:"issuer"`
|
||||
AuthorizationEndpoint string `json:"authorization_endpoint"`
|
||||
|
@ -31,6 +51,6 @@ func metadataHandleFunc(domain string) http.HandlerFunc {
|
|||
CodeChallengeMethodsSupported: []string{"S256"},
|
||||
}
|
||||
|
||||
sendJSONResponse(writer, http.StatusOK, metadata)
|
||||
}
|
||||
sendResponse(writer, http.StatusOK, metadata)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue