diff --git a/admin.go b/admin.go index fa4b1db0..ddc936ef 100644 --- a/admin.go +++ b/admin.go @@ -107,7 +107,7 @@ func listConf(rw http.ResponseWriter, r *http.Request) { m["SessionGCMaxLifetime"] = SessionGCMaxLifetime m["SessionProviderConfig"] = SessionProviderConfig m["SessionCookieLifeTime"] = SessionCookieLifeTime - m["EnabelFcgi"] = EnabelFcgi + m["EnableFcgi"] = EnableFcgi m["MaxMemory"] = MaxMemory m["EnableGzip"] = EnableGzip m["DirectoryIndex"] = DirectoryIndex diff --git a/app.go b/app.go index d10d436c..ed57b978 100644 --- a/app.go +++ b/app.go @@ -64,7 +64,7 @@ func (app *App) Run() { ) endRunning := make(chan bool, 1) - if EnabelFcgi { + if EnableFcgi { if EnableStdIo { err = fcgi.Serve(nil, app.Handlers) // standard I/O if err == nil { @@ -89,6 +89,7 @@ func (app *App) Run() { } } else { if Graceful { + httpsAddr := addr app.Server.Addr = addr app.Server.Handler = app.Handlers app.Server.ReadTimeout = time.Duration(HTTPServerTimeOut) * time.Second @@ -97,11 +98,12 @@ func (app *App) Run() { go func() { time.Sleep(20 * time.Microsecond) if HTTPSPort != 0 { - addr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPSPort) - app.Server.Addr = addr + httpsAddr = fmt.Sprintf("%s:%d", HTTPAddr, HTTPSPort) + app.Server.Addr = httpsAddr } - server := grace.NewServer(addr, app.Handlers) - server.Server = app.Server + server := grace.NewServer(httpsAddr, app.Handlers) + server.Server.ReadTimeout = app.Server.ReadTimeout + server.Server.WriteTimeout = app.Server.WriteTimeout err := server.ListenAndServeTLS(HTTPCertFile, HTTPKeyFile) if err != nil { BeeLogger.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid())) @@ -113,8 +115,9 @@ func (app *App) Run() { if EnableHTTPListen { go func() { server := grace.NewServer(addr, app.Handlers) - server.Server = app.Server - if ListenTCP4 && HTTPAddr == "" { + server.Server.ReadTimeout = app.Server.ReadTimeout + server.Server.WriteTimeout = app.Server.WriteTimeout + if ListenTCP4 { server.Network = "tcp4" } err := server.ListenAndServe() @@ -151,7 +154,7 @@ func (app *App) Run() { go func() { app.Server.Addr = addr BeeLogger.Info("http server Running on %s", app.Server.Addr) - if ListenTCP4 && HTTPAddr == "" { + if ListenTCP4 { ln, err := net.Listen("tcp4", app.Server.Addr) if err != nil { BeeLogger.Critical("ListenAndServe: ", err) diff --git a/config.go b/config.go index c2f23f67..d9ff624c 100644 --- a/config.go +++ b/config.go @@ -60,15 +60,15 @@ var ( EnableDocs bool // EnableErrorsShow wheather show errors in page. if true, show error and trace info in page rendered with error template. EnableErrorsShow bool - // EnabelFcgi turn on the fcgi Listen, default is false - EnabelFcgi bool + // EnableFcgi turn on the fcgi Listen, default is false + EnableFcgi bool // EnableGzip means gzip the response EnableGzip bool // EnableHTTPListen represent whether turn on the HTTP, default is true EnableHTTPListen bool // EnableHTTPTLS represent whether turn on the HTTPS, default is true EnableHTTPTLS bool - // EnableStdIo works with EnabelFcgi Use FCGI via standard I/O + // EnableStdIo works with EnableFcgi Use FCGI via standard I/O EnableStdIo bool // EnableXSRF whether turn on xsrf. default is false EnableXSRF bool @@ -435,8 +435,8 @@ func ParseConfig() (err error) { SessionCookieLifeTime = sesscookielifetime } - if enabelFcgi, err := AppConfig.Bool("EnabelFcgi"); err == nil { - EnabelFcgi = enabelFcgi + if enableFcgi, err := AppConfig.Bool("EnableFcgi"); err == nil { + EnableFcgi = enableFcgi } if enablegzip, err := AppConfig.Bool("EnableGzip"); err == nil { @@ -529,7 +529,6 @@ func ParseConfig() (err error) { if ext == "" { continue } - ext = strings.ToLower(ext) if !strings.HasPrefix(ext, ".") { ext = "." + ext } diff --git a/context/context.go b/context/context.go index fb9c6d96..8f1144f3 100644 --- a/context/context.go +++ b/context/context.go @@ -55,7 +55,6 @@ func (ctx *Context) Redirect(status int, localurl string) { // Abort stops this request. // if beego.ErrorMaps exists, panic body. func (ctx *Context) Abort(status int, body string) { - ctx.ResponseWriter.WriteHeader(status) panic(body) } diff --git a/context/output.go b/context/output.go index a4bb3d09..d132e392 100644 --- a/context/output.go +++ b/context/output.go @@ -103,7 +103,19 @@ func (output *BeegoOutput) Cookie(name string, value string, others ...interface //fix cookie not work in IE if len(others) > 0 { switch v := others[0].(type) { - case int, int32, int64: + case int: + if v > 0 { + fmt.Fprintf(&b, "; Expires=%s; Max-Age=%d", time.Now().Add(time.Duration(v)*time.Second).UTC().Format(time.RFC1123), v) + } else if v <= 0 { + fmt.Fprintf(&b, "; Max-Age=0") + } + case int64: + if v > 0 { + fmt.Fprintf(&b, "; Expires=%s; Max-Age=%d", time.Now().Add(time.Duration(v)*time.Second).UTC().Format(time.RFC1123), v) + } else if v <= 0 { + fmt.Fprintf(&b, "; Max-Age=0") + } + case int32: if v > 0 { fmt.Fprintf(&b, "; Expires=%s; Max-Age=%d", time.Now().Add(time.Duration(v)*time.Second).UTC().Format(time.RFC1123), v) } else if v <= 0 { diff --git a/controller.go b/controller.go index 7fbf6dc5..0750daf4 100644 --- a/controller.go +++ b/controller.go @@ -647,8 +647,8 @@ func (c *Controller) CheckXSRFCookie() bool { // XSRFFormHTML writes an input field contains xsrf token value. func (c *Controller) XSRFFormHTML() string { - return "" + return `` } // GetControllerAndAction gets the executing controller name and action name. diff --git a/memzipfile.go b/memzipfile.go index 1e5239f5..376a1ae9 100644 --- a/memzipfile.go +++ b/memzipfile.go @@ -219,9 +219,9 @@ func getAcceptEncodingZip(r *http.Request) string { ss = strings.ToLower(ss) if strings.Contains(ss, "gzip") { return "gzip" - } - if strings.Contains(ss, "deflate") { + } else if strings.Contains(ss, "deflate") { return "deflate" + } else { + return "" } - return "" } diff --git a/orm/cmd_utils.go b/orm/cmd_utils.go index 5b40fd07..bddada7c 100644 --- a/orm/cmd_utils.go +++ b/orm/cmd_utils.go @@ -45,13 +45,14 @@ func getDbDropSQL(al *alias) (sqls []string) { func getColumnTyp(al *alias, fi *fieldInfo) (col string) { T := al.DbBaser.DbTypes() fieldType := fi.fieldType + fieldSize := fi.size checkColumn: switch fieldType { case TypeBooleanField: col = T["bool"] case TypeCharField: - col = fmt.Sprintf(T["string"], fi.size) + col = fmt.Sprintf(T["string"], fieldSize) case TypeTextField: col = T["string-text"] case TypeDateField: @@ -89,6 +90,7 @@ checkColumn: } case RelForeignKey, RelOneToOne: fieldType = fi.relModelInfo.fields.pk.fieldType + fieldSize = fi.relModelInfo.fields.pk.size goto checkColumn } diff --git a/orm/db.go b/orm/db.go index 2f2c52da..b62c165b 100644 --- a/orm/db.go +++ b/orm/db.go @@ -488,7 +488,8 @@ func (d *dbBase) Update(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time. d.ins.ReplaceMarks(&query) - if res, err := q.Exec(query, setValues...); err == nil { + res, err := q.Exec(query, setValues...) + if err == nil { return res.RowsAffected() } return 0, err diff --git a/orm/models_boot.go b/orm/models_boot.go index 808b7822..3690557b 100644 --- a/orm/models_boot.go +++ b/orm/models_boot.go @@ -266,7 +266,10 @@ func bootStrap() { if found == false { mForC: for _, ffi := range fi.relModelInfo.fields.fieldsByType[RelManyToMany] { - if ffi.relModelInfo == mi { + conditions := fi.relThrough != "" && fi.relThrough == ffi.relThrough || + fi.relTable != "" && fi.relTable == ffi.relTable || + fi.relThrough == "" && fi.relTable == "" + if ffi.relModelInfo == mi && conditions { found = true fi.reverseField = ffi.reverseFieldInfoTwo.name diff --git a/orm/models_info_f.go b/orm/models_info_f.go index 66dcc23a..14e1f2c6 100644 --- a/orm/models_info_f.go +++ b/orm/models_info_f.go @@ -223,6 +223,11 @@ checkType: break checkType case "many": fieldType = RelReverseMany + if tv := tags["rel_table"]; tv != "" { + fi.relTable = tv + } else if tv := tags["rel_through"]; tv != "" { + fi.relThrough = tv + } break checkType default: err = fmt.Errorf("error") diff --git a/router.go b/router.go index c0a50988..1e8144bf 100644 --- a/router.go +++ b/router.go @@ -15,10 +15,7 @@ package beego import ( - "bufio" - "errors" "fmt" - "net" "net/http" "os" "path" @@ -353,7 +350,7 @@ func (p *ControllerRegister) Handler(pattern string, h http.Handler, options ... route.handler = h if len(options) > 0 { if _, ok := options[0].(bool); ok { - pattern = path.Join(pattern, "?:all") + pattern = path.Join(pattern, "?:all(.*)") } } for _, m := range HTTPMETHOD { @@ -581,7 +578,7 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request) var runMethod string var routerInfo *controllerInfo - w := &responseWriter{writer: rw} + w := &responseWriter{rw, false, 0} if RunMode == "dev" { w.Header().Set("Server", BeegoServerName) @@ -856,7 +853,7 @@ Admin: // Call WriteHeader if status code has been set changed if context.Output.Status != 0 { - w.writer.WriteHeader(context.Output.Status) + w.WriteHeader(context.Output.Status) } } @@ -895,14 +892,14 @@ func (p *ControllerRegister) recoverPanic(context *beecontext.Context) { //responseWriter is a wrapper for the http.ResponseWriter //started set to true if response was written to then don't execute other handler type responseWriter struct { - writer http.ResponseWriter + http.ResponseWriter started bool status int } // Header returns the header map that will be sent by WriteHeader. func (w *responseWriter) Header() http.Header { - return w.writer.Header() + return w.ResponseWriter.Header() } // Write writes the data to the connection as part of an HTTP reply, @@ -910,7 +907,7 @@ func (w *responseWriter) Header() http.Header { // started means the response has sent out. func (w *responseWriter) Write(p []byte) (int, error) { w.started = true - return w.writer.Write(p) + return w.ResponseWriter.Write(p) } // WriteHeader sends an HTTP response header with status code, @@ -918,23 +915,7 @@ func (w *responseWriter) Write(p []byte) (int, error) { func (w *responseWriter) WriteHeader(code int) { w.status = code w.started = true - w.writer.WriteHeader(code) -} - -// hijacker for http -func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { - hj, ok := w.writer.(http.Hijacker) - if !ok { - return nil, nil, errors.New("webserver doesn't support hijacking") - } - return hj.Hijack() -} - -func (w *responseWriter) Flush() { - f, ok := w.writer.(http.Flusher) - if ok { - f.Flush() - } + w.ResponseWriter.WriteHeader(code) } func tourl(params map[string]string) string { diff --git a/router_test.go b/router_test.go index c6ec9c92..9598f99c 100644 --- a/router_test.go +++ b/router_test.go @@ -333,6 +333,18 @@ func TestRouterHandler(t *testing.T) { } } +func TestRouterHandlerAll(t *testing.T) { + r, _ := http.NewRequest("POST", "/sayhi/a/b/c", nil) + w := httptest.NewRecorder() + + handler := NewControllerRegister() + handler.Handler("/sayhi", http.HandlerFunc(sayhello), true) + handler.ServeHTTP(w, r) + if w.Body.String() != "sayhello" { + t.Errorf("TestRouterHandler can't run") + } +} + // // Benchmarks NewApp: // diff --git a/staticfile.go b/staticfile.go index e1fc4f73..de530b0c 100644 --- a/staticfile.go +++ b/staticfile.go @@ -96,9 +96,8 @@ func serverStaticRouter(ctx *context.Context) { } isStaticFileToCompress := false - lowerFileName := strings.ToLower(filePath) for _, statExtension := range StaticExtensionsToGzip { - if strings.HasSuffix(lowerFileName, statExtension) { + if strings.HasSuffix(strings.ToLower(filePath), strings.ToLower(statExtension)) { isStaticFileToCompress = true break } diff --git a/validation/validators.go b/validation/validators.go index ec1545fb..2662b701 100644 --- a/validation/validators.go +++ b/validation/validators.go @@ -74,6 +74,33 @@ func (r Required) IsSatisfied(obj interface{}) bool { if i, ok := obj.(int); ok { return i != 0 } + if i, ok := obj.(uint); ok { + return i != 0 + } + if i, ok := obj.(int8); ok { + return i != 0 + } + if i, ok := obj.(uint8); ok { + return i != 0 + } + if i, ok := obj.(int16); ok { + return i != 0 + } + if i, ok := obj.(uint16); ok { + return i != 0 + } + if i, ok := obj.(uint32); ok { + return i != 0 + } + if i, ok := obj.(int32); ok { + return i != 0 + } + if i, ok := obj.(int64); ok { + return i != 0 + } + if i, ok := obj.(uint64); ok { + return i != 0 + } if t, ok := obj.(time.Time); ok { return !t.IsZero() }