func (t *testRoute) Handler() routem.HandlerFunc { if t.handler != nil { return t.handler } return func(ctx context.Context) routem.HTTPError { if 2 == ctx.Value(secondKey) { return nil } return routem.NewHTTPError(500, fmt.Errorf("Value 2 not in context.")) } }
func TestErrorRouteErrorHandler(t *testing.T) { routes := []routem.Route{ &testRoute{ path: "/test", handler: func(ctx context.Context) routem.HTTPError { return routem.NewHTTPError(304, fmt.Errorf("Moved Permanently!")) }, errorHandler: func(err routem.HTTPError, ctx context.Context) error { return fmt.Errorf("Error handling an error: %v", err) }, }, } response := assertServer(t, routes, routem.Get, "http://localhost/test") assert.Equal(t, 500, response.Code) }
func (root *rootNode) ServeHTTP(response http.ResponseWriter, request *http.Request) { parts := strings.Split(request.URL.Path, "/") routeInfo, err := root.find(parts, routem.Method(request.Method)) timeout := routem.DefaultTimeout if err == nil { timeout = routeInfo.route.Timeout() } ctx, cancel := routem.NewRequestContext( root.ctx, timeout, request, response, routeParams(routeInfo, parts)) defer cancel() if err == nil { complete := make(chan routem.HTTPError) go func() { complete <- routeInfo.handler(ctx) }() select { case <-ctx.Done(): err = routem.NewHTTPError(408, fmt.Errorf("Request Timed Out!")) case err = <-complete: } } if err != nil { var errErr error if routeInfo != nil && routeInfo.route.ErrorHandler() != nil { errErr = routeInfo.route.ErrorHandler()(err, ctx) } else if root.errorHandler != nil { errErr = root.errorHandler(err, ctx) } else if err == routeNotFoundError { http.Error(response, fmt.Sprintf("Route Not Found: %s", errErr), http.StatusNotFound) } else { errErr = err } if errErr != nil { http.Error(response, fmt.Sprintf("Internal Server Error: %s", errErr), http.StatusInternalServerError) } } }
func TestRouteErrorHandler(t *testing.T) { routes := []routem.Route{ &testRoute{ path: "/test", handler: func(ctx context.Context) routem.HTTPError { return routem.NewHTTPError(304, fmt.Errorf("Moved Permanently!")) }, errorHandler: func(err routem.HTTPError, ctx context.Context) error { response := routem.ResponseWriterFromContext(ctx) http.Error(response, "Converted to 400", 400) return nil }, }, } response := assertServer(t, routes, routem.Get, "http://localhost/test") assert.Equal(t, 400, response.Code) }
func (t *testRoute) Middlewares() []routem.MiddlewareFunc { return []routem.MiddlewareFunc{ func(next routem.HandlerFunc) routem.HandlerFunc { return func(ctx context.Context) routem.HTTPError { ctx = context.WithValue(ctx, firstKey, 1) return next(ctx) } }, func(next routem.HandlerFunc) routem.HandlerFunc { return func(ctx context.Context) routem.HTTPError { if 1 == ctx.Value(firstKey) { ctx = context.WithValue(ctx, secondKey, 2) return next(ctx) } return routem.NewHTTPError(500, fmt.Errorf("First value not in context.")) } }, } }
if !inserted && err == nil { newChild, err := newNode(parts[1]) if err == nil { n.children[newChild.path] = newChild inserted, err = newChild.insert(parts[1:], route, depth+1, params) } } } } return inserted, err } var routeNotFoundError = routem.NewHTTPError(http.StatusNotFound, fmt.Errorf("No Such Route")) func (n *node) find(parts []string, method routem.Method) (*routeInfo, routem.HTTPError) { var info *routeInfo = nil var err routem.HTTPError = nil // Did we fish our wish? if n.path == ":" || parts[0] == n.path { // Did we run out of parts? if len(parts) == 1 { info = n.routes[method] } else { // Search all the children subParts := parts[1:]