更流畅的FileServe和Routing合作

huangapple go评论73阅读模式
英文:

More fluent cooperation of FileServe and Routing

问题

我有一个问题,我想在FileServe上为我的主要AngularJS(Yeoman部署)应用程序文件夹提供服务,路径为/,但这将破坏我的所有路由绑定。有没有办法我可以保留它们并保持我的路由完整?

在下面的代码中,我仍然需要转到/app并重新绑定其他文件夹,因为我不想过多地修改Grunt文件,所以为文件夹添加了一些额外的备份路径绑定。

func initializeRoutes() {
    // 处理所有请求,通过提供相同名称的文件来提供服务
    fileHandler := http.FileServer(http.Dir(*clFlagStaticDirectory))
    bowerFileHandler := http.FileServer(http.Dir("../bower_components"))
    imagesFileHandler := http.FileServer(http.Dir("../app/images"))
    scriptsFileHandler := http.FileServer(http.Dir("../app/scripts"))
    stylesFileHandler := http.FileServer(http.Dir("../app/styles"))
    viewsFileHandler := http.FileServer(http.Dir("../app/views"))

    // 设置路由
    mainRoute := mux.NewRouter()
    mainRoute.StrictSlash(true)
    // mainRoute.Handle("/", http.RedirectHandler("/static/", 302))
    mainRoute.PathPrefix("/app").Handler(http.StripPrefix("/app", fileHandler))
    mainRoute.PathPrefix("/app/bower_components").Handler(http.StripPrefix("/bower_components", bowerFileHandler))
    mainRoute.PathPrefix("/bower_components").Handler(http.StripPrefix("/bower_components", bowerFileHandler))
    mainRoute.PathPrefix("/images").Handler(http.StripPrefix("/images", imagesFileHandler))
    mainRoute.PathPrefix("/scripts").Handler(http.StripPrefix("/scripts", scriptsFileHandler))
    mainRoute.PathPrefix("/styles").Handler(http.StripPrefix("/styles", stylesFileHandler))
    mainRoute.PathPrefix("/views").Handler(http.StripPrefix("/views", viewsFileHandler))

    // 基本路由
    // 用户路由
    userRoute := mainRoute.PathPrefix("/users").Subrouter()
    userRoute.Handle("/login", handler(userDoLogin)).Methods("POST")
    userRoute.Handle("/logout", handler(userDoLogout)).Methods("GET")
    userRoute.Handle("/forgot_password", handler(forgotPassword)).Methods("POST")

    // 绑定API路由
    apiRoute := mainRoute.PathPrefix("/api").Subrouter()

    apiProductModelRoute := apiRoute.PathPrefix("/productmodels").Subrouter()
    apiProductModelRoute.Handle("/", handler(listProductModels)).Methods("GET")
    apiProductModelRoute.Handle("/{id}", handler(getProductModel)).Methods("GET")

    // 绑定通用路由
    http.Handle("/", mainRoute)
}

所以我的目标是将/app作为我的/主路径进行服务,但保留所有的Mux路由以覆盖FileServe。所以如果我有一个/app/users/login文件夹,它不会加载,而是让路由器生效。

注意:我纯粹通过HTTPS提供服务,没有通过HTTP

非常感谢!这让我很困惑,这是我在开始我的前端代码之前需要解决的最后一件事情 :).

英文:

I have an issue where I want to serve my main AngularJS (Yeoman deployment) app folder on FileServe / but it will destroy all my router bindings. Is there any way I can reserve them and keep my routes in-tact?

In the code below I still have to go to /app and re-bind the other folders, because I don't want to temper with the Grunt file too much (yet), so added some extra backup path-bindings for the folders.

