Skip to content

Commit

Permalink
emicklei#59 continued: reworked router/container so errors are bubble…
Browse files Browse the repository at this point in the history
…d up and dealt with at the container level as to not interefere with filters
  • Loading branch information
jchenry committed Oct 12, 2013
1 parent 521f870 commit 9af6c64
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 32 deletions.
21 changes: 17 additions & 4 deletions container.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,28 @@ func (c *Container) dispatch(httpWriter http.ResponseWriter, httpRequest *http.R
}()
}
}
// Find best match Route ; detected is false if no match was found
webService, route, detected := c.router.SelectRoute(
// Find best match Route ; err is non nil if no match was found
webService, route, err := c.router.SelectRoute(
c.webServices,
httpWriter,
httpRequest)
if !detected {
if err != nil {
// a non-200 response has already been written
// run container filters anyway ; they should not touch the response...
chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) {}} // nop
chain := FilterChain{Filters: c.containerFilters, Target: func(req *Request, resp *Response) {
switch err.(type) {
case ServiceError:
ser := err.(ServiceError)
httpWriter.WriteHeader(ser.Code)
httpWriter.Write([]byte(ser.Message))
default:
}

// err

// handle err here

}}
chain.ProcessFilter(newRequest(httpRequest), newResponse(writer))
return
}
Expand Down
27 changes: 14 additions & 13 deletions curly.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package restful

import (
// "log"
"errors"
"net/http"
"sort"
"strings"
Expand All @@ -19,23 +20,23 @@ type CurlyRouter struct{}
func (c CurlyRouter) SelectRoute(
webServices []*WebService,
httpWriter http.ResponseWriter,
httpRequest *http.Request) (selectedService *WebService, selected *Route, ok bool) {
httpRequest *http.Request) (selectedService *WebService, selected *Route, err error) {

requestTokens := tokenizePath(httpRequest.URL.Path)

detectedService := c.detectWebService(requestTokens, webServices)
if detectedService == nil {
return nil, nil, false
return nil, nil, errors.New("no detected service")
}
candidateRoutes := c.selectRoutes(detectedService, httpWriter, requestTokens)
if len(candidateRoutes) == 0 {
return detectedService, nil, false
return detectedService, nil, errors.New("no candidate routes")
}
selectedRoute := c.detectRoute(candidateRoutes, httpWriter, httpRequest)
selectedRoute, err := c.detectRoute(candidateRoutes, httpWriter, httpRequest)
if selectedRoute == nil {
return detectedService, nil, false
return detectedService, nil, err
}
return detectedService, selectedRoute, true
return detectedService, selectedRoute, nil
}

func (c CurlyRouter) selectRoutes(ws *WebService, httpWriter http.ResponseWriter, requestTokens []string) []Route {
Expand Down Expand Up @@ -68,13 +69,13 @@ func (c CurlyRouter) matchesRouteByPathTokens(routeTokens, requestTokens []strin
return true, paramCount, staticCount
}

func (c CurlyRouter) detectRoute(candidateRoutes []Route, httpWriter http.ResponseWriter, httpRequest *http.Request) *Route {
route, found := RouterJSR311{}.detectRoute(candidateRoutes, httpWriter, httpRequest) // TODO change signature
if found {
return route
} else {
return nil
}
func (c CurlyRouter) detectRoute(candidateRoutes []Route, httpWriter http.ResponseWriter, httpRequest *http.Request) (*Route, error) {
return RouterJSR311{}.detectRoute(candidateRoutes, httpWriter, httpRequest) // TODO change signature
// if found != nil{
// return route
// } else {
// return nil
// }
}

func (c CurlyRouter) detectWebService(requestTokens []string, webServices []*WebService) *WebService {
Expand Down
28 changes: 14 additions & 14 deletions jsr311.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ type RouterJSR311 struct{}
func (r RouterJSR311) SelectRoute(
webServices []*WebService,
httpWriter http.ResponseWriter,
httpRequest *http.Request) (selectedService *WebService, selectedRoute *Route, ok bool) {
httpRequest *http.Request) (selectedService *WebService, selectedRoute *Route, err error) {

// Identify the root resource class (WebService)
dispatcher, finalMatch, err := r.detectDispatcher(httpRequest.URL.Path, webServices)
if err != nil {
httpWriter.WriteHeader(http.StatusNotFound)
return nil, nil, false
// httpWriter.WriteHeader(http.StatusNotFound)
return nil, nil, NewError(http.StatusNotFound, "")
}
// Obtain the set of candidate methods (Routes)
routes := r.selectRoutes(dispatcher, finalMatch)
Expand All @@ -38,7 +38,7 @@ func (r RouterJSR311) SelectRoute(
}

// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2
func (r RouterJSR311) detectRoute(routes []Route, httpWriter http.ResponseWriter, httpRequest *http.Request) (*Route, bool) {
func (r RouterJSR311) detectRoute(routes []Route, httpWriter http.ResponseWriter, httpRequest *http.Request) (*Route, error) {
// http method
methodOk := []Route{}
for _, each := range routes {
Expand All @@ -47,9 +47,9 @@ func (r RouterJSR311) detectRoute(routes []Route, httpWriter http.ResponseWriter
}
}
if len(methodOk) == 0 {
httpWriter.WriteHeader(http.StatusMethodNotAllowed)
httpWriter.Write([]byte("405: Method Not Allowed"))
return nil, false
// httpWriter.WriteHeader(http.StatusMethodNotAllowed)
// httpWriter.Write([]byte())
return nil, NewError(http.StatusMethodNotAllowed, "405: Method Not Allowed")
}
inputMediaOk := methodOk
// content-type
Expand All @@ -62,9 +62,9 @@ func (r RouterJSR311) detectRoute(routes []Route, httpWriter http.ResponseWriter
}
}
if len(inputMediaOk) == 0 {
httpWriter.WriteHeader(http.StatusUnsupportedMediaType)
httpWriter.Write([]byte("415: Unsupported Media Type"))
return nil, false
// httpWriter.WriteHeader(http.StatusUnsupportedMediaType)
// httpWriter.Write([]byte("415: Unsupported Media Type"))
return nil, NewError(http.StatusUnsupportedMediaType, "415: Unsupported Media Type")
}
}
// accept
Expand All @@ -79,11 +79,11 @@ func (r RouterJSR311) detectRoute(routes []Route, httpWriter http.ResponseWriter
}
}
if len(outputMediaOk) == 0 {
httpWriter.WriteHeader(http.StatusNotAcceptable)
httpWriter.Write([]byte("406: Not Acceptable"))
return &Route{}, false
// httpWriter.WriteHeader(http.StatusNotAcceptable)
// httpWriter.Write([]byte("406: Not Acceptable"))
return &Route{}, NewError(http.StatusNotAcceptable, "406: Not Acceptable")
}
return r.bestMatchByMedia(outputMediaOk, contentType, accept), true
return r.bestMatchByMedia(outputMediaOk, contentType, accept), nil
}

// http://jsr311.java.net/nonav/releases/1.1/spec/spec3.html#x3-360003.7.2
Expand Down
2 changes: 1 addition & 1 deletion router.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ type RouteSelector interface {
SelectRoute(
webServices []*WebService,
httpWriter http.ResponseWriter,
httpRequest *http.Request) (selectedService *WebService, selected *Route, ok bool)
httpRequest *http.Request) (selectedService *WebService, selected *Route, err error)
}

0 comments on commit 9af6c64

Please sign in to comment.