mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-30 10:56:28 +02:00
- Rename SessionState to State to avoid stutter. - Simplified option validation to use a wrapper function for base64 secrets. - Removed authenticates grpc code. - Abstracted logic to load and validate a user's authenticate session. - Removed instances of url.Parse in favor of urlutil's version. - proxy: replaces grpc refresh logic with forced deadline advancement. - internal/sessions: remove rest store; parse authorize header as part of session store. - proxy: refactor request signer - sessions: remove extend deadline (fixes #294) - remove AuthenticateInternalAddr - remove AuthenticateInternalAddrString - omit type tag.Key from declaration of vars TagKey* it will be inferred from the right-hand side - remove compatibility package xerrors - use cloned http.DefaultTransport as base transport
105 lines
2.9 KiB
Go
105 lines
2.9 KiB
Go
package httputil // import "github.com/pomerium/pomerium/internal/httputil"
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
|
|
"github.com/pomerium/pomerium/internal/log"
|
|
"github.com/pomerium/pomerium/internal/templates"
|
|
)
|
|
|
|
// Error formats creates a HTTP error with code, user friendly (and safe) error
|
|
// message. If nil or empty, HTTP status code defaults to 500 and message
|
|
// defaults to the text of the status code.
|
|
func Error(message string, code int, err error) error {
|
|
if code == 0 {
|
|
code = http.StatusInternalServerError
|
|
}
|
|
if message == "" {
|
|
message = http.StatusText(code)
|
|
}
|
|
return &httpError{Message: message, Code: code, Err: err}
|
|
}
|
|
|
|
type httpError struct {
|
|
// Message to present to the end user.
|
|
Message string
|
|
// HTTP status codes as registered with IANA.
|
|
Code int
|
|
|
|
Err error // the cause
|
|
}
|
|
|
|
func (e *httpError) Error() string {
|
|
s := fmt.Sprintf("%d %s: %s", e.Code, http.StatusText(e.Code), e.Message)
|
|
if e.Err != nil {
|
|
return s + ": " + e.Err.Error()
|
|
}
|
|
return s
|
|
}
|
|
func (e *httpError) Unwrap() error { return e.Err }
|
|
|
|
// Timeout reports whether this error represents a user debuggable error.
|
|
func (e *httpError) Debugable() bool {
|
|
return e.Code == http.StatusUnauthorized || e.Code == http.StatusForbidden
|
|
}
|
|
|
|
// ErrorResponse renders an error page given an error. If the error is a
|
|
// http error from this package, a user friendly message is set, http status code,
|
|
// the ability to debug are also set.
|
|
func ErrorResponse(rw http.ResponseWriter, r *http.Request, e error) {
|
|
statusCode := http.StatusInternalServerError // default status code to return
|
|
errorString := e.Error()
|
|
var canDebug bool
|
|
var requestID string
|
|
var httpError *httpError
|
|
// if this is an HTTPError, we can add some additional useful information
|
|
if errors.As(e, &httpError) {
|
|
canDebug = httpError.Debugable()
|
|
statusCode = httpError.Code
|
|
errorString = httpError.Message
|
|
}
|
|
|
|
log.FromRequest(r).Error().Err(e).Str("http-message", errorString).Int("http-code", statusCode).Msg("http-error")
|
|
|
|
if id, ok := log.IDFromRequest(r); ok {
|
|
requestID = id
|
|
}
|
|
if r.Header.Get("Accept") == "application/json" {
|
|
var response struct {
|
|
Error string `json:"error"`
|
|
}
|
|
response.Error = errorString
|
|
writeJSONResponse(rw, statusCode, response)
|
|
} else {
|
|
rw.WriteHeader(statusCode)
|
|
t := struct {
|
|
Code int
|
|
Title string
|
|
Message string
|
|
RequestID string
|
|
CanDebug bool
|
|
}{
|
|
Code: statusCode,
|
|
Title: http.StatusText(statusCode),
|
|
Message: errorString,
|
|
RequestID: requestID,
|
|
CanDebug: canDebug,
|
|
}
|
|
templates.New().ExecuteTemplate(rw, "error.html", t)
|
|
}
|
|
}
|
|
|
|
// writeJSONResponse is a helper that sets the application/json header and writes a response.
|
|
func writeJSONResponse(rw http.ResponseWriter, code int, response interface{}) {
|
|
rw.Header().Set("Content-Type", "application/json")
|
|
rw.WriteHeader(code)
|
|
|
|
err := json.NewEncoder(rw).Encode(response)
|
|
if err != nil {
|
|
io.WriteString(rw, err.Error())
|
|
}
|
|
}
|