Documentation ¶
Overview ¶
Package router provides a simple & efficient parametrized HTTP router.
A HTTP router allows you to map a HTTP request method and path to a specific function. A parameterized HTTP router allows you to designate specific portions of the request path as a parameter, which can later be fetched during the request itself.
This package allows you modify the routing table ad-hoc, even while the server is running.
Index ¶
- Variables
- func ServeHTTPRange(options ServeHTTPRangeOptions) error
- type ByteRange
- type Handle
- type IMime
- type Request
- type ServeHTTPRangeOptions
- type Server
- func (s *Server) Handle(method, path string, handler Handle)
- func (s *Server) ListenAndServe(addr string) error
- func (s *Server) RemoveHandle(method, path string)
- func (s *Server) Serve(listener net.Listener) error
- func (s *Server) ServeFiles(localRoot string, urlRoot string)
- func (s *Server) SetMethodNotAllowedHandle(handle func(w http.ResponseWriter, r *http.Request))
- func (s *Server) SetNotFoundHandle(handle func(w http.ResponseWriter, r *http.Request))
- func (s *Server) Stop()
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var CacheMaxAge time.Duration = 24 * time.Hour
CacheMaxAge the amount of time browsers may consider static content to be fresh. Set this to 0 to not include a "Cache-Control" header for static requests.
var GenerateDirectoryListing = true
GenerateDirectoryListing if the router should generate a directory listing for static directories that do not have an index file (see also IndexFileName)
var IndexFileName = "index.html"
IndexFileName is the name used when searching a directory for an index
Functions ¶
func ServeHTTPRange ¶ added in v1.9.0
func ServeHTTPRange(options ServeHTTPRangeOptions) error
ServeHTTPRange serve a HTTP range
Types ¶
type ByteRange ¶ added in v1.9.0
ByteRange describes a range of offsets for reading from a byte slice.
There are thee possabilities for byte ranges: (Start=100, End=200) Read data from offset 100 until offset 200. (Start=100, End=-1) Read all remaining data from offset 100 until the end of the reader. (Start=-1, End=100) Read the last 100 bytes of the reader.
func ParseRangeHeader ¶ added in v1.9.0
ParseRangeHeader will parse the value from the HTTP ranges header and return a slice of byte ranges, or nil if the headers value is malformed.
func (ByteRange) ContentRangeValue ¶ added in v1.9.0
ContentRangeValue will return a value sutible for the content-range header
type Handle ¶
type Handle func(http.ResponseWriter, Request)
Handle describes the signature for a handle of a path
type IMime ¶
type IMime interface { // GetMime is called with the path to a file when the router needs a value for the "Content-Type" header. // This method must be thread-safe and should not panic. If an error occurs you must return // "application/octet-stream". // // filePath is guranteed to exist and be readable by the running process. GetMime(filePath string) string }
IMime describes an interface for a MIME detection system
var MimeGetter IMime = &extensionMimeGetterType{}
MimeGetter the implementation used to determine the value of the "Content-Type" header for static files. By default this uses a simple implentation that guesses the MIME type based on the extension in the files name.
type Request ¶
type Request struct { // The underlaying HTTP request HTTP *http.Request // A map of any parameters from the router path mapped to their values from the request path Parameters map[string]string }
Request describes a HTTP request
type ServeHTTPRangeOptions ¶ added in v1.9.0
type ServeHTTPRangeOptions struct { // Any additional headers to append to the request. // Do not specify a content-type here, instead use the MIMEType property. Headers map[string]string // Cookies to set on the response Cookies []http.Cookie // Byte ranges from the HTTP request Ranges []ByteRange // The incoming reader, must support seeking Reader io.ReadSeeker // The total length of the data TotalLength uint64 // The content type of the data MIMEType string // The outgoing HTTP response writer Writer http.ResponseWriter }
ServeHTTPRangeOptions options for serving a HTTP range request
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server describes a server. Do not initialize a new copy of a Server{}, but instead use router.New()
func New ¶
func New() *Server
New will initialize a new Server instance and return it. This does not start the server.
func (*Server) Handle ¶
Handle registers a handler for an HTTP request of method to path.
Method must be a valid HTTP method, in all caps. Path must always begin with a forward slash /. Will panic on invalid vales. Will panic if registering a duplicate method & path.
Handle may be called even while the server is listening and is threadsafe.
Any segment that begins with a colon (:) will be parameterized. The value of all parameters for the path will be populated into the Parameters map included in the Request object in the handler. For example:
handle path = "/widgets/:widget_id/cost/:currency" request path = "/widgets/1234/cost/cad" parameters = { "widget_id": "1234", "currency": "cad" }
Any segment that begins with an astreisk (*) will be parameterized as well, however unlike colon parameters, these will include the entire remaining path as the value of the parameter, whereas colon parameters will only include that segment as the value. Multiple methods can be registered for the same wildcard path, provided they use the same parameter name. Any segments included after the parameter name are ignored. For example
handle path = "/proxy/*url" request path = "/proxy/some/multi/segmented/value" parameters = { "url": "some/multi/segmented/value" }
Parameter segments are exclusive, meaning you can not have a static segment at the same position as a parameterized element. For example, these both will panic:
// This panics because /all occupies the same segment as the parameter :username server.Handle("GET", "/users/:username", ...) server.Handle("GET", "/users/all", ...) // This panics because /user/id occupied the same segment as the wildcard parameter *param server.Handle("GET", "/users/*param", ...) server.Handle("GET", "/users/user/id", ...)
Paths that end with a slash are unique to those that don't. For example, these would be considred unique by the router:
server.Handle("GET", "/users/all/", ...) server.Handle("GET", "/users/all", ...)
Example ¶
package main import ( "net/http" "github.com/ecnepsnai/web/router" ) func main() { server := router.New() server.Handle("GET", "/hello/:greeting", func(rw http.ResponseWriter, r router.Request) { rw.Write([]byte("Hello, " + r.Parameters["greeting"])) }) }
Output:
func (*Server) ListenAndServe ¶
ListenAndServe will listen for HTTP requests on the specified socket address. Valid addresses are typically in the form of: <IP Address>:<Port Number>. For IPv6 addresses, wrap the address in brackets.
An error will only be returned if there was an error listening or the listener was closed.
Example ¶
package main import ( "github.com/ecnepsnai/web/router" ) func main() { server := router.New() server.ListenAndServe("127.0.0.1:8080") }
Output:
func (*Server) RemoveHandle ¶
RemoveHandle will remove any handler for the given method and path. If no handle exists, it does nothing. If both method and path are * it removes everything from the routing table.
Note that parameter names are not considered when removing a path. For example, you may register a path with `/:username` and remove it with `/:something_else`.
This may be called even while the server is listening and is threadsafe.
Example ¶
package main import ( "net/http" "github.com/ecnepsnai/web/router" ) func main() { server := router.New() server.Handle("GET", "/hello/:greeting", func(rw http.ResponseWriter, r router.Request) { rw.Write([]byte("Hello, " + r.Parameters["greeting"])) }) server.RemoveHandle("GET", "/hello/:greeting") server.RemoveHandle("*", "*") // Will remove everything from the routing table! }
Output:
func (*Server) Serve ¶
Serve will listen for HTTP requests on the given listener.
An error will only be returned if there was an error listening or the listener was abruptly closed.
Example ¶
package main import ( "net" "github.com/ecnepsnai/web/router" ) func main() { server := router.New() l, _ := net.Listen("tcp", "[::1]:8080") server.Serve(l) }
Output:
func (*Server) ServeFiles ¶
ServeFiles registers a handler for all requests under urlRoot to serve any files matching the same path in a local filesystem directory localRoot.
For example:
localRoot = /usr/share/www/ urlRoot = /static/ Request for '/static/image.jpg' would read file '/usr/share/www/image.jpg'
Will panic if any handle is registered under urlRoot. Attempting to register a new handle under urlRoot after calling ServeFiles will panic.
Caching will be enabled by default for all files served by this router. The mtime of the file will be used for the Last-Modified date.
By default, the server will use the file extension (if any) to determine the MIME type for the response. You may use your own MIME detection by implementing the IMime interface and setting MimeGetter.
The server will also instruct clients to cache files served for up-to 1 day. You can control this with the CacheMaxAge variable.
When a directory is requested, the router will look for an index file with the name from the IndexFileName variable. If no file is found, a directory listing will automatically be generated. You can control this with the GenerateDirectoryListing variable.
Example ¶
package main import ( "github.com/ecnepsnai/web/router" ) func main() { server := router.New() localDirectory := "/usr/share/http" // Directory to serve files from urlRoot := "/assets/" // Top-level path for all requests to be directed to the local directory server.ServeFiles(localDirectory, urlRoot) // Now any HTTP GET or HEAD requests to /assets/ will read files from /usr/share/http. // For example: // HTTP GET "/assets/index.html" will read file "/usr/share/http/index.html" }
Output:
func (*Server) SetMethodNotAllowedHandle ¶
func (s *Server) SetMethodNotAllowedHandle(handle func(w http.ResponseWriter, r *http.Request))
SetMethodNotAllowedHandle will set the handle called when a request comes in for a known path but not the correct method.
A default handle is set when the server is created.
func (*Server) SetNotFoundHandle ¶
func (s *Server) SetNotFoundHandle(handle func(w http.ResponseWriter, r *http.Request))
SetNotFoundHandle will set the handle called when a request that did not match any registered path comes in.
A default handle is set when the server is created.