README 수정.
This commit is contained in:
parent
04e4ecab0f
commit
35decb6232
215
README.md
215
README.md
|
@ -21,217 +21,4 @@ go get amuz.es/src/go/logging
|
|||
```
|
||||
|
||||
## Getting Started
|
||||
|
||||
Create a `server.go` file with the following content:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/qiangxue/fasthttp-routing"
|
||||
"github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
router := routing.New()
|
||||
|
||||
router.Get("/", func(c *routing.Context) error {
|
||||
fmt.Fprintf(c, "Hello, world!")
|
||||
return nil
|
||||
})
|
||||
|
||||
panic(fasthttp.ListenAndServe(":8080", router.HandleRequest))
|
||||
}
|
||||
```
|
||||
|
||||
Now run the following command to start the Web server:
|
||||
|
||||
```
|
||||
go run server.go
|
||||
```
|
||||
|
||||
You should be able to access URLs such as `http://localhost:8080`.
|
||||
|
||||
|
||||
### Routes
|
||||
|
||||
ozzo-routing works by building a routing table in a router and then dispatching HTTP requests to the matching handlers
|
||||
found in the routing table. An intuitive illustration of a routing table is as follows:
|
||||
|
||||
|
||||
Routes | Handlers
|
||||
--------------------|-----------------
|
||||
`GET /users` | m1, m2, h1, ...
|
||||
`POST /users` | m1, m2, h2, ...
|
||||
`PUT /users/<id>` | m1, m2, h3, ...
|
||||
`DELETE /users/<id>`| m1, m2, h4, ...
|
||||
|
||||
|
||||
For an incoming request `GET /users`, the first route would match and the handlers m1, m2, and h1 would be executed.
|
||||
If the request is `PUT /users/123`, the third route would match and the corresponding handlers would be executed.
|
||||
Note that the token `<id>` can match any number of non-slash characters and the matching part can be accessed as
|
||||
a path parameter value in the handlers.
|
||||
|
||||
**If an incoming request matches multiple routes in the table, the route added first to the table will take precedence.
|
||||
All other matching routes will be ignored.**
|
||||
|
||||
The actual implementation of the routing table uses a variant of the radix tree data structure, which makes the routing
|
||||
process as fast as working with a hash table, thanks to the inspiration from [httprouter](https://github.com/julienschmidt/httprouter).
|
||||
|
||||
To add a new route and its handlers to the routing table, call the `To` method like the following:
|
||||
|
||||
```go
|
||||
router := routing.New()
|
||||
router.To("GET", "/users", m1, m2, h1)
|
||||
router.To("POST", "/users", m1, m2, h2)
|
||||
```
|
||||
|
||||
You can also use shortcut methods, such as `Get`, `Post`, `Put`, etc., which are named after the HTTP method names:
|
||||
|
||||
```go
|
||||
router.Get("/users", m1, m2, h1)
|
||||
router.Post("/users", m1, m2, h2)
|
||||
```
|
||||
|
||||
If you have multiple routes with the same URL path but different HTTP methods, like the above example, you can
|
||||
chain them together as follows,
|
||||
|
||||
```go
|
||||
router.Get("/users", m1, m2, h1).Post(m1, m2, h2)
|
||||
```
|
||||
|
||||
If you want to use the same set of handlers to handle the same URL path but different HTTP methods, you can take
|
||||
the following shortcut:
|
||||
|
||||
```go
|
||||
router.To("GET,POST", "/users", m1, m2, h)
|
||||
```
|
||||
|
||||
A route may contain parameter tokens which are in the format of `<name:pattern>`, where `name` stands for the parameter
|
||||
name, and `pattern` is a regular expression which the parameter value should match. A token `<name>` is equivalent
|
||||
to `<name:[^/]*>`, i.e., it matches any number of non-slash characters. At the end of a route, an asterisk character
|
||||
can be used to match any number of arbitrary characters. Below are some examples:
|
||||
|
||||
* `/users/<username>`: matches `/users/admin`
|
||||
* `/users/accnt-<id:\d+>`: matches `/users/accnt-123`, but not `/users/accnt-admin`
|
||||
* `/users/<username>/*`: matches `/users/admin/profile/address`
|
||||
|
||||
When a URL path matches a route, the matching parameters on the URL path can be accessed via `Context.Param()`:
|
||||
|
||||
```go
|
||||
router := routing.New()
|
||||
|
||||
router.Get("/users/<username>", func (c *routing.Context) error {
|
||||
fmt.Fprintf(c, "Name: %v", c.Param("username"))
|
||||
return nil
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
### Route Groups
|
||||
|
||||
Route group is a way of grouping together the routes which have the same route prefix. The routes in a group also
|
||||
share the same handlers that are registered with the group via its `Use` method. For example,
|
||||
|
||||
```go
|
||||
router := routing.New()
|
||||
api := router.Group("/api")
|
||||
api.Use(m1, m2)
|
||||
api.Get("/users", h1).Post(h2)
|
||||
api.Put("/users/<id>", h3).Delete(h4)
|
||||
```
|
||||
|
||||
The above `/api` route group establishes the following routing table:
|
||||
|
||||
|
||||
Routes | Handlers
|
||||
------------------------|-------------
|
||||
`GET /api/users` | m1, m2, h1, ...
|
||||
`POST /api/users` | m1, m2, h2, ...
|
||||
`PUT /api/users/<id>` | m1, m2, h3, ...
|
||||
`DELETE /api/users/<id>`| m1, m2, h4, ...
|
||||
|
||||
|
||||
As you can see, all these routes have the same route prefix `/api` and the handlers `m1` and `m2`. In other similar
|
||||
routing frameworks, the handlers registered with a route group are also called *middlewares*.
|
||||
|
||||
Route groups can be nested. That is, a route group can create a child group by calling the `Group()` method. The router
|
||||
serves as the top level route group. A child group inherits the handlers registered with its parent group. For example,
|
||||
|
||||
```go
|
||||
router := routing.New()
|
||||
router.Use(m1)
|
||||
|
||||
api := router.Group("/api")
|
||||
api.Use(m2)
|
||||
|
||||
users := group.Group("/users")
|
||||
users.Use(m3)
|
||||
users.Put("/<id>", h1)
|
||||
```
|
||||
|
||||
Because the router serves as the parent of the `api` group which is the parent of the `users` group,
|
||||
the `PUT /api/users/<id>` route is associated with the handlers `m1`, `m2`, `m3`, and `h1`.
|
||||
|
||||
|
||||
### Router
|
||||
|
||||
Router manages the routing table and dispatches incoming requests to appropriate handlers. A router instance is created
|
||||
by calling the `routing.New()` method.
|
||||
|
||||
To hook up router with fasthttp, use the following code:
|
||||
|
||||
```go
|
||||
router := routing.New()
|
||||
fasthttp.ListenAndServe(":8080", router.HandleRequest)
|
||||
```
|
||||
|
||||
|
||||
### Handlers
|
||||
|
||||
A handler is a function with the signature `func(*routing.Context) error`. A handler is executed by the router if
|
||||
the incoming request URL path matches the route that the handler is associated with. Through the `routing.Context`
|
||||
parameter, you can access the request information in handlers.
|
||||
|
||||
A route may be associated with multiple handlers. These handlers will be executed in the order that they are registered
|
||||
to the route. The execution sequence can be terminated in the middle using one of the following two methods:
|
||||
|
||||
* A handler returns an error: the router will skip the rest of the handlers and handle the returned error.
|
||||
* A handler calls `Context.Abort()`: the router will simply skip the rest of the handlers. There is no error to be handled.
|
||||
|
||||
A handler can call `Context.Next()` to explicitly execute the rest of the unexecuted handlers and take actions after
|
||||
they finish execution. For example, a response compression handler may start the output buffer, call `Context.Next()`,
|
||||
and then compress and send the output to response.
|
||||
|
||||
|
||||
### Context
|
||||
|
||||
For each incoming request, a `routing.Context` object is passed through the relevant handlers. Because `routing.Context`
|
||||
embeds `fasthttp.RequestCtx`, you can access all properties and methods provided by the latter.
|
||||
|
||||
Additionally, the `Context.Param()` method allows handlers to access the URL path parameters that match the current route.
|
||||
Using `Context.Get()` and `Context.Set()`, handlers can share data between each other. For example, an authentication
|
||||
handler can store the authenticated user identity by calling `Context.Set()`, and other handlers can retrieve back
|
||||
the identity information by calling `Context.Get()`.
|
||||
|
||||
Context also provides a handy `WriteData()` method that can be used to write data of arbitrary type to the response.
|
||||
The `WriteData()` method can also be overridden (by replacement) to achieve more versatile response data writing.
|
||||
|
||||
|
||||
### Error Handling
|
||||
|
||||
A handler may return an error indicating some erroneous condition. Sometimes, a handler or the code it calls may cause
|
||||
a panic. Both should be handled properly to ensure best user experience. It is recommended that you use
|
||||
the `fault.Recover` handler or a similar error handler to handle these errors.
|
||||
|
||||
If an error is not handled by any handler, the router will handle it by calling its `handleError()` method which
|
||||
simply sets an appropriate HTTP status code and writes the error message to the response.
|
||||
|
||||
When an incoming request has no matching route, the router will call the handlers registered via the `Router.NotFound()`
|
||||
method. All the handlers registered via `Router.Use()` will also be called in advance. By default, the following two
|
||||
handlers are registered with `Router.NotFound()`:
|
||||
|
||||
* `routing.MethodNotAllowedHandler`: a handler that sends an `Allow` HTTP header indicating the allowed HTTP methods for a requested URL
|
||||
* `routing.NotFoundHandler`: a handler triggering 404 HTTP error
|
||||
TBD
|
||||
|
|
Loading…
Reference in New Issue