2016-10-06 6 views
0

httprouterの機能のようなexpressjsを実装しようとしています。 私は私がしたかった主なものであるNewRoutes機能を持つ構造体type mounterGolang httpRouterは、関数のスライスと共に使用されたときに最後の応答を返します

type Mounter struct { 
    BasePath string 
    Routes []*Route 
} 

とsubRoutes

type Route struct { 
    Path string 
    Method string 
    Func Handle 
} 

type Handle func(http.ResponseWriter, *http.Request, Params)

type Params interface{}

を表しRoute構造体を作成しますexpressjsの新しいルートからのポートはexpress.Router

func NewRoutes(base string) (mounter *Mounter) { 
    mounter = &Mounter{ 
     BasePath: base, 
    } 
    return 
} 

と私は*Mounter

//GET request handler 
func (mounter *Mounter) GET(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "get", Func}) 
} 

//POST request handler 
func (mounter *Mounter) POST(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "post", Func}) 
} 

//PUT request handler 
func (mounter *Mounter) PUT(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "put", Func}) 
} 

//DELETE request handler 
func (mounter *Mounter) DELETE(path string, Func Handle) { 
    mounter.Routes = append(mounter.Routes, &Route{path, "delete", Func}) 
} 

get post put deleteメソッドを持っており、最終的に私は

func (mounter *Mounter) Mount(router *rtr.Router) { 
    mounter.BasePath = strings.TrimSuffix(mounter.BasePath, "/") 
    for _, route := range mounter.Routes { 
     path := route.Path 
     if !strings.HasSuffix(path, "/") { 
      path += "/" 
     } 
     path = mounter.BasePath + path 
     switch strings.ToLower(route.Method) { 
     case "get": 
      router.GET(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     case "post": 
      router.POST(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     case "delete": 
      router.DELETE(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     case "put": 
      router.PUT(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
       route.Func(res, req, params) 
      }) 
     } 
    } 
} 

すべての作品、実際のルータにルータをマウントマウント方法を持っていると同じことかなりいいですし、メソッドが正常に動作しています。もし私がポストリクエストをエンドポイントに送信しようとすると、それは素晴らしい404を与えますが、唯一の問題は、それは常に最後に追加されたメンバーのハンドラで応答しているにかかわらず、サブパスのよう

package api 
var ApiRouter = express.NewRoutes("/api/") 

func init() { 
    ApiRouter.GET("/", func(res http.ResponseWriter, req *http.Request, _ express.Params) { 
     fmt.Fprintln(res, "testget/") 
    }) 
    ApiRouter.GET("/pt", func(res http.ResponseWriter, req *http.Request, _ express.Params) { 
     fmt.Fprintln(res, "pt") 
    }) 
    ApiRouter.POST("/test", func(res http.ResponseWriter, req *http.Request, _ express.Params) { 
     fmt.Fprintln(res, "test/post") 
    }) 
} 

package main 
func main() { 
    router := express.New() 
    api.ApiRouter.Mount(router) 
    for _, route := range api.ApiRouter.Routes { 
     fmt.Println(*route) 
    } 
    router.ServeFiles("/public/*filepath", http.Dir("./public/")) 
    http.ListenAndServe(":1024", router) 
} 

は常にtest/postを応答しますと私はテスト目的のために上記のやっているrangeの出力は あるので、あなたはいずれかを持っています常に同じ機能を使用して応答するが、パスを完全に認識する理由

答えて

1

Iteration Variables and Closuresとして知られているMountメソッドに問題があります。キャプチャのための新しい変数を宣言します。route

thisRoute := route //capture iteration variable 
switch strings.ToLower(route.Method) { 
case "get": 
    router.GET(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
     thisRoute.Func(res, req, params) 
    }) 
case "post": 
    router.POST(path, func(res http.ResponseWriter, req *http.Request, params rtr.Params) { 
     thisRoute.Func(res, req, params) 
    }) 
//... 
} 
+0

ワウが私の問題を解決しました。 – nikoss

関連する問題