v0.5 release

This commit is contained in:
Javier Provecho Fernandez 2015-02-07 15:10:43 +01:00
commit 50e7e42730
8 changed files with 62 additions and 42 deletions

View File

@ -9,6 +9,10 @@ List of all the awesome people working to make Gin the best Web Framework in Go.
People and companies, who have contributed, in alphabetical order. People and companies, who have contributed, in alphabetical order.
**@achedeuzot (Klemen Sever)**
- Fix newline debug printing
**@adammck (Adam Mckaig)** **@adammck (Adam Mckaig)**
- Add MIT license - Add MIT license
@ -60,7 +64,7 @@ People and companies, who have contributed, in alphabetical order.
- Fix typo. SetHTTPTemplate -> SetHTMLTemplate - Fix typo. SetHTTPTemplate -> SetHTMLTemplate
**@jammie-stackhouse (Jamie Stackhouse) **@jammie-stackhouse (Jamie Stackhouse)**
- Add more shortcuts for router methods - Add more shortcuts for router methods
@ -72,6 +76,10 @@ People and companies, who have contributed, in alphabetical order.
- Fix typo in comment - Fix typo in comment
**@joiggama (Ignacio Galindo)**
- Add utf-8 charset header on renders
**@julienschmidt (Julien Schmidt)** **@julienschmidt (Julien Schmidt)**
- gofmt the code examples - gofmt the code examples
@ -130,6 +138,10 @@ People and companies, who have contributed, in alphabetical order.
- Fix Port usage in README. - Fix Port usage in README.
**@RobAWilkinson (Robert Wilkinson)**
- Add example of forms and params
**@se77en (Damon Zhao)** **@se77en (Damon Zhao)**
- Improve color logging - Improve color logging
@ -142,7 +154,7 @@ People and companies, who have contributed, in alphabetical order.
- Fixes some texts in README II - Fixes some texts in README II
**@slimmy (Jimmy Pettersson) **@slimmy (Jimmy Pettersson)**
- Added messages for required bindings - Added messages for required bindings
@ -150,6 +162,10 @@ People and companies, who have contributed, in alphabetical order.
- Add support for ignored/unexported fields in binding - Add support for ignored/unexported fields in binding
**@superalsrk (SRK.Lyu)**
- Update httprouter godeps
**@yosssi (Keiji Yoshida)** **@yosssi (Keiji Yoshida)**
- Fix link in README - Fix link in README

View File

@ -1,6 +1,9 @@
#Changelog #Changelog
###Gin 0.5 (Jan 4, 2015) ###Gin 0.6 (Mar 7, 2015)
###Gin 0.5 (Feb 7, 2015)
- [NEW] Content Negotiation - [NEW] Content Negotiation
- [FIX] Solved security bug that allow a client to spoof ip - [FIX] Solved security bug that allow a client to spoof ip

2
Godeps/Godeps.json generated
View File

@ -4,7 +4,7 @@
"Deps": [ "Deps": [
{ {
"ImportPath": "github.com/julienschmidt/httprouter", "ImportPath": "github.com/julienschmidt/httprouter",
"Rev": "aeec11926f7a8fab580383810e1b1bbba99bdaa7" "Rev": "00ce1c6a267162792c367acc43b1681a884e1872"
} }
] ]
} }

View File

