Documentation ¶
Index ¶
- Variables
- func CanonicalMIMEHeaderKey(s string) string
- func Clean(p string) string
- func IsTokenRune(r rune) bool
- func MethodNotAllowedHandler(h *HttpObjectHead, methods map[string]*LeafVerb)
- func MethodNotFoundHandler(h *HttpObjectHead)
- func ShowErrorsJsonPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
- func ShowErrorsPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
- func SimplePanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
- func StreamingHTTPProxy_ConnectionHandler(opts *StreamingHTTPProxyServerOptions, stream *StreamNetConn)
- func StreamingHTTPProxy_SendHohThenDuplexStream(opts *StreamingHTTPProxyServerOptions, req_h *HttpObjectHead, buffSize int)
- func StreamingHTTPProxy_Server(opts *StreamingHTTPProxyServerOptions)
- func WriteHttpResponse(h *HttpObjectHead, bb []byte) (err error)
- func WriteSimpleHttpResponse(s *StreamNetConn, bb []byte, code int) (err error)
- type ChanStreamBytesBuff
- type ChanStreamSingleBytes
- type Command
- type CommandMsg
- type ConnectionsRegistry
- type CookieEntry
- type Group
- type HandleFunc
- type HeadersMapArray
- type HttpObjectHead
- func (h *HttpObjectHead) CancelRequestWithResponseAndClose(h2 *HttpObjectHead, bb []byte) (err error)
- func (h *HttpObjectHead) MarshalHTTPReply() (bb []byte)
- func (h *HttpObjectHead) MarshalHTTPRequest() (bb []byte, err error)
- func (hoh *HttpObjectHead) ParseCookieHeaders()
- func (hoh *HttpObjectHead) ParseSetCookieHeaders()
- type LeafVerb
- type LookupResult
- type Node
- type PanicHandleFunc
- type PathSource
- type ReadUntiler
- type ReaderChunk
- type RedirectBehavior
- type StreamNetConn
- func (s *StreamNetConn) Close()
- func (s *StreamNetConn) ParseHttpObjectHead() (h *HttpObjectHead, err error)
- func (s *StreamNetConn) ParseHttpObjectHeadResponse() (h *HttpObjectHead, err error)
- func (s *StreamNetConn) ReadHTTPBodyChunk() (chunk []byte, last bool)
- func (s *StreamNetConn) ReadLength(n int) (bb []byte, err error)
- func (s *StreamNetConn) ReadUntil(re *regexp.Regexp, f func(rc *ReaderChunk)) *ReaderChunk
- func (s *StreamNetConn) WriteWhole(bb []byte) error
- type StreamingHTTPProxyServerOptions
- type TreeMux
Constants ¶
This section is empty.
Variables ¶
var ReChunked = regexp.MustCompile(`(, ?|^)chunked($|,)`)
Functions ¶
func CanonicalMIMEHeaderKey ¶ added in v1.3.14
CanonicalMIMEHeaderKey returns the canonical format of the MIME header key s. The canonicalization converts the first letter and any letter following a hyphen to upper case; the rest are converted to lowercase. For example, the canonical key for "accept-encoding" is "Accept-Encoding". MIME header keys are assumed to be ASCII only. If s contains a space or invalid header field bytes, it is returned without modifications.
func Clean ¶
Clean is the URL version of path.Clean, it returns a canonical URL path for p, eliminating . and .. elements.
The following rules are applied iteratively until no further processing can be done:
- Replace multiple slashes with a single slash.
- Eliminate each . path name element (the current directory).
- Eliminate each inner .. path name element (the parent directory) along with the non-.. element that precedes it.
- Eliminate .. elements that begin a rooted path: that is, replace "/.." by "/" at the beginning of a path.
If the result of this process is an empty string, "/" is returned
func IsTokenRune ¶ added in v1.3.36
func MethodNotAllowedHandler ¶
func MethodNotAllowedHandler(h *HttpObjectHead, methods map[string]*LeafVerb)
MethodNotAllowedHandler is the default handler for TreeMux.MethodNotAllowedHandler, which is called for patterns that match, but do not have a handler installed for the requested method. It simply writes the status code http.StatusMethodNotAllowed and fills in the `Allow` header value appropriately.
func MethodNotFoundHandler ¶
func MethodNotFoundHandler(h *HttpObjectHead)
func ShowErrorsJsonPanicHandler ¶
func ShowErrorsJsonPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
func ShowErrorsPanicHandler ¶
func ShowErrorsPanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
ShowErrorsPanicHandler prints a nice representation of an error to the browser. This was taken from github.com/gocraft/web, which adapted it from the Traffic project.
func SimplePanicHandler ¶
func SimplePanicHandler(w http.ResponseWriter, r *http.Request, err interface{})
SimplePanicHandler just returns error 500.
func StreamingHTTPProxy_ConnectionHandler ¶ added in v1.3.0
func StreamingHTTPProxy_ConnectionHandler(opts *StreamingHTTPProxyServerOptions, stream *StreamNetConn)
func StreamingHTTPProxy_SendHohThenDuplexStream ¶
func StreamingHTTPProxy_SendHohThenDuplexStream( opts *StreamingHTTPProxyServerOptions, req_h *HttpObjectHead, buffSize int, )
it's expected you call this from the RequestObjectHandleFunc
func StreamingHTTPProxy_Server ¶
func StreamingHTTPProxy_Server(opts *StreamingHTTPProxyServerOptions)
func WriteHttpResponse ¶
func WriteHttpResponse(h *HttpObjectHead, bb []byte) (err error)
func WriteSimpleHttpResponse ¶
func WriteSimpleHttpResponse(s *StreamNetConn, bb []byte, code int) (err error)
Types ¶
type ChanStreamBytesBuff ¶ added in v1.3.11
type ChanStreamBytesBuff struct { Buff []byte Ch chan []byte Ctx context.Context DelimFindTailLen int // contains filtered or unexported fields }
func (*ChanStreamBytesBuff) Read ¶ added in v1.3.11
func (s *ChanStreamBytesBuff) Read(p []byte) (n int, err error)
WARNING: not tested yet
func (*ChanStreamBytesBuff) ReadUntil ¶ added in v1.3.11
func (s *ChanStreamBytesBuff) ReadUntil(re *regexp.Regexp, f func(rc *ReaderChunk)) *ReaderChunk
WARNING: not tested yet
func (*ChanStreamBytesBuff) Run ¶ added in v1.3.11
func (s *ChanStreamBytesBuff) Run()
WARNING: not tested yet
type ChanStreamSingleBytes ¶ added in v1.3.11
func (*ChanStreamSingleBytes) Read ¶ added in v1.3.11
func (s *ChanStreamSingleBytes) Read(p []byte) (n int, err error)
WARNING: not tested yet
func (*ChanStreamSingleBytes) ReadUntil ¶ added in v1.3.11
func (s *ChanStreamSingleBytes) ReadUntil(re *regexp.Regexp, f func(rc *ReaderChunk)) *ReaderChunk
WARNING: not tested yet
type CommandMsg ¶ added in v1.3.23
type CommandMsg struct { Command Command ChDown chan CommandMsg }
type ConnectionsRegistry ¶ added in v1.3.23
func NewConnectionsRegistry ¶ added in v1.3.23
func NewConnectionsRegistry() *ConnectionsRegistry
func (*ConnectionsRegistry) Add ¶ added in v1.3.23
func (cr *ConnectionsRegistry) Add(c net.Conn)
func (*ConnectionsRegistry) Remove ¶ added in v1.3.23
func (cr *ConnectionsRegistry) Remove(c net.Conn)
type CookieEntry ¶ added in v1.3.14
type CookieEntry struct { // Name is missing here, because it's the map's key // Not all fields should be put in request, only those set Value string Domain string Path string SameSite string Secure bool HttpOnly bool Persistent bool HostOnly bool Expires time.Time Creation time.Time LastAccess time.Time }
type Group ¶
type Group struct {
// contains filtered or unexported fields
}
func (*Group) Handle ¶
func (g *Group) Handle(method string, path string, handler HandleFunc) *LeafVerb
Path elements starting with : indicate a wildcard in the path. A wildcard will only match on a single path segment. That is, the pattern `/post/:postid` will match on `/post/1` or `/post/1/`, but not `/post/1/2`.
A path element starting with * is a catch-all, whose value will be a string containing all text in the URL matched by the wildcards. For example, with a pattern of `/images/*path` and a requested URL `images/abc/def`, path would contain `abc/def`.
Routing Rule Priority ¶
The priority rules in the router are simple.
1. Static path segments take the highest priority. If a segment and its subtree are able to match the URL, that match is returned.
2. Wildcards take second priority. For a particular wildcard to match, that wildcard and its subtree must match the URL.
3. Finally, a catch-all rule will match when the earlier path segments have matched, and none of the static or wildcard conditions have matched. Catch-all rules must be at the end of a pattern.
So with the following patterns, we'll see certain matches:
router = httptreemux.New() router.GET("/:page", pageHandler) router.GET("/:year/:month/:post", postHandler) router.GET("/:year/:month", archiveHandler) router.GET("/images/*path", staticHandler) router.GET("/favicon.ico", staticHandler) /abc will match /:page /2014/05 will match /:year/:month /2014/05/really-great-blog-post will match /:year/:month/:post /images/CoolImage.gif will match /images/*path /images/2014/05/MayImage.jpg will also match /images/*path, with all the text after /images stored in the variable path. /favicon.ico will match /favicon.ico
Trailing Slashes ¶
The router has special handling for paths with trailing slashes. If a pattern is added to the router with a trailing slash, any matches on that pattern without a trailing slash will be redirected to the version with the slash. If a pattern does not have a trailing slash, matches on that pattern with a trailing slash will be redirected to the version without.
The trailing slash flag is only stored once for a pattern. That is, if a pattern is added for a method with a trailing slash, all other methods for that pattern will also be considered to have a trailing slash, regardless of whether or not it is specified for those methods too.
This behavior can be turned off by setting TreeMux.RedirectTrailingSlash to false. By default it is set to true. The specifics of the redirect depend on RedirectBehavior.
One exception to this rule is catch-all patterns. By default, trailing slash redirection is disabled on catch-all patterns, since the structure of the entire URL and the desired patterns can not be predicted. If trailing slash removal is desired on catch-all patterns, set TreeMux.RemoveCatchAllTrailingSlash to true.
router = httptreemux.New() router.GET("/about", pageHandler) router.GET("/posts/", postIndexHandler) router.POST("/posts", postFormHandler) GET /about will match normally. GET /about/ will redirect to /about. GET /posts will redirect to /posts/. GET /posts/ will match normally. POST /posts will redirect to /posts/, because the GET method used a trailing slash.
type HandleFunc ¶
type HandleFunc func(node *LeafVerb, hoh *HttpObjectHead, pp map[string]string)
type HeadersMapArray ¶ added in v1.3.27
func (HeadersMapArray) UString0 ¶ added in v1.3.27
func (hma HeadersMapArray) UString0(key string) (val string)
type HttpObjectHead ¶
type HttpObjectHead struct { Schema string `yaml:"Schema,omitempty"` // on marshal, if empty, is auto-set to "HTTP/1.1"; useless in general Method string `yaml:"Method"` RawPath string `yaml:"RawPath"` // host not included, query not included RawQuery string `yaml:"RawQuery,omitempty"` // params after ? QueryParamsMap map[string]any `yaml:"QueryParamsMap,omitempty"` HeadersMapArray `yaml:"HeadersMapArray"` CookiesMap map[string]CookieEntry `yaml:"CookiesMap,omitempty"` ResponseCode int `yaml:"ResponseCode,omitempty"` StreamObject *StreamNetConn `yaml:"-"` UserData map[string]any `yaml:"-"` // can be used to store user data, when constructing pipelines }
func (*HttpObjectHead) CancelRequestWithResponseAndClose ¶ added in v1.3.2
func (h *HttpObjectHead) CancelRequestWithResponseAndClose(h2 *HttpObjectHead, bb []byte) (err error)
func (*HttpObjectHead) MarshalHTTPReply ¶ added in v1.0.1
func (h *HttpObjectHead) MarshalHTTPReply() (bb []byte)
func (*HttpObjectHead) MarshalHTTPRequest ¶
func (h *HttpObjectHead) MarshalHTTPRequest() (bb []byte, err error)
func (*HttpObjectHead) ParseCookieHeaders ¶ added in v1.3.36
func (hoh *HttpObjectHead) ParseCookieHeaders()
TODO: IMPORTANT: This implementation, heavily taken from Google's net/http, IS NOT COMPLETE, and must be fixed, or you risk losing important bits of information!!
func (*HttpObjectHead) ParseSetCookieHeaders ¶ added in v1.3.36
func (hoh *HttpObjectHead) ParseSetCookieHeaders()
type LeafVerb ¶ added in v1.3.34
type LeafVerb struct { HandleFunc UserData map[string]any ParentNode *Node }
type LookupResult ¶
type LookupResult struct { // StatusCode informs the caller about the result of the lookup. // This will generally be `http.StatusNotFound` or `http.StatusMethodNotAllowed` for an // error case. On a normal success, the statusCode will be `http.StatusOK`. A redirect code // will also be used in the case Node *Node StatusCode int LeafVerb *LeafVerb Params map[string]string LeafVerbs map[string]*LeafVerb // Only has a value when StatusCode is MethodNotAllowed. }
LookupResult contains information about a route lookup, which is returned from Lookup and can be passed to ServeLookupResult if the request should be served.
type Node ¶ added in v1.3.25
type Node struct { Path string Priority int StaticIndices []byte ChildrenStatic []*Node ChildWildcard *Node // If none of the above match, check the wildcard children ChildCatchAll *Node // If none of the above match, then we use the catch-all, if applicable. AddSlash bool IsCatchAll bool ImplicitHead bool // If true, the head handler was set implicitly, so let it also be set explicitly. LeafVerbs map[string]*LeafVerb // If this node is the end of the URL, then call the handler, if applicable. LeafWildcardNames []string // The names of the parameters to apply. UserData map[string]any ParentNode *Node }
type PanicHandleFunc ¶
type PanicHandleFunc func(h *HttpObjectHead, err interface{})
The params argument contains the parameters parsed from wildcards and catch-alls in the URL.
type PathSource ¶
type PathSource int
type ReadUntiler ¶ added in v1.3.11
type ReadUntiler interface {
ReadUntil(re *regexp.Regexp, f func(rc *ReaderChunk)) *ReaderChunk
}
type ReaderChunk ¶
func ReadUntil ¶ added in v1.3.11
func ReadUntil(r io.Reader, taillen int, re *regexp.Regexp, f ...func(rc *ReaderChunk)) *ReaderChunk
type RedirectBehavior ¶
type RedirectBehavior int
RedirectBehavior sets the behavior when the router redirects the request to the canonical version of the requested URL using RedirectTrailingSlash or RedirectClean. The default behavior is to return a 301 status, redirecting the browser to the version of the URL that matches the given pattern.
On a POST request, most browsers that receive a 301 will submit a GET request to the redirected URL, meaning that any data will likely be lost. If you want to handle and avoid this behavior, you may use Redirect307, which causes most browsers to resubmit the request using the original method and request body.
Since 307 is supposed to be a temporary redirect, the new 308 status code has been proposed, which is treated the same, except it indicates correctly that the redirection is permanent. The big caveat here is that the RFC is relatively recent, and older browsers will not know what to do with it. Therefore its use is not recommended unless you really know what you're doing.
Finally, the UseHandler value will simply call the handler function for the pattern.
const ( Redirect301 RedirectBehavior = iota // Return 301 Moved Permanently Redirect307 // Return 307 HTTP/1.1 Temporary Redirect Redirect308 // Return a 308 RFC7538 Permanent Redirect UseHandler // Just call the handler function )
type StreamNetConn ¶
type StreamNetConn struct { Conn net.Conn MaxtimeNoProgress time.Duration MaxtimeTotal time.Duration EOF bool ErrStr string DelimFindTailLen int ConnectionsRegistry *ConnectionsRegistry // contains filtered or unexported fields }
func NewStreamNetConn ¶
func NewStreamNetConn( c net.Conn, maxtimeNoProgress, maxtimeTotal time.Duration, connreg *ConnectionsRegistry, ) (s *StreamNetConn)
func (*StreamNetConn) Close ¶ added in v1.3.23
func (s *StreamNetConn) Close()
func (*StreamNetConn) ParseHttpObjectHead ¶ added in v1.3.26
func (s *StreamNetConn) ParseHttpObjectHead() (h *HttpObjectHead, err error)
func (*StreamNetConn) ParseHttpObjectHeadResponse ¶ added in v1.3.26
func (s *StreamNetConn) ParseHttpObjectHeadResponse() (h *HttpObjectHead, err error)
func (*StreamNetConn) ReadHTTPBodyChunk ¶ added in v1.3.28
func (s *StreamNetConn) ReadHTTPBodyChunk() (chunk []byte, last bool)
func (*StreamNetConn) ReadLength ¶
func (s *StreamNetConn) ReadLength(n int) (bb []byte, err error)
func (*StreamNetConn) ReadUntil ¶ added in v1.3.0
func (s *StreamNetConn) ReadUntil(re *regexp.Regexp, f func(rc *ReaderChunk)) *ReaderChunk
func (*StreamNetConn) WriteWhole ¶ added in v1.3.0
func (s *StreamNetConn) WriteWhole(bb []byte) error
type StreamingHTTPProxyServerOptions ¶
type StreamingHTTPProxyServerOptions struct { Bind string MaxtimeNoProgress time.Duration MaxtimeTotal time.Duration Log zerolog.Logger RequestObjectHandleFunc func(req_h *HttpObjectHead) ReplyObjectHandleFunc func(repl_h *HttpObjectHead, req_h *HttpObjectHead) (ok bool) // req is passed to be able to match the two AcceptConnectionCallback func(conn net.Conn) (canProceedOk bool) EndConnectionCallback func() ConnectionsRegistry *ConnectionsRegistry WG_All_Gs sync.WaitGroup CommandCh chan CommandMsg }
type TreeMux ¶
type TreeMux struct { Group // The default PanicHandler just returns a 500 code. PanicHandler PanicHandleFunc // The default NotFoundHandler is http.NotFound. NotFoundHandler func(h *HttpObjectHead) // Any OPTIONS request that matches a path without its own OPTIONS handler will use this handler, // if set, instead of calling MethodNotAllowedHandler. OptionsVerb *LeafVerb // MethodNotAllowedHandler is called when a pattern matches, but that // pattern does not have a handler for the requested method. The default // handler just writes the status code http.StatusMethodNotAllowed and adds // the required Allowed header. // The methods parameter contains the map of each method to the corresponding // handler function. MethodNotAllowedHandler func(h *HttpObjectHead, methods map[string]*LeafVerb) // HeadCanUseGet allows the router to use the GET handler to respond to // HEAD requests if no explicit HEAD handler has been added for the // matching pattern. This is true by default. HeadCanUseGet bool // RedirectCleanPath allows the router to try clean the current request path, // if no handler is registered for it, using CleanPath from github.com/dimfeld/httppath. // This is true by default. RedirectCleanPath bool // RedirectTrailingSlash enables automatic redirection in case router doesn't find a matching route // for the current request path but a handler for the path with or without the trailing // slash exists. This is true by default. RedirectTrailingSlash bool // RemoveCatchAllTrailingSlash removes the trailing slash when a catch-all pattern // is matched, if set to true. By default, catch-all paths are never redirected. RemoveCatchAllTrailingSlash bool // RedirectBehavior sets the default redirect behavior when RedirectTrailingSlash or // RedirectCleanPath are true. The default value is Redirect301. RedirectBehavior RedirectBehavior // RedirectMethodBehavior overrides the default behavior for a particular HTTP method. // The key is the method name, and the value is the behavior to use for that method. RedirectMethodBehavior map[string]RedirectBehavior // EscapeAddedRoutes controls URI escaping behavior when adding a route to the tree. // If set to true, the router will add both the route as originally passed, and // a version passed through URL.EscapedPath. This behavior is disabled by default. EscapeAddedRoutes bool // SafeAddRoutesWhileRunning tells the router to protect all accesses to the tree with an RWMutex. This is only needed // if you are going to add routes after the router has already begun serving requests. There is a potential // performance penalty at high load. SafeAddRoutesWhileRunning bool // CaseInsensitive determines if routes should be treated as case-insensitive. CaseInsensitive bool Log zerolog.Logger // contains filtered or unexported fields }
func (*TreeMux) DispatchRouterHandler ¶ added in v1.3.34
func (t *TreeMux) DispatchRouterHandler(h *HttpObjectHead)