3

問題: ミドルウェアから mux.CurrentRoute(r).GetName() にアクセスできません。(ミドルウェアからアクセスできましたが、以前はリクエストにアクセスできなかったため、ミドルウェアの動作方法を変更する必要がありました)。そのため、何かをいじってしまい、ルート名にアクセスできる作業状態に戻す方法がわかりません。

どんな助けでも大歓迎です!

エラー:

runtime error: invalid memory address or nil pointer dereference 

コード:

func main() {
    var (
        err          error
        r            *mux.Router
        devRouter    *mux.Router
        usersRouter  *mux.Router
        brandsRouter *mux.Router
    )
    defer db.Close()
    defer store.Close()

    r = mux.NewRouter()
    devRouter = r.PathPrefix("/api/v1/dev").Subrouter()
    usersRouter = r.PathPrefix("/api/v1/users").Subrouter()
    brandsRouter = r.PathPrefix("/api/v1/brands").Subrouter()

    // development endpoints
    devRouter.HandleFunc("/db/seed", devDbSeed)
    ...

    // users
    usersRouter.HandleFunc("/create", usersCreateHandlerFunc).Methods("POST").Name("USERS_CREATE")
    ...

    // brands
    brandsRouter.HandleFunc("/create", brandsCreateHandlerFunc).Methods("POST").Name("BRANDS_CREATE")
    ...

    // products
    brandsRouter.HandleFunc("/{brand_id:[0-9]+}/products", brandsProductsListHandlerFunc).Methods("GET").Name("BRANDS_PRODUCTS_LIST")
    ...

    // mwAuthorize and mwAuthenticate basically work the same
    mw := []func(http.Handler) http.Handler{mwAuthenticate, mwAuthorize}
    http.Handle("/", use(r, mw...))
    err = http.ListenAndServe(":9000", nil)
    if err != nil {
         logIt(err)
    }
}

func use(h http.Handler, mw ...func(http.Handler) http.Handler) http.Handler {
    // exec order: mw[0],mw[1],mw[N]...
    for i := len(mw) - 1; i >= 0; i-- {
        h = mw[i](h)
    }
    return h
}

func mwAuthorize(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
         if true != authorize(r) {
            w.WriteHeader(http.StatusForbidden)
            return
         } else {
            next.ServeHTTP(w, r)
         }
     })
}

func authorize(r *http.Request) (isAuthorized bool) {
    isAuthorized = false
    /**
       This is where it's failing!
    */
    routeName := mux.CurrentRoute(r).GetName()
    switch routeName {
    case "USERS_CREATE":
        // route-specific authorization
        break
    ...
    default:
        break
    }
    return
}

更新 (2015-01-04 @ 4:49PM EST): したがって、ミドルウェアを削除した後 (または、少なくとも mux.CurrentRoute を読み取ろうとしているセクションをコメントアウトした後)、宛先の handlerfunc からルート名を取得できます (例: usersCreateHandlerFunc または BrandsCreateHandlerFunc)。これは私の問題を解決しません (すべての handlerfunc とは対照的に、ミドルウェアで認証/承認を実行したいのですが)、*mux.Router は最終的な後までミドルウェアで使用できないことを知らせてくれる予感があります。 .ServeHTTP 呼び出し。(または、それらの線に沿った何か...)

更新 (2015 年 1 月 4 日 @ 午後 5 時 41 分 EST): Negroni をミドルウェア コンポーネントとして使用する別の方向 (あまり好まれませんが) を試しました。mux.CurrentRoute を取得しようとすると、まだ nil-pointer エラーが発生します。

更新 (2015-01-04 @ 6:17PM EST): ミドルウェア機能からリクエスト (例: r.URL) にアクセスできますが、mux.Route (例: mux.CurrentRoute( r)))。マルチプレクサのソースをもう少し調べたところ、ルーターがまだマッチャーを実行していないため、現在のマルチプレクサ コンテキストが設定されていないことが原因だと思います (したがって、ミドルウェアが処理されるまで現在のルートがわからないためです)。完了です)。ただし、これを解決する方法、またはこれを処理するためにコードを再構築する方法はまだわかりません。

4

3 に答える 3

2

どうですか:

routeName := mux.CurrentRoute(r).GetName()

はどこrですか*http.Request。インポートすることを忘れないでください"github.com/gorilla/mux"。これを使用するには、ルートを定義するときに名前を付ける必要があることに注意してください。

于 2020-07-22T01:39:31.407 に答える