-
Notifications
You must be signed in to change notification settings - Fork 221
Expand file tree
/
Copy pathresponder.go
More file actions
139 lines (114 loc) · 3.39 KB
/
responder.go
File metadata and controls
139 lines (114 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package defaults
import (
"net/http"
"strings"
"github.com/volatiletech/authboss"
)
// Responder helps respond to http requests
type Responder struct {
Renderer authboss.Renderer
}
// NewResponder constructor
func NewResponder(renderer authboss.Renderer) *Responder {
return &Responder{Renderer: renderer}
}
// Respond to an HTTP request. It's main job is to merge data that comes in from
// various middlewares via the context with the data sent by the controller and
// render that.
func (r *Responder) Respond(w http.ResponseWriter, req *http.Request, code int, page string, data authboss.HTMLData) error {
ctxData := req.Context().Value(authboss.CTXKeyData)
if ctxData != nil {
if data == nil {
data = authboss.HTMLData{}
}
data.Merge(ctxData.(authboss.HTMLData))
}
rendered, mime, err := r.Renderer.Render(req.Context(), page, data)
if err != nil {
return err
}
w.Header().Set("Content-Type", mime)
w.WriteHeader(code)
_, err = w.Write(rendered)
return err
}
func isAPIRequest(r *http.Request) bool {
return strings.HasPrefix(r.Header.Get("Content-Type"), "application/json")
}
// Redirector for http requests
type Redirector struct {
Renderer authboss.Renderer
// FormValueName for the redirection
FormValueName string
// CoerceRedirectTo200 forces http.StatusTemporaryRedirect and
// and http.StatusPermanentRedirect to http.StatusOK
CorceRedirectTo200 bool
}
// NewRedirector constructor
func NewRedirector(renderer authboss.Renderer, formValueName string) *Redirector {
return &Redirector{FormValueName: formValueName, Renderer: renderer}
}
// Redirect the client elsewhere. If it's an API request it will simply render
// a JSON response with information that should help a client to decide what
// to do.
func (r *Redirector) Redirect(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
var redirectFunction = r.redirectNonAPI
if isAPIRequest(req) {
redirectFunction = r.redirectAPI
}
return redirectFunction(w, req, ro)
}
func (r Redirector) redirectAPI(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
path := ro.RedirectPath
redir := req.FormValue(r.FormValueName)
if len(redir) != 0 && ro.FollowRedirParam {
path = redir
}
var status = "success"
var message string
if len(ro.Success) != 0 {
message = ro.Success
}
if len(ro.Failure) != 0 {
status = "failure"
message = ro.Failure
}
data := authboss.HTMLData{
"location": path,
}
data["status"] = status
if len(message) != 0 {
data["message"] = message
}
body, mime, err := r.Renderer.Render(req.Context(), "redirect", data)
if err != nil {
return err
}
if len(body) != 0 {
w.Header().Set("Content-Type", mime)
}
if ro.Code != 0 {
if r.CorceRedirectTo200 && (ro.Code == http.StatusTemporaryRedirect || ro.Code == http.StatusPermanentRedirect) {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(ro.Code)
}
}
_, err = w.Write(body)
return err
}
func (r Redirector) redirectNonAPI(w http.ResponseWriter, req *http.Request, ro authboss.RedirectOptions) error {
path := ro.RedirectPath
redir := req.FormValue(r.FormValueName)
if len(redir) != 0 && ro.FollowRedirParam {
path = redir
}
if len(ro.Success) != 0 {
authboss.PutSession(w, authboss.FlashSuccessKey, ro.Success)
}
if len(ro.Failure) != 0 {
authboss.PutSession(w, authboss.FlashErrorKey, ro.Failure)
}
http.Redirect(w, req, path, http.StatusFound)
return nil
}