@ -1,7 +1,4 @@
#Gin Web Framework #Gin Web Framework [![GoDoc](https://godoc.org/github.com/gin-gonic/gin?status.svg)](https://godoc.org/github.com/gin-gonic/gin) [![Build Status](https://travis-ci.org/gin-gonic/gin.svg)](https://travis-ci.org/gin-gonic/gin)
[![GoDoc](https://godoc.org/github.com/gin-gonic/gin?status.svg)](https://godoc.org/github.com/gin-gonic/gin)
[![Build Status](https://travis-ci.org/gin-gonic/gin.svg)](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 thanks to [httprouter](https://github.com/julienschmidt/httprouter). If you need performance and good productivity, you will love Gin. Gin is a web framework written in Golang. It features a martini-like API with much better performance, up to 40 times faster thanks to [httprouter](https://github.com/julienschmidt/httprouter). If you need performance and good productivity, you will love Gin.
@ -35,24 +32,25 @@ func main() {
##Gin is new, will it be supported? ##Gin is new, will it be supported?
Yes, Gin is an internal project of [my](https://github.com/manucorporat) upcoming startup. We developed it and we are going to continue using and improve it. Yes, Gin is an internal tool of [Manu](https://github.com/manucorporat) and [Javi](https://github.com/javierprovecho) for many of our projects/start-ups. We developed it and we are going to continue using and improve it.
##Roadmap for v1.0 ##Roadmap for v1.0
- [x] Performance improments, reduce allocation and garbage collection overhead
- [x] Fix bugs
- [ ] Stable API
- [ ] Ask our designer for a cool logo - [ ] Ask our designer for a cool logo
- [ ] Add tons of unit tests - [ ] Add tons of unit tests
- [ ] Add internal benchmarks suite - [ ] Add internal benchmarks suite
- [ ] More powerful validation API
- [ ] Improve documentation
- [ ] Add Swagger support
- [x] Stable API
- [x] Improve logging system - [x] Improve logging system
- [x] Improve JSON/XML validation using bindings - [x] Improve JSON/XML validation using bindings
- [x] Improve XML support - [x] Improve XML support
- [x] Flexible rendering system - [x] Flexible rendering system
- [ ] More powerful validation API - [x] Add more cool middlewares, for example redis caching (this also helps developers to understand the framework).
- [ ] Improve documentation
- [X] Add more cool middlewares, for example redis caching (this also helps developers to understand the framework).
- [x] Continuous integration - [x] Continuous integration
- [x] Performance improments, reduce allocation and garbage collection overhead
- [x] Fix bugs
@ -133,7 +131,8 @@ func main() {
c.String(200, message) c.String(200, message)
}) })
// However, this one will match /user/john and also /user/john/send // However, this one will match /user/john/ and also /user/john/send
// If no other routers match /user/john, it will redirect to /user/join/
r.GET("/user/:name/*action", func(c *gin.Context) { r.GET("/user/:name/*action", func(c *gin.Context) {
name := c.Params.ByName("name") name := c.Params.ByName("name")
action := c.Params.ByName("action") action := c.Params.ByName("action")
@ -145,7 +144,25 @@ func main() {
r.Run(":8080") r.Run(":8080")
} }
``` ```
###Form parameters
```go
func main() {
r := gin.Default()
// This will respond to urls like search?firstname=Jane&lastname=Doe
r.GET("/search", func(c *gin.Context) {
// You need to call ParseForm() on the request to receive url and form params first
c.Request.ParseForm()
firstname := c.Request.Form.Get("firstname")
lastname := c.Request.Form.get("lastname")
message := "Hello "+ firstname + lastname
c.String(200, message)
})
r.Run(":8080")
}
```
#### Grouping routes #### Grouping routes
```go ```go
@ -329,22 +346,6 @@ func main() {
Note: this will use `httpNotFound` instead of the Router's `NotFound` handler. Note: this will use `httpNotFound` instead of the Router's `NotFound` handler.
####Serving static files
Use Engine.ServeFiles(path string, root http.FileSystem):
```go
func main() {
r := gin.Default()
r.Static("/assets", "./assets")
// Listen and server on 0.0.0.0:8080
r.Run(":8080")
}
```
Note: this will use `httpNotFound` instead of the Router's `NotFound` handler.
####HTML rendering ####HTML rendering
Using LoadHTMLTemplates() Using LoadHTMLTemplates()

View File

@ -170,7 +170,7 @@ func Validate(obj interface{}, parents ...string) error {
field := typ.Field(i) field := typ.Field(i)
// Allow ignored and unexported fields in the struct // Allow ignored and unexported fields in the struct
if field.Tag.Get("form") == "-" || field.PkgPath != "" { if len(field.PkgPath) > 0 || field.Tag.Get("form") == "-" {
continue continue
} }

View File

@ -76,7 +76,7 @@ func TestContextJSON(t *testing.T) {
t.Errorf("Response should be {\"foo\":\"bar\"}, was: %s", w.Body.String()) t.Errorf("Response should be {\"foo\":\"bar\"}, was: %s", w.Body.String())
} }
if w.HeaderMap.Get("Content-Type") != "application/json" { if w.HeaderMap.Get("Content-Type") != "application/json; charset=utf-8" {
t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type")) t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type"))
} }
} }
@ -103,7 +103,7 @@ func TestContextHTML(t *testing.T) {
t.Errorf("Response should be Hello alexandernyquist, was: %s", w.Body.String()) t.Errorf("Response should be Hello alexandernyquist, was: %s", w.Body.String())
} }
if w.HeaderMap.Get("Content-Type") != "text/html" { if w.HeaderMap.Get("Content-Type") != "text/html; charset=utf-8" {
t.Errorf("Content-Type should be text/html, was %s", w.HeaderMap.Get("Content-Type")) t.Errorf("Content-Type should be text/html, was %s", w.HeaderMap.Get("Content-Type"))
} }
} }
@ -125,7 +125,7 @@ func TestContextString(t *testing.T) {
t.Errorf("Response should be test, was: %s", w.Body.String()) t.Errorf("Response should be test, was: %s", w.Body.String())
} }
if w.HeaderMap.Get("Content-Type") != "text/plain" { if w.HeaderMap.Get("Content-Type") != "text/plain; charset=utf-8" {
t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type")) t.Errorf("Content-Type should be text/plain, was %s", w.HeaderMap.Get("Content-Type"))
} }
} }
@ -147,7 +147,7 @@ func TestContextXML(t *testing.T) {
t.Errorf("Response should be <map><foo>bar</foo></map>, was: %s", w.Body.String()) t.Errorf("Response should be <map><foo>bar</foo></map>, was: %s", w.Body.String())
} }
if w.HeaderMap.Get("Content-Type") != "application/xml" { if w.HeaderMap.Get("Content-Type") != "application/xml; charset=utf-8" {
t.Errorf("Content-Type should be application/xml, was %s", w.HeaderMap.Get("Content-Type")) t.Errorf("Content-Type should be application/xml, was %s", w.HeaderMap.Get("Content-Type"))
} }
} }
@ -336,7 +336,7 @@ func TestBindingJSON(t *testing.T) {
t.Errorf("Response should be {\"parsed\":\"bar\"}, was: %s", w.Body.String()) t.Errorf("Response should be {\"parsed\":\"bar\"}, was: %s", w.Body.String())
} }
if w.HeaderMap.Get("Content-Type") != "application/json" { if w.HeaderMap.Get("Content-Type") != "application/json; charset=utf-8" {
t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type")) t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type"))
} }
} }
@ -369,7 +369,7 @@ func TestBindingJSONEncoding(t *testing.T) {
t.Errorf("Response should be {\"parsed\":\"嘉\"}, was: %s", w.Body.String()) t.Errorf("Response should be {\"parsed\":\"嘉\"}, was: %s", w.Body.String())
} }
if w.HeaderMap.Get("Content-Type") != "application/json" { if w.HeaderMap.Get("Content-Type") != "application/json; charset=utf-8" {
t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type")) t.Errorf("Content-Type should be application/json, was %s", w.HeaderMap.Get("Content-Type"))
} }
} }

