diff --git a/beego.go b/beego.go
index 3286cf40..f8f89ac7 100644
--- a/beego.go
+++ b/beego.go
@@ -207,6 +207,11 @@ func Router(path string, c ControllerInterface) *App {
return BeeApp
}
+func RouterHandler(path string, c http.Handler) *App {
+ BeeApp.Handlers.AddHandler(path, c)
+ return BeeApp
+}
+
func Filter(filter http.HandlerFunc) *App {
BeeApp.Filter(filter)
return BeeApp
diff --git a/example/chat/chat.go b/example/chat/chat.go
new file mode 100644
index 00000000..09005753
--- /dev/null
+++ b/example/chat/chat.go
@@ -0,0 +1,42 @@
+package main
+
+import (
+ "fmt"
+ "github.com/astaxie/beego"
+ "github.com/fzzy/sockjs-go/sockjs"
+ "strings"
+)
+
+var users *sockjs.SessionPool = sockjs.NewSessionPool()
+
+func chatHandler(s sockjs.Session) {
+ users.Add(s)
+ defer users.Remove(s)
+
+ for {
+ m := s.Receive()
+ if m == nil {
+ break
+ }
+ fullAddr := s.Info().RemoteAddr
+ addr := fullAddr[:strings.LastIndex(fullAddr, ":")]
+ m = []byte(fmt.Sprintf("%s: %s", addr, m))
+ users.Broadcast(m)
+ }
+}
+
+type MainController struct {
+ beego.Controller
+}
+
+func (m *MainController) Get() {
+ m.TplNames = "index.html"
+}
+
+func main() {
+ conf := sockjs.NewConfig()
+ sockjshandler := sockjs.NewHandler("/chat", chatHandler, conf)
+ beego.Router("/", &MainController{})
+ beego.RouterHandler("/chat/:info(.*)", sockjshandler)
+ beego.Run()
+}
diff --git a/example/chat/views/index.html b/example/chat/views/index.html
new file mode 100644
index 00000000..12e5616b
--- /dev/null
+++ b/example/chat/views/index.html
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+ Sockjs-go chat
+
+
+ Sockjs-go chat
+
+
+ Status: disconnected
+
+
+
+
+
+
\ No newline at end of file
diff --git a/router.go b/router.go
index 3a1dd2a8..4e7b6c17 100644
--- a/router.go
+++ b/router.go
@@ -16,14 +16,22 @@ type controllerInfo struct {
controllerType reflect.Type
}
+type userHandler struct {
+ pattern string
+ regex *regexp.Regexp
+ params map[int]string
+ h http.Handler
+}
+
type ControllerRegistor struct {
- routers []*controllerInfo
- fixrouters []*controllerInfo
- filters []http.HandlerFunc
+ routers []*controllerInfo
+ fixrouters []*controllerInfo
+ filters []http.HandlerFunc
+ userHandlers map[string]*userHandler
}
func NewControllerRegistor() *ControllerRegistor {
- return &ControllerRegistor{routers: make([]*controllerInfo, 0)}
+ return &ControllerRegistor{routers: make([]*controllerInfo, 0), userHandlers: make(map[string]*userHandler)}
}
func (p *ControllerRegistor) Add(pattern string, c ControllerInterface) {
@@ -77,6 +85,52 @@ func (p *ControllerRegistor) Add(pattern string, c ControllerInterface) {
}
+func (p *ControllerRegistor) AddHandler(pattern string, c http.Handler) {
+ parts := strings.Split(pattern, "/")
+
+ j := 0
+ params := make(map[int]string)
+ for i, part := range parts {
+ if strings.HasPrefix(part, ":") {
+ expr := "([^/]+)"
+ //a user may choose to override the defult expression
+ // similar to expressjs: ‘/user/:id([0-9]+)’
+ if index := strings.Index(part, "("); index != -1 {
+ expr = part[index:]
+ part = part[:index]
+ }
+ params[j] = part
+ parts[i] = expr
+ j++
+ }
+ }
+ if j == 0 {
+ //now create the Route
+ uh := &userHandler{}
+ uh.pattern = pattern
+ uh.h = c
+ p.userHandlers[pattern] = uh
+ } else { // add regexp routers
+ //recreate the url pattern, with parameters replaced
+ //by regular expressions. then compile the regex
+ pattern = strings.Join(parts, "/")
+ regex, regexErr := regexp.Compile(pattern)
+ if regexErr != nil {
+ //TODO add error handling here to avoid panic
+ panic(regexErr)
+ return
+ }
+
+ //now create the Route
+ uh := &userHandler{}
+ uh.regex = regex
+ uh.params = params
+ uh.pattern = pattern
+ uh.h = c
+ p.userHandlers[pattern] = uh
+ }
+}
+
// Filter adds the middleware filter.
func (p *ControllerRegistor) Filter(filter http.HandlerFunc) {
p.filters = append(p.filters, filter)
@@ -143,6 +197,43 @@ func (p *ControllerRegistor) ServeHTTP(rw http.ResponseWriter, r *http.Request)
requestPath := r.URL.Path
+ //user defined Handler
+ for pattern, c := range p.userHandlers {
+ if c.regex == nil && pattern == requestPath {
+ c.h.ServeHTTP(rw, r)
+ return
+ } else if c.regex == nil {
+ continue
+ }
+
+ //check if Route pattern matches url
+ if !c.regex.MatchString(requestPath) {
+ continue
+ }
+
+ //get submatches (params)
+ matches := c.regex.FindStringSubmatch(requestPath)
+
+ //double check that the Route matches the URL pattern.
+ if len(matches[0]) != len(requestPath) {
+ continue
+ }
+
+ if len(c.params) > 0 {
+ //add url parameters to the query param map
+ values := r.URL.Query()
+ for i, match := range matches[1:] {
+ values.Add(c.params[i], match)
+ params[c.params[i]] = match
+ }
+ //reassemble query params and add to RawQuery
+ r.URL.RawQuery = url.Values(values).Encode() + "&" + r.URL.RawQuery
+ //r.URL.RawQuery = url.Values(values).Encode()
+ }
+ c.h.ServeHTTP(rw, r)
+ return
+ }
+
//first find path from the fixrouters to Improve Performance
for _, route := range p.fixrouters {
n := len(requestPath)