Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F10384210
handle.go
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
18 KB
Subscribers
None
handle.go
View Options
/*
* Copyright © 2018 A Bunch Tell LLC.
*
* This file is part of WriteFreely.
*
* WriteFreely is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, included
* in the LICENSE file in this source code package.
*/
package
writefreely
import
(
"fmt"
"html/template"
"net/http"
"net/url"
"runtime/debug"
"strconv"
"strings"
"time"
"github.com/gorilla/sessions"
"github.com/writeas/impart"
"github.com/writeas/web-core/log"
"github.com/writeas/writefreely/page"
)
type
UserLevel
int
const
(
UserLevelNone
UserLevel
=
iota
// user or not -- ignored
UserLevelOptional
// user or not -- object fetched if user
UserLevelNoneRequired
// non-user (required)
UserLevelUser
// user (required)
)
type
(
handlerFunc
func
(
app
*
App
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
error
userHandlerFunc
func
(
app
*
App
,
u
*
User
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
error
dataHandlerFunc
func
(
app
*
App
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
([]
byte
,
string
,
error
)
authFunc
func
(
app
*
App
,
r
*
http
.
Request
)
(
*
User
,
error
)
)
type
Handler
struct
{
errors
*
ErrorPages
sessionStore
*
sessions
.
CookieStore
app
*
App
}
// ErrorPages hold template HTML error pages for displaying errors to the user.
// In each, there should be a defined template named "base".
type
ErrorPages
struct
{
NotFound
*
template
.
Template
Gone
*
template
.
Template
InternalServerError
*
template
.
Template
Blank
*
template
.
Template
}
// NewHandler returns a new Handler instance, using the given StaticPage data,
// and saving alias to the application's CookieStore.
func
NewHandler
(
app
*
App
)
*
Handler
{
h
:=
&
Handler
{
errors
:
&
ErrorPages
{
NotFound
:
template
.
Must
(
template
.
New
(
""
).
Parse
(
"{{define \"base\"}}<html><head><title>404</title></head><body><p>Not found.</p></body></html>{{end}}"
)),
Gone
:
template
.
Must
(
template
.
New
(
""
).
Parse
(
"{{define \"base\"}}<html><head><title>410</title></head><body><p>Gone.</p></body></html>{{end}}"
)),
InternalServerError
:
template
.
Must
(
template
.
New
(
""
).
Parse
(
"{{define \"base\"}}<html><head><title>500</title></head><body><p>Internal server error.</p></body></html>{{end}}"
)),
Blank
:
template
.
Must
(
template
.
New
(
""
).
Parse
(
"{{define \"base\"}}<html><head><title>{{.Title}}</title></head><body><p>{{.Content}}</p></body></html>{{end}}"
)),
},
sessionStore
:
app
.
sessionStore
,
app
:
app
,
}
return
h
}
// NewWFHandler returns a new Handler instance, using WriteFreely template files.
// You MUST call writefreely.InitTemplates() before this.
func
NewWFHandler
(
app
*
App
)
*
Handler
{
h
:=
NewHandler
(
app
)
h
.
SetErrorPages
(
&
ErrorPages
{
NotFound
:
pages
[
"404-general.tmpl"
],
Gone
:
pages
[
"410.tmpl"
],
InternalServerError
:
pages
[
"500.tmpl"
],
Blank
:
pages
[
"blank.tmpl"
],
})
return
h
}
// SetErrorPages sets the given set of ErrorPages as templates for any errors
// that come up.
func
(
h
*
Handler
)
SetErrorPages
(
e
*
ErrorPages
)
{
h
.
errors
=
e
}
// User handles requests made in the web application by the authenticated user.
// This provides user-friendly HTML pages and actions that work in the browser.
func
(
h
*
Handler
)
User
(
f
userHandlerFunc
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
h
.
handleHTTPError
(
w
,
r
,
func
()
error
{
var
status
int
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
log
.
Error
(
"%s: %s"
,
e
,
debug
.
Stack
())
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
http
.
StatusInternalServerError
}
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
}()
u
:=
getUserSession
(
h
.
app
,
r
)
if
u
==
nil
{
err
:=
ErrNotLoggedIn
status
=
err
.
Status
return
err
}
err
:=
f
(
h
.
app
,
u
,
w
,
r
)
if
err
==
nil
{
status
=
http
.
StatusOK
}
else
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
err
.
Status
}
else
{
status
=
http
.
StatusInternalServerError
}
return
err
}())
}
}
// Admin handles requests on /admin routes
func
(
h
*
Handler
)
Admin
(
f
userHandlerFunc
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
h
.
handleHTTPError
(
w
,
r
,
func
()
error
{
var
status
int
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
log
.
Error
(
"%s: %s"
,
e
,
debug
.
Stack
())
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
http
.
StatusInternalServerError
}
log
.
Info
(
fmt
.
Sprintf
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
()))
}()
u
:=
getUserSession
(
h
.
app
,
r
)
if
u
==
nil
||
!
u
.
IsAdmin
()
{
err
:=
impart
.
HTTPError
{
http
.
StatusNotFound
,
""
}
status
=
err
.
Status
return
err
}
err
:=
f
(
h
.
app
,
u
,
w
,
r
)
if
err
==
nil
{
status
=
http
.
StatusOK
}
else
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
err
.
Status
}
else
{
status
=
http
.
StatusInternalServerError
}
return
err
}())
}
}
// UserAPI handles requests made in the API by the authenticated user.
// This provides user-friendly HTML pages and actions that work in the browser.
func
(
h
*
Handler
)
UserAPI
(
f
userHandlerFunc
)
http
.
HandlerFunc
{
return
h
.
UserAll
(
false
,
f
,
func
(
app
*
App
,
r
*
http
.
Request
)
(
*
User
,
error
)
{
// Authorize user from Authorization header
t
:=
r
.
Header
.
Get
(
"Authorization"
)
if
t
==
""
{
return
nil
,
ErrNoAccessToken
}
u
:=
&
User
{
ID
:
app
.
db
.
GetUserID
(
t
)}
if
u
.
ID
==
-
1
{
return
nil
,
ErrBadAccessToken
}
return
u
,
nil
})
}
func
(
h
*
Handler
)
UserAll
(
web
bool
,
f
userHandlerFunc
,
a
authFunc
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
handleFunc
:=
func
()
error
{
var
status
int
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
log
.
Error
(
"%s: %s"
,
e
,
debug
.
Stack
())
impart
.
WriteError
(
w
,
impart
.
HTTPError
{
http
.
StatusInternalServerError
,
"Something didn't work quite right."
})
status
=
500
}
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
}()
u
,
err
:=
a
(
h
.
app
,
r
)
if
err
!=
nil
{
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
err
.
Status
}
else
{
status
=
500
}
return
err
}
err
=
f
(
h
.
app
,
u
,
w
,
r
)
if
err
==
nil
{
status
=
200
}
else
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
err
.
Status
}
else
{
status
=
500
}
return
err
}
if
web
{
h
.
handleHTTPError
(
w
,
r
,
handleFunc
())
}
else
{
h
.
handleError
(
w
,
r
,
handleFunc
())
}
}
}
func
(
h
*
Handler
)
RedirectOnErr
(
f
handlerFunc
,
loc
string
)
handlerFunc
{
return
func
(
app
*
App
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
error
{
err
:=
f
(
app
,
w
,
r
)
if
err
!=
nil
{
if
ie
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
// Override default redirect with returned error's, if it's a
// redirect error.
if
ie
.
Status
==
http
.
StatusFound
{
return
ie
}
}
return
impart
.
HTTPError
{
http
.
StatusFound
,
loc
}
}
return
nil
}
}
func
(
h
*
Handler
)
Page
(
n
string
)
http
.
HandlerFunc
{
return
h
.
Web
(
func
(
app
*
App
,
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
error
{
t
,
ok
:=
pages
[
n
]
if
!
ok
{
return
impart
.
HTTPError
{
http
.
StatusNotFound
,
"Page not found."
}
}
sp
:=
pageForReq
(
app
,
r
)
err
:=
t
.
ExecuteTemplate
(
w
,
"base"
,
sp
)
if
err
!=
nil
{
log
.
Error
(
"Unable to render page: %v"
,
err
)
}
return
err
},
UserLevelOptional
)
}
func
(
h
*
Handler
)
WebErrors
(
f
handlerFunc
,
ul
UserLevel
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
// TODO: factor out this logic shared with Web()
h
.
handleHTTPError
(
w
,
r
,
func
()
error
{
var
status
int
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
u
:=
getUserSession
(
h
.
app
,
r
)
username
:=
"None"
if
u
!=
nil
{
username
=
u
.
Username
}
log
.
Error
(
"User: %s\n\n%s: %s"
,
username
,
e
,
debug
.
Stack
())
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
500
}
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
}()
var
session
*
sessions
.
Session
var
err
error
if
ul
!=
UserLevelNone
{
session
,
err
=
h
.
sessionStore
.
Get
(
r
,
cookieName
)
if
err
!=
nil
&&
(
ul
==
UserLevelNoneRequired
||
ul
==
UserLevelUser
)
{
// Cookie is required, but we can ignore this error
log
.
Error
(
"Handler: Unable to get session (for user permission %d); ignoring: %v"
,
ul
,
err
)
}
_
,
gotUser
:=
session
.
Values
[
cookieUserVal
].(
*
User
)
if
ul
==
UserLevelNoneRequired
&&
gotUser
{
to
:=
correctPageFromLoginAttempt
(
r
)
log
.
Info
(
"Handler: Required NO user, but got one. Redirecting to %s"
,
to
)
err
:=
impart
.
HTTPError
{
http
.
StatusFound
,
to
}
status
=
err
.
Status
return
err
}
else
if
ul
==
UserLevelUser
&&
!
gotUser
{
log
.
Info
(
"Handler: Required a user, but DIDN'T get one. Sending not logged in."
)
err
:=
ErrNotLoggedIn
status
=
err
.
Status
return
err
}
}
// TODO: pass User object to function
err
=
f
(
h
.
app
,
w
,
r
)
if
err
==
nil
{
status
=
200
}
else
if
httpErr
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
httpErr
.
Status
if
status
<
300
||
status
>
399
{
addSessionFlash
(
h
.
app
,
w
,
r
,
httpErr
.
Message
,
session
)
return
impart
.
HTTPError
{
http
.
StatusFound
,
r
.
Referer
()}
}
}
else
{
e
:=
fmt
.
Sprintf
(
"[Web handler] 500: %v"
,
err
)
if
!
strings
.
HasSuffix
(
e
,
"write: broken pipe"
)
{
log
.
Error
(
e
)
}
else
{
log
.
Error
(
e
)
}
log
.
Info
(
"Web handler internal error render"
)
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
500
}
return
err
}())
}
}
// Web handles requests made in the web application. This provides user-
// friendly HTML pages and actions that work in the browser.
func
(
h
*
Handler
)
Web
(
f
handlerFunc
,
ul
UserLevel
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
h
.
handleHTTPError
(
w
,
r
,
func
()
error
{
var
status
int
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
u
:=
getUserSession
(
h
.
app
,
r
)
username
:=
"None"
if
u
!=
nil
{
username
=
u
.
Username
}
log
.
Error
(
"User: %s\n\n%s: %s"
,
username
,
e
,
debug
.
Stack
())
log
.
Info
(
"Web deferred internal error render"
)
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
500
}
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
}()
if
ul
!=
UserLevelNone
{
session
,
err
:=
h
.
sessionStore
.
Get
(
r
,
cookieName
)
if
err
!=
nil
&&
(
ul
==
UserLevelNoneRequired
||
ul
==
UserLevelUser
)
{
// Cookie is required, but we can ignore this error
log
.
Error
(
"Handler: Unable to get session (for user permission %d); ignoring: %v"
,
ul
,
err
)
}
_
,
gotUser
:=
session
.
Values
[
cookieUserVal
].(
*
User
)
if
ul
==
UserLevelNoneRequired
&&
gotUser
{
to
:=
correctPageFromLoginAttempt
(
r
)
log
.
Info
(
"Handler: Required NO user, but got one. Redirecting to %s"
,
to
)
err
:=
impart
.
HTTPError
{
http
.
StatusFound
,
to
}
status
=
err
.
Status
return
err
}
else
if
ul
==
UserLevelUser
&&
!
gotUser
{
log
.
Info
(
"Handler: Required a user, but DIDN'T get one. Sending not logged in."
)
err
:=
ErrNotLoggedIn
status
=
err
.
Status
return
err
}
}
// TODO: pass User object to function
err
:=
f
(
h
.
app
,
w
,
r
)
if
err
==
nil
{
status
=
200
}
else
if
httpErr
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
httpErr
.
Status
}
else
{
e
:=
fmt
.
Sprintf
(
"[Web handler] 500: %v"
,
err
)
log
.
Error
(
e
)
log
.
Info
(
"Web internal error render"
)
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
500
}
return
err
}())
}
}
func
(
h
*
Handler
)
All
(
f
handlerFunc
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
h
.
handleError
(
w
,
r
,
func
()
error
{
// TODO: return correct "success" status
status
:=
200
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
log
.
Error
(
"%s:\n%s"
,
e
,
debug
.
Stack
())
impart
.
WriteError
(
w
,
impart
.
HTTPError
{
http
.
StatusInternalServerError
,
"Something didn't work quite right."
})
status
=
500
}
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
}()
// TODO: do any needed authentication
err
:=
f
(
h
.
app
,
w
,
r
)
if
err
!=
nil
{
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
err
.
Status
}
else
{
status
=
500
}
}
return
err
}())
}
}
func
(
h
*
Handler
)
Download
(
f
dataHandlerFunc
,
ul
UserLevel
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
h
.
handleHTTPError
(
w
,
r
,
func
()
error
{
var
status
int
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
log
.
Error
(
"%s: %s"
,
e
,
debug
.
Stack
())
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
500
}
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
}()
data
,
filename
,
err
:=
f
(
h
.
app
,
w
,
r
)
if
err
!=
nil
{
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
status
=
err
.
Status
}
else
{
status
=
500
}
return
err
}
ext
:=
".json"
ct
:=
"application/json"
if
strings
.
HasSuffix
(
r
.
URL
.
Path
,
".csv"
)
{
ext
=
".csv"
ct
=
"text/csv"
}
else
if
strings
.
HasSuffix
(
r
.
URL
.
Path
,
".zip"
)
{
ext
=
".zip"
ct
=
"application/zip"
}
w
.
Header
().
Set
(
"Content-Disposition"
,
fmt
.
Sprintf
(
"attachment; filename=%s%s"
,
filename
,
ext
))
w
.
Header
().
Set
(
"Content-Type"
,
ct
)
w
.
Header
().
Set
(
"Content-Length"
,
strconv
.
Itoa
(
len
(
data
)))
fmt
.
Fprint
(
w
,
string
(
data
))
status
=
200
return
nil
}())
}
}
func
(
h
*
Handler
)
Redirect
(
url
string
,
ul
UserLevel
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
h
.
handleHTTPError
(
w
,
r
,
func
()
error
{
start
:=
time
.
Now
()
var
status
int
if
ul
!=
UserLevelNone
{
session
,
err
:=
h
.
sessionStore
.
Get
(
r
,
cookieName
)
if
err
!=
nil
&&
(
ul
==
UserLevelNoneRequired
||
ul
==
UserLevelUser
)
{
// Cookie is required, but we can ignore this error
log
.
Error
(
"Handler: Unable to get session (for user permission %d); ignoring: %v"
,
ul
,
err
)
}
_
,
gotUser
:=
session
.
Values
[
cookieUserVal
].(
*
User
)
if
ul
==
UserLevelNoneRequired
&&
gotUser
{
to
:=
correctPageFromLoginAttempt
(
r
)
log
.
Info
(
"Handler: Required NO user, but got one. Redirecting to %s"
,
to
)
err
:=
impart
.
HTTPError
{
http
.
StatusFound
,
to
}
status
=
err
.
Status
return
err
}
else
if
ul
==
UserLevelUser
&&
!
gotUser
{
log
.
Info
(
"Handler: Required a user, but DIDN'T get one. Sending not logged in."
)
err
:=
ErrNotLoggedIn
status
=
err
.
Status
return
err
}
}
status
=
sendRedirect
(
w
,
http
.
StatusFound
,
url
)
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
return
nil
}())
}
}
func
(
h
*
Handler
)
handleHTTPError
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
err
error
)
{
if
err
==
nil
{
return
}
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
if
err
.
Status
>=
300
&&
err
.
Status
<
400
{
sendRedirect
(
w
,
err
.
Status
,
err
.
Message
)
return
}
else
if
err
.
Status
==
http
.
StatusUnauthorized
{
q
:=
""
if
r
.
URL
.
RawQuery
!=
""
{
q
=
url
.
QueryEscape
(
"?"
+
r
.
URL
.
RawQuery
)
}
sendRedirect
(
w
,
http
.
StatusFound
,
"/login?to="
+
r
.
URL
.
Path
+
q
)
return
}
else
if
err
.
Status
==
http
.
StatusGone
{
w
.
WriteHeader
(
err
.
Status
)
p
:=
&
struct
{
page
.
StaticPage
Content
*
template
.
HTML
}{
StaticPage
:
pageForReq
(
h
.
app
,
r
),
}
if
err
.
Message
!=
""
{
co
:=
template
.
HTML
(
err
.
Message
)
p
.
Content
=
&
co
}
h
.
errors
.
Gone
.
ExecuteTemplate
(
w
,
"base"
,
p
)
return
}
else
if
err
.
Status
==
http
.
StatusNotFound
{
w
.
WriteHeader
(
err
.
Status
)
h
.
errors
.
NotFound
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
return
}
else
if
err
.
Status
==
http
.
StatusInternalServerError
{
w
.
WriteHeader
(
err
.
Status
)
log
.
Info
(
"handleHTTPErorr internal error render"
)
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
return
}
else
if
err
.
Status
==
http
.
StatusAccepted
{
impart
.
WriteSuccess
(
w
,
""
,
err
.
Status
)
return
}
else
{
p
:=
&
struct
{
page
.
StaticPage
Title
string
Content
template
.
HTML
}{
pageForReq
(
h
.
app
,
r
),
fmt
.
Sprintf
(
"Uh oh (%d)"
,
err
.
Status
),
template
.
HTML
(
fmt
.
Sprintf
(
"<p style=\"text-align: center\" class=\"introduction\">%s</p>"
,
err
.
Message
)),
}
h
.
errors
.
Blank
.
ExecuteTemplate
(
w
,
"base"
,
p
)
return
}
impart
.
WriteError
(
w
,
err
)
return
}
impart
.
WriteError
(
w
,
impart
.
HTTPError
{
http
.
StatusInternalServerError
,
"This is an unhelpful error message for a miscellaneous internal error."
})
}
func
(
h
*
Handler
)
handleError
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
,
err
error
)
{
if
err
==
nil
{
return
}
if
err
,
ok
:=
err
.(
impart
.
HTTPError
);
ok
{
if
err
.
Status
>=
300
&&
err
.
Status
<
400
{
sendRedirect
(
w
,
err
.
Status
,
err
.
Message
)
return
}
// if strings.Contains(r.Header.Get("Accept"), "text/html") {
impart
.
WriteError
(
w
,
err
)
// }
return
}
if
IsJSON
(
r
.
Header
.
Get
(
"Content-Type"
))
{
impart
.
WriteError
(
w
,
impart
.
HTTPError
{
http
.
StatusInternalServerError
,
"This is an unhelpful error message for a miscellaneous internal error."
})
return
}
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
}
func
correctPageFromLoginAttempt
(
r
*
http
.
Request
)
string
{
to
:=
r
.
FormValue
(
"to"
)
if
to
==
""
{
to
=
"/"
}
else
if
!
strings
.
HasPrefix
(
to
,
"/"
)
{
to
=
"/"
+
to
}
return
to
}
func
(
h
*
Handler
)
LogHandlerFunc
(
f
http
.
HandlerFunc
)
http
.
HandlerFunc
{
return
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
h
.
handleHTTPError
(
w
,
r
,
func
()
error
{
status
:=
200
start
:=
time
.
Now
()
defer
func
()
{
if
e
:=
recover
();
e
!=
nil
{
log
.
Error
(
"Handler.LogHandlerFunc\n\n%s: %s"
,
e
,
debug
.
Stack
())
h
.
errors
.
InternalServerError
.
ExecuteTemplate
(
w
,
"base"
,
pageForReq
(
h
.
app
,
r
))
status
=
500
}
// TODO: log actual status code returned
log
.
Info
(
"\"%s %s\" %d %s \"%s\""
,
r
.
Method
,
r
.
RequestURI
,
status
,
time
.
Since
(
start
),
r
.
UserAgent
())
}()
f
(
w
,
r
)
return
nil
}())
}
}
func
sendRedirect
(
w
http
.
ResponseWriter
,
code
int
,
location
string
)
int
{
w
.
Header
().
Set
(
"Location"
,
location
)
w
.
WriteHeader
(
code
)
return
code
}
File Metadata
Details
Attached
Mime Type
text/html
Expires
Sat, Nov 23, 7:43 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3104450
Attached To
rWF WriteFreely
Event Timeline
Log In to Comment