4
gin.go
View File

@ -127,7 +127,7 @@ func (engine *Engine) ServeHTTP(writer http.ResponseWriter, request *http.Reques
} }
func (engine *Engine) Run(addr string) error { func (engine *Engine) Run(addr string) error {
debugPrint("Listening and serving HTTP on %s", addr) debugPrint("Listening and serving HTTP on %s\n", addr)
if err := http.ListenAndServe(addr, engine); err != nil { if err := http.ListenAndServe(addr, engine); err != nil {
return err return err
} }
@ -135,7 +135,7 @@ func (engine *Engine) Run(addr string) error {
} }
func (engine *Engine) RunTLS(addr string, cert string, key string) error { func (engine *Engine) RunTLS(addr string, cert string, key string) error {
debugPrint("Listening and serving HTTPS on %s", addr) debugPrint("Listening and serving HTTPS on %s\n", addr)
if err := http.ListenAndServeTLS(addr, cert, key, engine); err != nil { if err := http.ListenAndServeTLS(addr, cert, key, engine); err != nil {
return err return err
} }

View File

@ -50,7 +50,7 @@ var (
) )
func writeHeader(w http.ResponseWriter, code int, contentType string) { func writeHeader(w http.ResponseWriter, code int, contentType string) {
w.Header().Set("Content-Type", contentType) w.Header().Set("Content-Type", contentType+"; charset=utf-8")
w.WriteHeader(code) w.WriteHeader(code)
} }