diff --git a/context.go b/context.go index c7beed9e4..7b528546d 100644 --- a/context.go +++ b/context.go @@ -11,6 +11,7 @@ import ( "net/url" "golang.org/x/net/websocket" + "bytes" ) type ( @@ -110,68 +111,99 @@ func (c *Context) Bind(i interface{}) error { // Render renders a template with data and sends a text/html response with status // code. Templates can be registered using `Echo.SetRenderer()`. -func (c *Context) Render(code int, name string, data interface{}) error { +func (c *Context) Render(code int, name string, data interface{}) (err error) { if c.echo.renderer == nil { return RendererNotRegistered } + buf := new (bytes.Buffer) + if err = c.echo.renderer.Render(buf, name, data); err != nil { + return + } c.response.Header().Set(ContentType, TextHTMLCharsetUTF8) c.response.WriteHeader(code) - return c.echo.renderer.Render(c.response, name, data) + c.response.Write(buf.Bytes()) + return } // HTML formats according to a format specifier and sends HTML response with // status code. func (c *Context) HTML(code int, format string, a ...interface{}) (err error) { + buf := new(bytes.Buffer) + _, err = fmt.Fprintf(buf, format, a...) + if err != nil { + return err + } c.response.Header().Set(ContentType, TextHTMLCharsetUTF8) c.response.WriteHeader(code) - _, err = fmt.Fprintf(c.response, format, a...) + c.response.Write(buf.Bytes()) return } // String formats according to a format specifier and sends text response with status // code. func (c *Context) String(code int, format string, a ...interface{}) (err error) { + buf := new(bytes.Buffer) + _, err = fmt.Fprintf(buf, format, a...) + if err != nil { + return err + } c.response.Header().Set(ContentType, TextPlain) c.response.WriteHeader(code) - _, err = fmt.Fprintf(c.response, format, a...) + c.response.Write(buf.Bytes()) return } // JSON sends a JSON response with status code. -func (c *Context) JSON(code int, i interface{}) error { +func (c *Context) JSON(code int, i interface{}) (err error) { + b, err := json.Marshal(i) + if err != nil { + return err + } c.response.Header().Set(ContentType, ApplicationJSONCharsetUTF8) c.response.WriteHeader(code) - return json.NewEncoder(c.response).Encode(i) + c.response.Write(b) + return } // JSONP sends a JSONP response with status code. It uses `callback` to construct // the JSONP payload. func (c *Context) JSONP(code int, callback string, i interface{}) (err error) { + b, err := json.Marshal(i) + if err != nil { + return err + } c.response.Header().Set(ContentType, ApplicationJavaScriptCharsetUTF8) c.response.WriteHeader(code) c.response.Write([]byte(callback + "(")) - if err = json.NewEncoder(c.response).Encode(i); err == nil { - c.response.Write([]byte(");")) - } + c.response.Write(b) + c.response.Write([]byte(");")) return } // XML sends an XML response with status code. -func (c *Context) XML(code int, i interface{}) error { +func (c *Context) XML(code int, i interface{}) (err error) { + b, err := xml.Marshal(i) + if err != nil { + return err + } c.response.Header().Set(ContentType, ApplicationXMLCharsetUTF8) c.response.WriteHeader(code) c.response.Write([]byte(xml.Header)) - return xml.NewEncoder(c.response).Encode(i) + c.response.Write(b) + return } // File sends a response with the content of the file. If attachment is true, the // client is prompted to save the file. -func (c *Context) File(name string, attachment bool) error { +func (c *Context) File(name string, attachment bool) (err error) { dir, file := path.Split(name) if attachment { c.response.Header().Set(ContentDisposition, "attachment; filename="+file) } - return serveFile(dir, file, c) + if err = serveFile(dir, file, c); err != nil { + c.response.Header().Del(ContentDisposition) + } + return } // NoContent sends a response with no body and a status code. diff --git a/context_test.go b/context_test.go index 77e4b7d8f..8d9becaff 100644 --- a/context_test.go +++ b/context_test.go @@ -94,7 +94,7 @@ func TestContext(t *testing.T) { if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, ApplicationJSONCharsetUTF8, rec.Header().Get(ContentType)) - assert.Equal(t, userJSON+"\n", rec.Body.String()) + assert.Equal(t, userJSON, rec.Body.String()) } // JSONP @@ -105,7 +105,7 @@ func TestContext(t *testing.T) { if assert.NoError(t, err) { assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, ApplicationJavaScriptCharsetUTF8, rec.Header().Get(ContentType)) - assert.Equal(t, callback+"("+userJSON+"\n);", rec.Body.String()) + assert.Equal(t, callback+"("+userJSON+");", rec.Body.String()) } // XML diff --git a/website/config.json b/website/config.json index 0c6995317..f72e384d6 100644 --- a/website/config.json +++ b/website/config.json @@ -6,13 +6,13 @@ "menu": { "main": [{ "Name": "Guide", - "Pre": "", + "Pre": "", "Weight": -110, "Identifier": "guide", "URL": "guide" }, { "Name": "Recipes", - "Pre": "", + "Pre": "", "Weight": -100, "Identifier": "recipes", "URL": "recipes" diff --git a/website/content/guide/customization.md b/website/content/guide/customization.md index 8e37851f8..24b04fe4a 100644 --- a/website/content/guide/customization.md +++ b/website/content/guide/customization.md @@ -3,6 +3,7 @@ title: Customization menu: main: parent: guide + weight: 20 --- ### HTTP error handler diff --git a/website/content/guide/error-handling.md b/website/content/guide/error-handling.md index b409a5dfe..273e0796f 100644 --- a/website/content/guide/error-handling.md +++ b/website/content/guide/error-handling.md @@ -3,6 +3,7 @@ title: Error Handling menu: main: parent: guide + weight: 70 --- Echo advocates centralized HTTP error handling by returning `error` from middleware diff --git a/website/content/guide/installation.md b/website/content/guide/installation.md index 06427bd11..0711b790a 100644 --- a/website/content/guide/installation.md +++ b/website/content/guide/installation.md @@ -3,6 +3,7 @@ title: Installation menu: main: parent: guide + weight: 10 --- Echo has been developed and tested using Go `1.4.x` diff --git a/website/content/guide/middleware.md b/website/content/guide/middleware.md index 2dece0cc7..f0df11e01 100644 --- a/website/content/guide/middleware.md +++ b/website/content/guide/middleware.md @@ -3,6 +3,7 @@ title: Middleware menu: main: parent: guide + weight: 40 --- Middleware is a function which is chained in the HTTP request-response cycle. Middleware diff --git a/website/content/guide/request.md b/website/content/guide/request.md index 9453ce3ea..92d4849f0 100644 --- a/website/content/guide/request.md +++ b/website/content/guide/request.md @@ -3,6 +3,7 @@ title: Request menu: main: parent: guide + weight: 50 --- ### Path parameter diff --git a/website/content/guide/response.md b/website/content/guide/response.md index 74658d011..a795a8df3 100644 --- a/website/content/guide/response.md +++ b/website/content/guide/response.md @@ -3,6 +3,7 @@ title: Response menu: main: parent: guide + weight: 60 --- ### Template diff --git a/website/content/guide/routing.md b/website/content/guide/routing.md index 8b16053cc..c6ea13996 100644 --- a/website/content/guide/routing.md +++ b/website/content/guide/routing.md @@ -3,6 +3,7 @@ title: Routing menu: main: parent: guide + weight: 30 --- Echo's router is [fast, optimized](https://github.com/labstack/echo#benchmark) and diff --git a/website/content/recipes/google-app-engine.md b/website/content/recipes/google-app-engine.md index 5e88c9acc..fe0d3f82e 100644 --- a/website/content/recipes/google-app-engine.md +++ b/website/content/recipes/google-app-engine.md @@ -1,5 +1,6 @@ --- title: Google App Engine +draft: true menu: main: parent: recipes diff --git a/website/layouts/partials/head.html b/website/layouts/partials/head.html index d73fbca43..46c14b986 100644 --- a/website/layouts/partials/head.html +++ b/website/layouts/partials/head.html @@ -14,6 +14,7 @@ + diff --git a/website/layouts/partials/menu.html b/website/layouts/partials/menu.html index 5d658b251..a0219a73d 100644 --- a/website/layouts/partials/menu.html +++ b/website/layouts/partials/menu.html @@ -2,9 +2,14 @@
{{ range .Site.Menus.main }} {{ if .HasChildren }} -

{{ .Name }}

+

+ {{ .Pre }} + {{ .Name }} +

{{ range .Children }} - {{ .Name }} + + {{ .Name }} + {{ end }} {{ end }} {{ end }} diff --git a/website/package.json b/website/package.json index 6b02b37a5..ef6b8bb86 100644 --- a/website/package.json +++ b/website/package.json @@ -1,7 +1,10 @@ { - "devDependencies": { - "gulp": "^3.8.11", - "gulp-gh-pages": "^0.5.1", - "gulp-shell": "^0.4.1" - } + "devDependencies": { + "gulp": "^3.8.11", + "gulp-gh-pages": "^0.5.1", + "gulp-shell": "^0.4.1" + }, + "dependencies": { + "prismjs": "0.0.1" + } } diff --git a/website/static/styles/echo.css b/website/static/styles/echo.css index f0e50ad44..49b8688db 100644 --- a/website/static/styles/echo.css +++ b/website/static/styles/echo.css @@ -1,25 +1,24 @@ -body { - background-color: #efefef; -} - footer { padding: 40px 80px !important; } - +code { + font-size: .95em; + padding: 2px 4px; + background: #eee; + color: #4d4d4c; + font-family: Source Code Pro, Monaco, Menlo, Consolas, monospace; +} a:link { text-decoration: none; } - .page-content { padding: 20px 0; max-width: 960px; margin: auto; } - .page-content header { padding-bottom: 16px; } - .menu a { display: block; padding: 2px 0