mirror of
https://github.com/volatiletech/authboss.git
synced 2024-11-28 08:58:38 +02:00
Add ability to wrap responsewriters indefinitely
This commit is contained in:
parent
2b5c85ee16
commit
c8457d818d
@ -2,6 +2,7 @@ package authboss
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -54,6 +55,16 @@ type ClientStateReadWriter interface {
|
|||||||
WriteState(http.ResponseWriter, ClientState, []ClientStateEvent) error
|
WriteState(http.ResponseWriter, ClientState, []ClientStateEvent) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnderlyingResponseWriter retrieves the response
|
||||||
|
// writer underneath the current one. This allows us
|
||||||
|
// to wrap and later discover the particular one that we want.
|
||||||
|
// Keep in mind this should not be used to call the normal methods
|
||||||
|
// of a responsewriter, just additional ones particular to that type
|
||||||
|
// because it's possible to introduce subtle bugs otherwise.
|
||||||
|
type UnderlyingResponseWriter interface {
|
||||||
|
UnderlyingResponseWriter() http.ResponseWriter
|
||||||
|
}
|
||||||
|
|
||||||
// ClientState represents the client's current state and can answer queries
|
// ClientState represents the client's current state and can answer queries
|
||||||
// about it.
|
// about it.
|
||||||
type ClientState interface {
|
type ClientState interface {
|
||||||
@ -106,6 +117,23 @@ func (a *Authboss) LoadClientState(w http.ResponseWriter, r *http.Request) (*htt
|
|||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MustClientStateResponseWriter tries to find a csrw inside the response
|
||||||
|
// writer by using the UnderlyingResponseWriter interface.
|
||||||
|
func MustClientStateResponseWriter(w http.ResponseWriter) *ClientStateResponseWriter {
|
||||||
|
for {
|
||||||
|
if c, ok := w.(*ClientStateResponseWriter); ok {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
if u, ok := w.(UnderlyingResponseWriter); ok {
|
||||||
|
w = u.UnderlyingResponseWriter()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("failed to find a ClientStateResponseWriter or UnderlyingResponseWriter in: %T", w))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WriteHeader writes the header, but in order to handle errors from the
|
// WriteHeader writes the header, but in order to handle errors from the
|
||||||
// underlying ClientStateReadWriter, it has to panic.
|
// underlying ClientStateReadWriter, it has to panic.
|
||||||
func (c *ClientStateResponseWriter) WriteHeader(code int) {
|
func (c *ClientStateResponseWriter) WriteHeader(code int) {
|
||||||
@ -132,6 +160,11 @@ func (c *ClientStateResponseWriter) Write(b []byte) (int, error) {
|
|||||||
return c.ResponseWriter.Write(b)
|
return c.ResponseWriter.Write(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UnderlyingResponseWriter for this isnstance
|
||||||
|
func (c *ClientStateResponseWriter) UnderlyingResponseWriter() http.ResponseWriter {
|
||||||
|
return c.ResponseWriter
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ClientStateResponseWriter) putClientState() error {
|
func (c *ClientStateResponseWriter) putClientState() error {
|
||||||
if c.hasWritten {
|
if c.hasWritten {
|
||||||
panic("should not call putClientState twice")
|
panic("should not call putClientState twice")
|
||||||
@ -203,7 +236,7 @@ func delState(w http.ResponseWriter, ctxKey contextKey, key string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setState(w http.ResponseWriter, ctxKey contextKey, op ClientStateEventKind, key, val string) {
|
func setState(w http.ResponseWriter, ctxKey contextKey, op ClientStateEventKind, key, val string) {
|
||||||
csrw := w.(*ClientStateResponseWriter)
|
csrw := MustClientStateResponseWriter(w)
|
||||||
ev := ClientStateEvent{
|
ev := ClientStateEvent{
|
||||||
Kind: op,
|
Kind: op,
|
||||||
Key: key,
|
Key: key,
|
||||||
|
@ -16,7 +16,7 @@ type Config struct {
|
|||||||
MountPath string
|
MountPath string
|
||||||
// ViewsPath is the path to search for overridden templates.
|
// ViewsPath is the path to search for overridden templates.
|
||||||
ViewsPath string
|
ViewsPath string
|
||||||
// RootURL is the scheme+host+port of the web application (eg https://www.happiness.com:8080) for url generation. No trailing slash.
|
// RootURL is the scheme+host+port of the web application (eg https://www.happiness.com:8080) for url generation. No trailing slash.
|
||||||
RootURL string
|
RootURL string
|
||||||
// BCryptCost is the cost of the bcrypt password hashing function.
|
// BCryptCost is the cost of the bcrypt password hashing function.
|
||||||
BCryptCost int
|
BCryptCost int
|
||||||
|
Loading…
Reference in New Issue
Block a user