func initializeRoutes() {
// Handle all requests by serving a file of the same name
fileHandler := http.FileServer(http.Dir(*clFlagStaticDirectory))
bowerFileHandler := http.FileServer(http.Dir("../bower_components"))
imagesFileHandler := http.FileServer(http.Dir("../app/images"))
scriptsFileHandler := http.FileServer(http.Dir("../app/scripts"))
stylesFileHandler := http.FileServer(http.Dir("../app/styles"))
viewsFileHandler := http.FileServer(http.Dir("../app/views"))
// Setup routes
mainRoute := mux.NewRouter()
mainRoute.StrictSlash(true)
// mainRoute.Handle("/", http.RedirectHandler("/static/", 302))
mainRoute.PathPrefix("/app").Handler(http.StripPrefix("/app", fileHandler))
mainRoute.PathPrefix("/app/bower_components").Handler(http.StripPrefix("/bower_components", bowerFileHandler))
mainRoute.PathPrefix("/bower_components").Handler(http.StripPrefix("/bower_components", bowerFileHandler))
mainRoute.PathPrefix("/images").Handler(http.StripPrefix("/images", imagesFileHandler))
mainRoute.PathPrefix("/scripts").Handler(http.StripPrefix("/scripts", scriptsFileHandler))
mainRoute.PathPrefix("/styles").Handler(http.StripPrefix("/styles", stylesFileHandler))
mainRoute.PathPrefix("/views").Handler(http.StripPrefix("/views", viewsFileHandler))
// Basic routes
// User routes
userRoute := mainRoute.PathPrefix("/users").Subrouter()
userRoute.Handle("/login", handler(userDoLogin)).Methods("POST")
userRoute.Handle("/logout", handler(userDoLogout)).Methods("GET")
userRoute.Handle("/forgot_password", handler(forgotPassword)).Methods("POST")
// Bind API Routes
apiRoute := mainRoute.PathPrefix("/api").Subrouter()
apiProductModelRoute := apiRoute.PathPrefix("/productmodels").Subrouter()
apiProductModelRoute.Handle("/", handler(listProductModels)).Methods("GET")
apiProductModelRoute.Handle("/{id}", handler(getProductModel)).Methods("GET")
// Bind generic route
http.Handle("/", mainRoute)
}

So my goal is the serve /app as my / main path, but reserve all my Mux Routes to win over the FileServe. So if I'll have a /app/users/login folder, it won't load, but instead it will let the Router win.

Note: I'm serving purely over HTTPS and nothing over HTTP.

Thanks so much in advance! This is breaking my brain and it's the last thing I need to figure out before I can fully start on my front-end code :).

答案1

得分: 1

看起来你想要改变路由的评估顺序,使得/users/login等路径在/之前匹配,而/路径应该由FileServer处理。

据我所知,路由将按照它们被定义的顺序进行匹配(添加到路由器中)。所以你只需要将API和其他动态路由放在/之前即可。

以下代码可以实现类似的功能:

  • /test路径的匹配在文件服务器之前进行评估,并返回字符串"OK"
  • 然后文件服务器返回路径下的文件

代码:

package main

import (
	"github.com/gorilla/mux"
	"net/http"
)

func main() {
	appFileHandler := http.FileServer(http.Dir("/Users/alex/Projects/tmp/so/app"))
	r := mux.NewRouter()
	r.PathPrefix("/test").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
		w.Write([]byte("OK"))
	})
	r.PathPrefix("/").Handler(appFileHandler)
	http.Handle("/", r)
	http.ListenAndServe(":8080", nil)
}

希望对你有帮助!

英文:

It looks for me like you want to change the order of how the routes are evaluated in a way that /users, /login, and similar are matched before the /. And the / should be server by the FileServer.

As far as I know, the routes will be matched in the order they are defined (added to the router). So you just have to move your API and other dynamic routes before /.

The following code works similar:

  • the /test match is evaluated before the file server and returns the string "OK"
  • then the file server returns the file under the path

Code:

package main
import (
"github.com/gorilla/mux"
"net/http"
)
func main() {
appFileHandler := http.FileServer(http.Dir("/Users/alex/Projects/tmp/so/app"))
r := mux.NewRouter()
r.PathPrefix("/test").HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Write([]byte("OK"))
})
r.PathPrefix("/").Handler(appFileHandler)
http.Handle("/", r)
http.ListenAndServe(":8080", nil)
}

huangapple
  • 本文由 发表于 2015年7月26日 20:23:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/31636909.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定