Merge branch 'master' into master

This commit is contained in:
Bo-Yi Wu 2017-09-28 22:55:48 +08:00 committed by GitHub
commit ad18194d9e
3 changed files with 48 additions and 29 deletions

View File

@ -163,6 +163,14 @@ func setTimeField(val string, structField reflect.StructField, value reflect.Val
l = time.UTC
}
if locTag := structField.Tag.Get("time_location"); locTag != "" {
loc, err := time.LoadLocation(locTag)
if err != nil {
return err
}
l = loc
}
t, err := time.ParseInLocation(timeFormat, val, l)
if err != nil {
return err

View File

@ -45,6 +45,7 @@ func createMultipartRequest() *http.Request {
must(mw.WriteField("id", ""))
must(mw.WriteField("time_local", "31/12/2016 14:55"))
must(mw.WriteField("time_utc", "31/12/2016 14:55"))
must(mw.WriteField("time_location", "31/12/2016 14:55"))
req, err := http.NewRequest("POST", "/", body)
must(err)
req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
@ -451,6 +452,7 @@ func TestContextPostFormMultipart(t *testing.T) {
ID string `form:"id"`
TimeLocal time.Time `form:"time_local" time_format:"02/01/2006 15:04"`
TimeUTC time.Time `form:"time_utc" time_format:"02/01/2006 15:04" time_utc:"1"`
TimeLocation time.Time `form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo"`
BlankTime time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
}
assert.NoError(t, c.Bind(&obj))
@ -463,6 +465,9 @@ func TestContextPostFormMultipart(t *testing.T) {
assert.Equal(t, obj.TimeLocal.Location(), time.Local)
assert.Equal(t, obj.TimeUTC.Format("02/01/2006 15:04"), "31/12/2016 14:55")
assert.Equal(t, obj.TimeUTC.Location(), time.UTC)
loc, _ := time.LoadLocation("Asia/Tokyo")
assert.Equal(t, obj.TimeLocation.Format("02/01/2006 15:04"), "31/12/2016 14:55")
assert.Equal(t, obj.TimeLocation.Location(), loc)
assert.True(t, obj.BlankTime.IsZero())
value, ok := c.GetQuery("foo")

48
gin.go
View File

@ -20,9 +20,11 @@ const (
defaultMultipartMemory = 32 << 20 // 32 MB
)
var default404Body = []byte("404 page not found")
var default405Body = []byte("405 method not allowed")
var defaultAppEngine bool
var (
default404Body = []byte("404 page not found")
default405Body = []byte("405 method not allowed")
defaultAppEngine bool
)
type HandlerFunc func(*Context)
type HandlersChain []HandlerFunc
@ -91,6 +93,7 @@ type Engine struct {
// If enabled, the url.RawPath will be used to find parameters.
UseRawPath bool
// If true, the path value will be unescaped.
// If UseRawPath is false (by default), the UnescapePathValues effectively is true,
// as url.Path gonna be used, which is already unescaped.
@ -161,13 +164,16 @@ func (engine *Engine) SecureJsonPrefix(prefix string) *Engine {
}
func (engine *Engine) LoadHTMLGlob(pattern string) {
left := engine.delims.Left
right := engine.delims.Right
if IsDebugging() {
debugPrintLoadTemplate(template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseGlob(pattern)))
debugPrintLoadTemplate(template.Must(template.New("").Delims(left, right).Funcs(engine.FuncMap).ParseGlob(pattern)))
engine.HTMLRender = render.HTMLDebug{Glob: pattern, FuncMap: engine.FuncMap, Delims: engine.delims}
return
}
templ := template.Must(template.New("").Delims(engine.delims.Left, engine.delims.Right).Funcs(engine.FuncMap).ParseGlob(pattern))
templ := template.Must(template.New("").Delims(left, right).Funcs(engine.FuncMap).ParseGlob(pattern))
engine.SetHTMLTemplate(templ)
}
@ -322,12 +328,12 @@ func (engine *Engine) HandleContext(c *Context) {
engine.pool.Put(c)
}
func (engine *Engine) handleHTTPRequest(context *Context) {
httpMethod := context.Request.Method
path := context.Request.URL.Path
func (engine *Engine) handleHTTPRequest(c *Context) {
httpMethod := c.Request.Method
path := c.Request.URL.Path
unescape := false
if engine.UseRawPath && len(context.Request.URL.RawPath) > 0 {
path = context.Request.URL.RawPath
if engine.UseRawPath && len(c.Request.URL.RawPath) > 0 {
path = c.Request.URL.RawPath
unescape = engine.UnescapePathValues
}
@ -337,20 +343,20 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
if t[i].method == httpMethod {
root := t[i].root
// Find route in tree
handlers, params, tsr := root.getValue(path, context.Params, unescape)
handlers, params, tsr := root.getValue(path, c.Params, unescape)
if handlers != nil {
context.handlers = handlers
context.Params = params
context.Next()
context.writermem.WriteHeaderNow()
c.handlers = handlers
c.Params = params
c.Next()
c.writermem.WriteHeaderNow()
return
}
if httpMethod != "CONNECT" && path != "/" {
if tsr && engine.RedirectTrailingSlash {
redirectTrailingSlash(context)
redirectTrailingSlash(c)
return
}
if engine.RedirectFixedPath && redirectFixedPath(context, root, engine.RedirectFixedPath) {
if engine.RedirectFixedPath && redirectFixedPath(c, root, engine.RedirectFixedPath) {
return
}
}
@ -362,15 +368,15 @@ func (engine *Engine) handleHTTPRequest(context *Context) {
for _, tree := range engine.trees {
if tree.method != httpMethod {
if handlers, _, _ := tree.root.getValue(path, nil, unescape); handlers != nil {
context.handlers = engine.allNoMethod
serveError(context, 405, default405Body)
c.handlers = engine.allNoMethod
serveError(c, 405, default405Body)
return
}
}
}
}
context.handlers = engine.allNoRoute
serveError(context, 404, default404Body)
c.handlers = engine.allNoRoute
serveError(c, 404, default404Body)
}
var mimePlain = []string{MIMEPlain}