GithubHelp home page GithubHelp logo

router's Introduction

gowww router GoDoc Build Coverage Go Report Status Stable

Package router provides a lightning fast HTTP router.

Features

  • Extreme performance: sub-microsecond routing in most cases
  • Full compatibility with the http.Handler interface
  • Generic: no magic methods, bring your own handlers
  • Path parameters, regular expressions and wildcards
  • Smart prioritized routes
  • Zero memory allocations during serving (but for parameters)
  • Respecting the principle of least surprise
  • Tested and used in production

Installing

  1. Get package:

    go get -u github.com/gowww/router
  2. Import it in your code:

    import "github.com/gowww/router"

Usage

  1. Make a new router:

    rt := router.New()
  2. Make a route:

    rt.Handle("GET", "/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    	fmt.Fprint(w, "Hello")
    }))

    Remember that HTTP methods are case-sensitive and uppercase by convention (RFC 7231 4.1).
    So you can directly use the built-in shortcuts for standard HTTP methods: Router.Get, Router.Post, Router.Put, Router.Patch and Router.Delete.

  3. Give the router to the server:

    http.ListenAndServe(":8080", rt)

Parameters

Named

A named parameter begins with : and matches any value until the next / or end of path.

To retrieve the value (stored in request's context), ask Parameter.
It will return the value as a string.

Example, with a parameter id:

rt.Get("/users/:id", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	id := router.Parameter(r, "id")
	fmt.Fprintf(w, "Page of user #%s", id)
}))
No surprise

A parameter can be used on the same level as a static route, without conflict:

rt.Get("/users/all", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "All users page")
}))

rt.Get("/users/:id", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	id := router.Parameter(r, "id")
	fmt.Fprintf(w, "Page of user #%s", id)
}))

Regular expressions

If a parameter must match an exact pattern (digits only, for example), you can also set a regular expression constraint just after the parameter name and another ::

rt.Get(`/users/:id:^\d+$`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	id := router.Parameter(r, "id")
	fmt.Fprintf(w, "Page of user #%s", id)
}))

If you don't need to retrieve the parameter value but only use a regular expression, you can omit the parameter name:

rt.Get(`/shows/::^prison-break-s06-.+`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, "Prison Break S06 — Coming soon…")
}))

Don't forget that regular expressions can significantly reduce performance.

No surprise

A parameter with a regular expression can be used on the same level as a simple parameter, without conflict:

rt.Get(`/users/:id:^\d+$`, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	id := router.Parameter(r, "id")
	fmt.Fprintf(w, "Page of user #%s", id)
}))

rt.Get("/users/:name", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	name := router.Parameter(r, "name")
	fmt.Fprintf(w, "Page of %s", name)
}))

Wildcard

A trailing slash in a route path is significant.
It behaves like a wildcard by matching the beginning of the request path.
The rest of the request path becomes the parameter value of *:

rt.Get("/files/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	filepath := router.Parameter(r, "*")
	fmt.Fprintf(w, "Get file %s", filepath)
}))

Note that a trailing slash in a request path is always trimmed and the client redirected.
For example, a request for /files/ will be redirected to /files and will never match a /files/ route.
In other words, /files and /files/ are two different routes.

No surprise

Deeper route paths with the same prefix as the wildcard will take precedence, without conflict:

// Will match:
// 	/files/one
// 	/files/two
// 	...
rt.Get("/files/:name", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {kv
	name := router.Parameter(r, "name")
	fmt.Fprintf(w, "Get root file #%s", name)
}))

// Will match:
// 	/files/one/...
// 	/files/two/...
// 	...
rt.Get("/files/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	filepath := router.Parameter(r, "*")
	fmt.Fprintf(w, "Get file %s", filepath)
}))

// Will match:
// 	/files/movies/one
// 	/files/movies/two
// 	...
rt.Get("/files/movies/:name", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	name := router.Parameter(r, "name")
	fmt.Fprintf(w, "Get movie #%s", name)
}))

Static files

For serving static files, like for other routes, just bring your own handler.

Example, with the standard net/http.FileServer:

rt.Get("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir("static"))))

Custom "not found" handler

When a request match no route, the response status is set to 404 and an empty body is sent by default.

But you can set your own "not found" handler.
In this case, it's up to you to set the response status code (normally 404):

rt.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
	http.NotFound(w, r)
})

router's People

Contributors

xthezealot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

router's Issues

Sorting by number of childrens is not usefull

I implemented a simple radix tree and did some tests. Based on my benchmarking tests, this algorithm is so fast that sorting doesn't make any significant difference. I would suggest you reconsider sorting by number of children.

What might show a difference is to put expensive tests last. So static path segments first, parameters without regex next and parameters with regex last. Sorting in this order needs only to update the modified children array.

I like to take the opportunity to congratulate you for the remarkable performance of your routing package. The no surprise is perfect too. Thank you.

very simple static routing for "/" doesn't seam to work

The following code doesn't return some files in my ./www directory.
My ./www directory contains two files ./www/index.html and ./www/css/main.css. Note that the css file is in a subdirectory named css.

When performing a get on http://localhost:8080 I get back the index.html file, but the css file is not returned.

Here is the code:

func main() {
	rt := router.New()
	rt.Get("/", http.FileServer(http.Dir("www")))
	http.ListenAndServe(":8080", rt)
}

When using the default server mux, I have no problem. I get the css file and the style is right.

func main() {
	http.Handle("/", http.FileServer(http.Dir("www")))
	http.ListenAndServe(":8080", nil)
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.