mirror of
https://github.com/labstack/echo.git
synced 2025-06-15 00:14:57 +02:00
Add recipes section in docs
Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
16
context.go
16
context.go
@ -4,6 +4,8 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"golang.org/x/net/websocket"
|
"golang.org/x/net/websocket"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -103,19 +105,21 @@ func (c *Context) JSON(code int, i interface{}) error {
|
|||||||
return json.NewEncoder(c.response).Encode(i)
|
return json.NewEncoder(c.response).Encode(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// String sends a text/plain response with status code.
|
// String formats according to a format specifier and sends text/plain response
|
||||||
func (c *Context) String(code int, s string) error {
|
// with status code.
|
||||||
|
func (c *Context) String(code int, format string, a ...interface{}) error {
|
||||||
c.response.Header().Set(ContentType, TextPlain)
|
c.response.Header().Set(ContentType, TextPlain)
|
||||||
c.response.WriteHeader(code)
|
c.response.WriteHeader(code)
|
||||||
_, err := c.response.Write([]byte(s))
|
_, err := fmt.Fprintf(c.response, format, a...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTML sends a text/html response with status code.
|
// HTML formats according to a format specifier and sends text/html response with
|
||||||
func (c *Context) HTML(code int, html string) error {
|
// status code.
|
||||||
|
func (c *Context) HTML(code int, format string, a ...interface{}) error {
|
||||||
c.response.Header().Set(ContentType, TextHTML)
|
c.response.Header().Set(ContentType, TextHTML)
|
||||||
c.response.WriteHeader(code)
|
c.response.WriteHeader(code)
|
||||||
_, err := c.response.Write([]byte(html))
|
_, err := fmt.Fprintf(c.response, format, a...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
recipes/file-upload/public/index.html
Normal file
16
recipes/file-upload/public/index.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Multipart File Upload</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Upload Files</h1>
|
||||||
|
<form action="/upload" method=post enctype=multipart/form-data>
|
||||||
|
Name: <input type="text" name="name"><br>
|
||||||
|
Email: <input type="email" name="email"><br>
|
||||||
|
Files: <input type="file" name="files" multiple><br><br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
51
recipes/file-upload/server.go
Normal file
51
recipes/file-upload/server.go
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func upload(c *echo.Context) error {
|
||||||
|
req := c.Request()
|
||||||
|
|
||||||
|
// req.ParseMultipartForm(16 << 20) // Max memory 16 MiB
|
||||||
|
|
||||||
|
// Read form fields
|
||||||
|
name := req.FormValue("name")
|
||||||
|
email := req.FormValue("email")
|
||||||
|
|
||||||
|
// Read files
|
||||||
|
files := req.MultipartForm.File["files"]
|
||||||
|
for _, f := range(files) {
|
||||||
|
// Source file
|
||||||
|
src, err := f.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
// Destination file
|
||||||
|
dst, err := os.Create(f.Filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dst.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(dst, src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c.String(http.StatusOK, "Thank You! %s <%s>, %d files uploaded successfully.",
|
||||||
|
name, email, len(files))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
e := echo.New()
|
||||||
|
e.Index("public/index.html")
|
||||||
|
e.Post("/upload", upload)
|
||||||
|
e.Run(":1323")
|
||||||
|
}
|
@ -11,10 +11,8 @@ func main() {
|
|||||||
// Setup
|
// Setup
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.Get("/", func(c *echo.Context) error {
|
e.Get("/", func(c *echo.Context) error {
|
||||||
c.String(http.StatusOK, "Six sick bricks tick")
|
return c.String(http.StatusOK, "Six sick bricks tick")
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Use github.com/facebookgo/grace/gracehttp
|
|
||||||
gracehttp.Serve(e.Server(":1323"))
|
gracehttp.Serve(e.Server(":1323"))
|
||||||
}
|
}
|
@ -12,10 +12,8 @@ func main() {
|
|||||||
// Setup
|
// Setup
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
e.Get("/", func(c *echo.Context) error {
|
e.Get("/", func(c *echo.Context) error {
|
||||||
c.String(http.StatusOK, "Sue sews rose on slow jor crows nose")
|
return c.String(http.StatusOK, "Sue sews rose on slow jor crows nose")
|
||||||
return nil
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Use github.com/tylerb/graceful
|
|
||||||
graceful.ListenAndServe(e.Server(":1323"), 5*time.Second)
|
graceful.ListenAndServe(e.Server(":1323"), 5*time.Second)
|
||||||
}
|
}
|
77
recipes/streaming-file-upload/server.go
Normal file
77
recipes/streaming-file-upload/server.go
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func upload(c *echo.Context) error {
|
||||||
|
mr, err := c.Request().MultipartReader()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read form field `name`
|
||||||
|
part, err := mr.NextPart()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer part.Close()
|
||||||
|
b, err := ioutil.ReadAll(part)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
name := string(b)
|
||||||
|
|
||||||
|
// Read form field `email`
|
||||||
|
part, err = mr.NextPart()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer part.Close()
|
||||||
|
b, err = ioutil.ReadAll(part)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
email := string(b)
|
||||||
|
|
||||||
|
println(name, email)
|
||||||
|
|
||||||
|
// Read files
|
||||||
|
i := 0
|
||||||
|
for {
|
||||||
|
part, err := mr.NextPart()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer part.Close()
|
||||||
|
|
||||||
|
file, err := os.Create(part.FileName())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if _, err := io.Copy(file, part); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return c.String(http.StatusOK, "Thank You! %s <%s>, %d files uploaded successfully.",
|
||||||
|
name, email, i)
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
e := echo.New()
|
||||||
|
e.SetDebug(true)
|
||||||
|
e.Index("../file-upload/public/index.html")
|
||||||
|
e.Post("/upload", upload)
|
||||||
|
e.Run(":1323")
|
||||||
|
}
|
@ -49,7 +49,7 @@ Enables debug mode.
|
|||||||
## Routing
|
## Routing
|
||||||
|
|
||||||
Echo's router is [fast, optimized](https://github.com/labstack/echo#benchmark) and
|
Echo's router is [fast, optimized](https://github.com/labstack/echo#benchmark) and
|
||||||
flexible. It's based on [redix tree](http://en.wikipedia.org/wiki/Radix_tree)
|
flexible. It's based on [radix tree](http://en.wikipedia.org/wiki/Radix_tree)
|
||||||
data structure which makes routing lookup really fast. It leverages
|
data structure which makes routing lookup really fast. It leverages
|
||||||
[sync pool](https://golang.org/pkg/sync/#Pool) to reuse memory and achieve
|
[sync pool](https://golang.org/pkg/sync/#Pool) to reuse memory and achieve
|
||||||
zero dynamic memory allocation with no GC overhead.
|
zero dynamic memory allocation with no GC overhead.
|
||||||
|
82
website/docs/recipes/file-upload.md
Normal file
82
website/docs/recipes/file-upload.md
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
## Multipart File Upload
|
||||||
|
|
||||||
|
`server.go`
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func upload(c *echo.Context) error {
|
||||||
|
req := c.Request()
|
||||||
|
|
||||||
|
// req.ParseMultipartForm(16 << 20) // Max memory 16 MiB
|
||||||
|
|
||||||
|
// Read form fields
|
||||||
|
name := req.FormValue("name")
|
||||||
|
email := req.FormValue("email")
|
||||||
|
|
||||||
|
// Read files
|
||||||
|
files := req.MultipartForm.File["files"]
|
||||||
|
for _, f := range(files) {
|
||||||
|
// Source file
|
||||||
|
src, err := f.Open()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer src.Close()
|
||||||
|
|
||||||
|
// Destination file
|
||||||
|
dst, err := os.Create(f.Filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer dst.Close()
|
||||||
|
|
||||||
|
if _, err = io.Copy(dst, src); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c.String(http.StatusOK, "Thank You! %s <%s>, %d files uploaded successfully.",
|
||||||
|
name, email, len(files))
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
e := echo.New()
|
||||||
|
e.Index("public/index.html")
|
||||||
|
e.Post("/upload", upload)
|
||||||
|
e.Run(":1323")
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
`index.html`
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Multipart File Upload</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Upload Files</h1>
|
||||||
|
<form action="/upload" method=post enctype=multipart/form-data>
|
||||||
|
Name: <input type="text" name="name"><br>
|
||||||
|
Email: <input type="email" name="email"><br>
|
||||||
|
Files: <input type="file" name="files" multiple><br><br>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## [Source Code]
|
52
website/docs/recipes/graceful-shutdown.md
Normal file
52
website/docs/recipes/graceful-shutdown.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
## Graceful Shutdown
|
||||||
|
|
||||||
|
### With [graceful](https://github.com/tylerb/graceful)
|
||||||
|
|
||||||
|
`server.go`
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
"github.com/tylerb/graceful"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Setup
|
||||||
|
e := echo.New()
|
||||||
|
e.Get("/", func(c *echo.Context) error {
|
||||||
|
return c.String(http.StatusOK, "Sue sews rose on slow jor crows nose")
|
||||||
|
})
|
||||||
|
|
||||||
|
graceful.ListenAndServe(e.Server(":1323"), 5*time.Second)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### With [grace](https://github.com/facebookgo/grace)
|
||||||
|
|
||||||
|
`server.go`
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/facebookgo/grace/gracehttp"
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Setup
|
||||||
|
e := echo.New()
|
||||||
|
e.Get("/", func(c *echo.Context) error {
|
||||||
|
return c.String(http.StatusOK, "Six sick bricks tick")
|
||||||
|
})
|
||||||
|
|
||||||
|
gracehttp.Serve(e.Server(":1323"))
|
||||||
|
}
|
||||||
|
```
|
53
website/docs/recipes/streaming-response.md
Normal file
53
website/docs/recipes/streaming-response.md
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
## Streaming Response
|
||||||
|
|
||||||
|
`server.go`
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type (
|
||||||
|
Geolocation struct {
|
||||||
|
Altitude float64
|
||||||
|
Latitude float64
|
||||||
|
Longitude float64
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
locations = []Geolocation{
|
||||||
|
{-97, 37.819929, -122.478255},
|
||||||
|
{1899, 39.096849, -120.032351},
|
||||||
|
{2619, 37.865101, -119.538329},
|
||||||
|
{42, 33.812092, -117.918974},
|
||||||
|
{15, 37.77493, -122.419416},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
e := echo.New()
|
||||||
|
e.Get("/stream", func(c *echo.Context) error {
|
||||||
|
c.Response().Header().Set(echo.ContentType, echo.ApplicationJSON)
|
||||||
|
c.Response().WriteHeader(http.StatusOK)
|
||||||
|
for _, l := range locations {
|
||||||
|
if err := json.NewEncoder(c.Response()).Encode(l); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.Response().Flush()
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
e.Run(":1323")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## [Source Code]()
|
26
website/docs/recipes/websocket.md
Normal file
26
website/docs/recipes/websocket.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
## WebSocket
|
||||||
|
|
||||||
|
`server.go`
|
||||||
|
|
||||||
|
```go
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/labstack/echo"
|
||||||
|
mw "github.com/labstack/echo/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
e := echo.New()
|
||||||
|
e.Use(mw.Logger())
|
||||||
|
e.WebSocket("/ws", func(c *echo.Context) error {
|
||||||
|
io.Copy(c.Socket(), c.Socket())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
e.Run(":1323")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## [Source Code]()
|
@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<link href="{{ base_url }}/css/bootstrap-custom.min.css" rel="stylesheet">
|
<link href="{{ base_url }}/css/bootstrap-custom.min.css" rel="stylesheet">
|
||||||
<link href="{{ base_url }}/css/font-awesome-4.0.3.css" rel="stylesheet">
|
<link href="{{ base_url }}/css/font-awesome-4.0.3.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="{{ base_url }}/css/highlight.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/8.6/styles/tomorrow-night.min.css">
|
||||||
<link href="{{ base_url }}/css/base.css" rel="stylesheet">
|
<link href="{{ base_url }}/css/base.css" rel="stylesheet">
|
||||||
<link href="{{ base_url }}/css/echo.css" rel="stylesheet">
|
<link href="{{ base_url }}/css/echo.css" rel="stylesheet">
|
||||||
{%- for path in extra_css %}
|
{%- for path in extra_css %}
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
site_name: Echo
|
site_name: Echo
|
||||||
|
|
||||||
theme: journal
|
theme: journal
|
||||||
|
|
||||||
theme_dir: echo
|
theme_dir: echo
|
||||||
|
|
||||||
copyright: '© 2015 LabStack'
|
copyright: '© 2015 LabStack'
|
||||||
|
|
||||||
repo_url: https://github.com/labstack/echo
|
repo_url: https://github.com/labstack/echo
|
||||||
|
|
||||||
google_analytics: ['UA-51208124-3', 'auto']
|
google_analytics: ['UA-51208124-3', 'auto']
|
||||||
|
pages:
|
||||||
|
- Home: index.md
|
||||||
|
- Guide: guide.md
|
||||||
|
- Recipes:
|
||||||
|
- File Upload: recipes/file-upload.md
|
||||||
|
- Graceful Shutdown: recipes/graceful-shutdown.md
|
||||||
|
- Streaming Response: recipes/streaming-response.md
|
||||||
|
- WebSocket: recipes/websocket.md
|
||||||
|
Reference in New Issue
Block a user