我正在编写一个从某些嵌入式设备接收HTTP POST的小型HTTP服务器。不幸的是,这些设备发送的格式错误的POST请求不包含PATH组件:
POST HTTP/1.1
Host: 192.168.13.130:8080
Content-Length: 572
Connection: Keep-Alive
<?xml version="1.0"?>
....REST OF XML BODY
由于这个原因,Go http从未将请求传递给我的任何处理程序,并始终以400 Bad Request响应。
由于这些是嵌入式设备并且改变它们发送请求的方式不是一个选项我可能我可以拦截HTTP请求,如果没有PATH,则在它传递给SeverMux之前添加一个(例如/)。
我通过创建自己的CameraMux尝试了这一点,但是在我从自定义ServeMux调用ServeHTTP()方法之前,Go总是以400 Bad Request响应(参见下面的代码)。
有没有办法在Go http响应Bad Request之前的某个时刻修改Request对象,或者有一种方法让Go接受请求,即使它没有PATH?
package main
import (
"net/http"
"log"
"os"
)
type CameraMux struct {
mux *http.ServeMux
}
func (handler *CameraMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// Try to fix URL.Path here but the server never reaches this method.
log.Printf("URL %v\n", r.URL.Path)
handler.mux.ServeHTTP(w, r)
}
func process(path string) error {
log.Printf("Processing %v\n", path)
// Do processing based on path and body
return nil
}
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path[1:]
log.Printf("Processing path %v\n", path)
err := process(path)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
} else {
w.WriteHeader(http.StatusOK)
}
})
err := http.ListenAndServe(":8080", &CameraMux{http.DefaultServeMux})
if err != nil {
log.Println(err)
os.Exit(1)
}
os.Exit(0)
}
答案 0 :(得分:0)
我不确定Go的HTTP解析器是否允许没有URI路径元素的请求。如果没有,那么你运气不好。但如果确实如此;您可以像这样覆盖请求的路径:
type FixPath struct {}
func (f *FixPath) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r.RequestURI = "/dummy/path" // fix URI path
http.DefaultServeMux.ServeHTTP(w, r) // forward the fixed request to http.DefaultServeMux
}
func main() {
// register handlers with http.DefaultServeMux through http.Handle or http.HandleFunc, and then...
http.ListenAndServe(":8080", &FixPath{})
}
答案 1 :(得分:0)
您看到的错误发生在请求解析逻辑中,该错误在调用ServeHTTP
之前发生。
来自ReadRequest
包的net/http
函数从套接字读取HTTP请求。它将使用空的URL部分标记请求的第一行,但随后继续to parse the URL:
if req.URL, err = url.ParseRequestURI(rawurl); err != nil {
return nil, err
}
不幸的是,这个函数将return an error for an empty URL string,这将反过来中止请求读取过程。
所以看起来没有一种简单的方法可以在不修改标准库代码的情况下实现您的目标。