mirror of
https://github.com/gin-gonic/gin.git
synced 2025-10-15 04:33:40 +08:00
Merge branch 'master' into export_responsewriter_app_engine
* master: Fixes bug when status code is negative Update README.md Updates CHANGELOG and AUTHORS Fixes html debug mode Using test mode Adds TestMode HTML template debug mode. Update README.md Typo in AUTHORS Adds debug mode (part 1) Updates AUTHORS.md Updates CHANGELOG Update README.md
This commit is contained in:
commit
ae4800e50f
22
AUTHORS.md
22
AUTHORS.md
@ -5,7 +5,7 @@ List of all the awesome people working to make Gin the best Web Framework in Go!
|
||||
##gin 0.x series authors
|
||||
|
||||
**Lead Developer:** Manu Martinez-Almeida (@manucorporat)
|
||||
**Stuff:**
|
||||
**Staff:**
|
||||
Javier Provecho (@javierprovecho)
|
||||
|
||||
People and companies, who have contributed, in alphabetical order.
|
||||
@ -22,10 +22,13 @@ People and companies, who have contributed, in alphabetical order.
|
||||
- Using template.Must to fix multiple return issue
|
||||
- ★ Added support for OPTIONS verb
|
||||
- ★ Setting response headers before calling WriteHeader
|
||||
- Improved documentation for model binding
|
||||
- ★ Added Content.Redirect()
|
||||
- ★ Added tons of Unit tests
|
||||
|
||||
|
||||
**@austinheap (Austin Heap)**
|
||||
- Adds travis CI integration
|
||||
- Added travis CI integration
|
||||
|
||||
|
||||
**@bluele (Jun Kimura)**
|
||||
@ -67,20 +70,23 @@ People and companies, who have contributed, in alphabetical order.
|
||||
**@mdigger (Dmitry Sedykh)**
|
||||
- Fixes Form binding when content-type is x-www-form-urlencoded
|
||||
- No repeat call c.Writer.Status() in gin.Logger
|
||||
- Fixed Content-Type for json render
|
||||
- Fixes Content-Type for json render
|
||||
|
||||
|
||||
**@mopemope (Yutaka Matsubara)**
|
||||
- ★ Adds Godep support (Dependencies Manager)
|
||||
- Fix variadic parameter in the flexible render API
|
||||
- Fix Corrupted plain render
|
||||
- Fix variadic parameter in new flexible render API
|
||||
|
||||
|
||||
|
||||
**@msemenistyi (Mykyta Semenistyi)**
|
||||
- update Readme.md. Add code to String method
|
||||
|
||||
|
||||
**@msoedov (Sasha Myasoedov)**
|
||||
- ★ Adds tons of unit tests.
|
||||
|
||||
|
||||
**@ngerakines (Nick Gerakines)**
|
||||
- ★ Improves API, c.GET() doesn't panic
|
||||
- Adds MustGet() method
|
||||
@ -95,4 +101,8 @@ People and companies, who have contributed, in alphabetical order.
|
||||
|
||||
|
||||
**@SkuliOskarsson (Skuli Oskarsson)**
|
||||
- Fixes some texts in README II
|
||||
- Fixes some texts in README II
|
||||
|
||||
|
||||
**@yuyabee**
|
||||
- Fixed README
|
10
CHANGELOG.md
10
CHANGELOG.md
@ -1,6 +1,12 @@
|
||||
##Changelog
|
||||
#Changelog
|
||||
|
||||
###Gin 0.4 (??)
|
||||
###Gin 0.4 (Aug 21, 2014)
|
||||
|
||||
- [NEW] Development mode
|
||||
- [NEW] Unit tests
|
||||
- [NEW] Add Content.Redirect()
|
||||
- [FIX] Deferring WriteHeader()
|
||||
- [FIX] Improved documentation for model binding
|
||||
|
||||
|
||||
###Gin 0.3 (Jul 18, 2014)
|
||||
|
13
README.md
13
README.md
@ -1,6 +1,6 @@
|
||||
#Gin Web Framework
|
||||
|
||||
[](https://godoc.org/github.com/gin-gonic/gin)
|
||||
[](https://godoc.org/github.com/gin-gonic/gin)
|
||||
[](https://travis-ci.org/gin-gonic/gin)
|
||||
|
||||
Gin is a web framework written in Golang. It features a martini-like API with much better performance, up to 40 times faster. If you need performance and good productivity, you will love Gin.
|
||||
@ -324,12 +324,13 @@ func main() {
|
||||
|
||||
Issuing a HTTP redirect is easy:
|
||||
|
||||
```r.GET("/test", func(c *gin.Context) {
|
||||
```go
|
||||
r.GET("/test", func(c *gin.Context) {
|
||||
c.Redirect(301, "http://www.google.com/")
|
||||
})
|
||||
|
||||
Both internal and external locations are supported.
|
||||
```
|
||||
Both internal and external locations are supported.
|
||||
|
||||
|
||||
#### Custom Middlewares
|
||||
|
||||
@ -425,7 +426,7 @@ func main() {
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// note than you are using the copied context "c_cp", IMPORTANT
|
||||
log.Println("Done! in path " + c_cp.Req.URL.Path)
|
||||
log.Println("Done! in path " + c_cp.Request.URL.Path)
|
||||
}()
|
||||
})
|
||||
|
||||
@ -435,7 +436,7 @@ func main() {
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// since we are NOT using a goroutine, we do not have to copy the context
|
||||
log.Println("Done! in path " + c.Req.URL.Path)
|
||||
log.Println("Done! in path " + c.Request.URL.Path)
|
||||
})
|
||||
|
||||
// Listen and server on 0.0.0.0:8080
|
||||
|
28
gin.go
28
gin.go
@ -1,6 +1,7 @@
|
||||
package gin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin/render"
|
||||
"github.com/julienschmidt/httprouter"
|
||||
"html/template"
|
||||
@ -73,13 +74,21 @@ func Default() *Engine {
|
||||
}
|
||||
|
||||
func (engine *Engine) LoadHTMLGlob(pattern string) {
|
||||
templ := template.Must(template.ParseGlob(pattern))
|
||||
engine.SetHTMLTemplate(templ)
|
||||
if gin_mode == debugCode {
|
||||
engine.HTMLRender = render.HTMLDebug
|
||||
} else {
|
||||
templ := template.Must(template.ParseGlob(pattern))
|
||||
engine.SetHTMLTemplate(templ)
|
||||
}
|
||||
}
|
||||
|
||||
func (engine *Engine) LoadHTMLFiles(files ...string) {
|
||||
templ := template.Must(template.ParseFiles(files...))
|
||||
engine.SetHTMLTemplate(templ)
|
||||
if gin_mode == debugCode {
|
||||
engine.HTMLRender = render.HTMLDebug
|
||||
} else {
|
||||
templ := template.Must(template.ParseFiles(files...))
|
||||
engine.SetHTMLTemplate(templ)
|
||||
}
|
||||
}
|
||||
|
||||
func (engine *Engine) SetHTMLTemplate(templ *template.Template) {
|
||||
@ -105,12 +114,18 @@ func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
}
|
||||
|
||||
func (engine *Engine) Run(addr string) {
|
||||
if gin_mode == debugCode {
|
||||
fmt.Println("[GIN-debug] Listening and serving HTTP on " + addr)
|
||||
}
|
||||
if err := http.ListenAndServe(addr, engine); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (engine *Engine) RunTLS(addr string, cert string, key string) {
|
||||
if gin_mode == debugCode {
|
||||
fmt.Println("[GIN-debug] Listening and serving HTTPS on " + addr)
|
||||
}
|
||||
if err := http.ListenAndServeTLS(addr, cert, key, engine); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -160,6 +175,11 @@ func (group *RouterGroup) pathFor(p string) string {
|
||||
func (group *RouterGroup) Handle(method, p string, handlers []HandlerFunc) {
|
||||
p = group.pathFor(p)
|
||||
handlers = group.combineHandlers(handlers)
|
||||
if gin_mode == debugCode {
|
||||
nuHandlers := len(handlers)
|
||||
name := funcName(handlers[nuHandlers-1])
|
||||
fmt.Printf("[GIN-debug] %-5s %-25s --> %s (%d handlers)\n", method, p, name, nuHandlers)
|
||||
}
|
||||
group.engine.router.Handle(method, p, func(w http.ResponseWriter, req *http.Request, params httprouter.Params) {
|
||||
c := group.engine.createContext(w, req, params, handlers)
|
||||
c.Next()
|
||||
|
@ -10,6 +10,10 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func init() {
|
||||
SetMode(TestMode)
|
||||
}
|
||||
|
||||
func PerformRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
|
||||
req, _ := http.NewRequest(method, path, nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
42
mode.go
Normal file
42
mode.go
Normal file
@ -0,0 +1,42 @@
|
||||
package gin
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
const GIN_MODE = "GIN_MODE"
|
||||
|
||||
const (
|
||||
DebugMode string = "debug"
|
||||
ReleaseMode string = "release"
|
||||
TestMode string = "test"
|
||||
)
|
||||
const (
|
||||
debugCode = iota
|
||||
releaseCode = iota
|
||||
testCode = iota
|
||||
)
|
||||
|
||||
var gin_mode int = debugCode
|
||||
|
||||
func SetMode(value string) {
|
||||
switch value {
|
||||
case DebugMode:
|
||||
gin_mode = debugCode
|
||||
case ReleaseMode:
|
||||
gin_mode = releaseCode
|
||||
case TestMode:
|
||||
gin_mode = testCode
|
||||
default:
|
||||
panic("gin mode unknown, the allowed modes are: " + DebugMode + " and " + ReleaseMode)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
value := os.Getenv(GIN_MODE)
|
||||
if len(value) == 0 {
|
||||
SetMode(DebugMode)
|
||||
} else {
|
||||
SetMode(value)
|
||||
}
|
||||
}
|
@ -25,6 +25,9 @@ type (
|
||||
// Redirects
|
||||
redirectRender struct{}
|
||||
|
||||
// Redirects
|
||||
htmlDebugRender struct{}
|
||||
|
||||
// form binding
|
||||
HTMLRender struct {
|
||||
Template *template.Template
|
||||
@ -32,10 +35,11 @@ type (
|
||||
)
|
||||
|
||||
var (
|
||||
JSON = jsonRender{}
|
||||
XML = xmlRender{}
|
||||
Plain = plainRender{}
|
||||
Redirect = redirectRender{}
|
||||
JSON = jsonRender{}
|
||||
XML = xmlRender{}
|
||||
Plain = plainRender{}
|
||||
Redirect = redirectRender{}
|
||||
HTMLDebug = htmlDebugRender{}
|
||||
)
|
||||
|
||||
func writeHeader(w http.ResponseWriter, code int, contentType string) {
|
||||
@ -61,13 +65,6 @@ func (_ xmlRender) Render(w http.ResponseWriter, code int, data ...interface{})
|
||||
return encoder.Encode(data[0])
|
||||
}
|
||||
|
||||
func (html HTMLRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
|
||||
writeHeader(w, code, "text/html")
|
||||
file := data[0].(string)
|
||||
obj := data[1]
|
||||
return html.Template.ExecuteTemplate(w, file, obj)
|
||||
}
|
||||
|
||||
func (_ plainRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
|
||||
writeHeader(w, code, "text/plain")
|
||||
format := data[0].(string)
|
||||
@ -80,3 +77,21 @@ func (_ plainRender) Render(w http.ResponseWriter, code int, data ...interface{}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (_ htmlDebugRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
|
||||
writeHeader(w, code, "text/html")
|
||||
file := data[0].(string)
|
||||
obj := data[1]
|
||||
t, err := template.ParseFiles(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return t.ExecuteTemplate(w, file, obj)
|
||||
}
|
||||
|
||||
func (html HTMLRender) Render(w http.ResponseWriter, code int, data ...interface{}) error {
|
||||
writeHeader(w, code, "text/html")
|
||||
file := data[0].(string)
|
||||
obj := data[1]
|
||||
return html.Template.ExecuteTemplate(w, file, obj)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func (w *responseWriter) reset(writer http.ResponseWriter) {
|
||||
}
|
||||
|
||||
func (w *responseWriter) WriteHeader(code int) {
|
||||
if code != 0 {
|
||||
if code > 0 {
|
||||
w.status = code
|
||||
if w.written {
|
||||
log.Println("[GIN] WARNING. Headers were already written!")
|
||||
|
6
utils.go
6
utils.go
@ -2,6 +2,8 @@ package gin
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"reflect"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
type H map[string]interface{}
|
||||
@ -38,3 +40,7 @@ func filterFlags(content string) string {
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
func funcName(f interface{}) string {
|
||||
return runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user