我在 Flutter Web 中有一个项目,我想为该项目创建一个纯 HTML 的登录页面,用于 SEO 目的。 我的目的是创建一个服务于具有更高优先级的静态文件的服务器,如果静态 HTML 文件会在请求时返回错误,则应使用构建的 Flutter Web 项目作为后备。
我在 Golang 中创建了这个服务器:
package main
import (
"net/http"
)
func main() {
http.ListenAndServe(":2000", professionalServer{})
}
type professionalServer struct{}
var flutterServer = http.FileServer(http.FileSystem(http.Dir("../../../professional/build/web")))
var staticServer = http.FileServer(http.FileSystem(http.Dir("../../../professional/landing-page/dist")))
func (professionalServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
res := preflightResponseWriter{OutputData: make(map[string]int)}
staticServer.ServeHTTP(res, r)
if res.OutputData["status_code"] == 200 {
staticServer.ServeHTTP(w, r)
} else {
flutterServer.ServeHTTP(w, r)
}
}
type preflightResponseWriter struct {
OutputData map[string]int
}
func (preflightResponseWriter) Header() http.Header {
return http.Header{}
}
func (preflightResponseWriter) Write([]byte) (int, error) {
return 0, nil
}
func (p preflightResponseWriter) WriteHeader(statusCode int) {
p.OutputData["status_code"] = statusCode
}
这实际上是可行的,但问题是 Flutter Web 使用散列格式作为路由(即 http://website.com/#/dashboard)并且浏览器不发送散列标签之后的部分,所以我的 golang 服务器看到 {{ 3}},然后它检查静态文件服务器是否可以处理这个 URL,它可以处理,因此静态文件服务器发送响应。
我该如何解决这个问题?是否可以将完整的 URL 发送到服务器,包括 # 后面的部分?
提前感谢您的帮助!
从@ResamVi 得到的建议启发了我如何解决这个问题: 我按照答案中的步骤操作,以便我的应用程序最终拥有基本的 href /app/。
然后,为了使服务器正常工作,我对我的服务器文件进行了以下更改:
package main
import (
"net/http"
"strings"
)
func main() {
http.ListenAndServe(":2000", professionalServer{})
}
type professionalServer struct{}
var flutterServer = http.StripPrefix("/app/", http.FileServer(http.FileSystem(http.Dir("../../../professional/build/web"))))
var staticServer = http.FileServer(http.FileSystem(http.Dir("../../../professional/landing-page/dist")))
func (professionalServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if strings.HasPrefix(r.URL.Path, "/app") {
rw := preflightResponseWriter{OutputData: make(map[string]int)}
flutterServer.ServeHTTP(rw, r)
if rw.OutputData["status_code"] >= 400 && rw.OutputData["status_code"] < 500 {
http.ServeFile(w, r, "../../../professional/build/web/index.html")
} else {
flutterServer.ServeHTTP(w, r)
}
} else {
staticServer.ServeHTTP(w, r)
}
// check if starts with /app
// if no -> staticServer
// if yes:
// simulate request, check if response code is ok
// if response code is ok, serve via flutterServer.Serve
// else serve file directly
}
type preflightResponseWriter struct {
OutputData map[string]int
}
func (preflightResponseWriter) Header() http.Header {
return http.Header{}
}
func (preflightResponseWriter) Write([]byte) (int, error) {
return 0, nil
}
func (p preflightResponseWriter) WriteHeader(statusCode int) {
p.OutputData["status_code"] = statusCode
}
现在,以 /app 开头的请求将加载 Flutter Web 应用程序的资产,或者,如果没有资产满足请求,则将加载 index.html。 如果请求 URL 不以 /app 开头,则会提供静态文件。
答案 0 :(得分:2)
这可能更适合作为评论,我会要求澄清您是否要更改网络应用程序的 URL strategy 但我没有代表(请原谅我的主,但这条规则是有点限制)
如果您可以随意更改 URL 策略,您可以通过在上面链接中所述的适当位置添加依赖项来实现:
import 'package:url_strategy/url_strategy.dart';
void main() {
setPathUrlStrategy();
runApp(MyApp());
}