Golang中net/http包调用非根路由时出现404错误的解决方法

Golang中net/http包调用非根路由时出现404错误的解决方法 我在 Stackoverflow 上发布了这个问题,但似乎没有人能够回答,所以我在此论坛重新发布。

如果有人能解答,我将非常感激,以下是问题的链接。

Stackoverflow 问题:

golang net/http give 404 error when trying to call other route that isn’t /


更多关于Golang中net/http包调用非根路由时出现404错误的解决方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

你的后端完全错了。你在同一路由上使用了两个文件服务器来提供页面。你应该为每个路由使用一个处理器,如下所示。

func handler(w http.ResponseWriter, r *http.Request) {
}
... 
http.HandleFunc("/example", handler)

LE:基本上,一个文件服务器对你的应用来说就足够了。

更多关于Golang中net/http包调用非根路由时出现404错误的解决方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


首先,你的404是文件未找到,而不是路由404。

状态1:你的文件错误。 如果 //example 是目录,你请求访问的文件是 ../frontend/public/index.html../frontend/public/exampme/index.html,请查看 net/http/fs.go 源代码。 /a.js -> ../frontend/public/a.js

[root@localhost tmp]# ls -R bruhurb/ frontend/
bruhurb/:
main.go

frontend/:
public

frontend/public:
example  index.html

frontend/public/example:
index.html
[root@localhost tmp]# cat frontend/public/index.html 
1
[root@localhost tmp]# cat frontend/public/example/index.html 
2
[root@localhost tmp]# cd bruhurb/
[root@localhost bruhurb]# ls
main.go
[root@localhost bruhurb]# go run main.go 
2020/04/08 22:42:53 Listening on http://locahost:8080

状态2:你的工作目录是临时目录或者工作目录错误。 添加代码 fmt.Println(os.Args[0]) 来显示工作目录。 如果使用 go run 命令启动服务器,Go 会使用一个临时目录运行,工作目录是临时的,否则相对路径是无效的,所以文件会返回404。

请使用 go build 并在工作目录中启动服务器,或者添加 os.Chdir 切换到工作目录。

这个问题通常是由于路由处理器注册不正确导致的。在net/http包中,默认的ServeMux对路由匹配有特定规则。以下是几种常见解决方案:

1. 使用HandleFunc注册精确路径

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Home page")
    })
    
    http.HandleFunc("/api", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "API endpoint")
    })
    
    http.HandleFunc("/api/data", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Data endpoint")
    })
    
    http.ListenAndServe(":8080", nil)
}

2. 使用自定义ServeMux并检查路径匹配

package main

import (
    "fmt"
    "net/http"
)

func main() {
    mux := http.NewServeMux()
    
    mux.HandleFunc("/", homeHandler)
    mux.HandleFunc("/api", apiHandler)
    mux.HandleFunc("/api/data", apiDataHandler)
    
    http.ListenAndServe(":8080", mux)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.NotFound(w, r)
        return
    }
    fmt.Fprintf(w, "Home page")
}

func apiHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "API endpoint")
}

func apiDataHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Data endpoint")
}

3. 使用第三方路由库(如gorilla/mux)

package main

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

func main() {
    r := mux.NewRouter()
    
    r.HandleFunc("/", homeHandler)
    r.HandleFunc("/api", apiHandler)
    r.HandleFunc("/api/data", apiDataHandler)
    
    http.ListenAndServe(":8080", r)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Home page")
}

func apiHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "API endpoint")
}

func apiDataHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Data endpoint")
}

4. 检查中间件或处理器链的问题

package main

import (
    "fmt"
    "net/http"
)

func loggingMiddleware(next http.HandlerFunc) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("Request: %s %s\n", r.Method, r.URL.Path)
        next(w, r)
    }
}

func main() {
    http.HandleFunc("/", loggingMiddleware(homeHandler))
    http.HandleFunc("/api", loggingMiddleware(apiHandler))
    http.HandleFunc("/api/data", loggingMiddleware(apiDataHandler))
    
    http.ListenAndServe(":8080", nil)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        http.NotFound(w, r)
        return
    }
    fmt.Fprintf(w, "Home page")
}

func apiHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "API endpoint")
}

func apiDataHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Data endpoint")
}

关键点:

  1. 确保路由处理器按正确顺序注册
  2. 根路径/会匹配所有请求,需要在处理器中检查具体路径
  3. 使用http.StripPrefix处理静态文件时可能影响路由
  4. 检查是否有其他中间件修改了请求路径

根据你的具体代码结构,选择适合的解决方案。如果问题仍然存在,请提供具体的代码片段以便进一步分析。

回到顶部