Go – 中间件阻止每个请求的 MIME 类型

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

Go - middleware blocks MIME type of each requests

问题

我修改了这个教程的中间件,以检查所有PUT和POST请求的JSON MIME类型。

但是中间件似乎每次都回复"不支持的媒体类型"。我尝试了下面的curl命令,其中明确设置了正确的MIME类型。我在每个请求中打印了客户端的Content-Type头字段,它始终是"text/plain; charset=utf-8"。

中间件代码如下:

func EnforceJSON(h httprouter.Handle) httprouter.Handle {
	return func(rw http.ResponseWriter, req *http.Request, ps httprouter.Params) {
		// 检查请求体是否存在
		if req.ContentLength == 0 {
			http.Error(rw, http.StatusText(400), http.StatusBadRequest)
			return
		}

		// 检查MIME类型
		buf := new(bytes.Buffer)
		buf.ReadFrom(req.Body)
		// 打印"text/plain; charset=utf-8"
		fmt.Println(http.DetectContentType(buf.Bytes()))
		if http.DetectContentType(buf.Bytes()) != "application/json; charset=utf-8" {
			http.Error(rw, http.StatusText(415), http.StatusUnsupportedMediaType)
			return
		}

		h(rw, req, ps)
	}
}
...
router.POST("/api/v1/users", EnforceJSON(CreateUser))

我的curl命令如下:

curl -H "Content-Type: application/json; charset=utf-8" \
-X POST \
-d '{"JSON": "在中间件接受MIME类型后将被检查。"}' \
http://localhost:8080/api/v1/users

我还尝试了Postman,但结果是一样的。

英文:

I modiefied the middleware of this tutorial to check for all PUT and POST request the JSON MIME type.

But the middleware seems to respond everytime with "Mediatype Not Supported". I tried the curl command below where I set explicitly the right MIME type. I print which each request the client's Content-Type header field which is allways "text/plain; charset=utf-8".

<!-- language: go-lang -->

The Middleware:

func EnforceJSON(h httprouter.Handle) httprouter.Handle {
	return func(rw http.ResponseWriter, req *http.Request, ps httprouter.Params) {
		// Check the existence of a request body
		if req.ContentLength == 0 {
			http.Error(rw, http.StatusText(400), http.StatusBadRequest)
			return
		}

		// Check the MIME type
		buf := new(bytes.Buffer)
		buf.ReadFrom(req.Body)
        // Prints &quot;text/plain; charset=utf-8&quot;
        fmt.Println(http.DetectContentType(buf.Bytes()))
		if http.DetectContentType(buf.Bytes()) != &quot;application/json; charset=utf-8&quot; {
			http.Error(rw, http.StatusText(415), http.StatusUnsupportedMediaType)
			return
		}

		h(rw, req, ps)
	}
}  
...
router.POST(&quot;/api/v1/users&quot;, EnforceJSON(CreateUser))

My curl command:

curl -H &quot;Content-Type: application/json; charset=utf-8&quot; \
-X POST \
-d &#39;{&quot;JSON&quot;: &quot;Will be checked after the middleware accepted the MIME type.&quot;}&#39; \
http://localhost:8080/api/v1/users

Alternativly I tried Postman but the result was the same.

答案1

得分: 1

根据DetectContentType函数的实现,它遵循"MIME Sniffing"指南(https://mimesniff.spec.whatwg.org/)中描述的规则。

为了通过内容确定MIME类型,该特定函数使用了"7. Determining the computed MIME type of a resource"这一项。该项没有确定"application/json"类型的规定,按照这些规则,结果将是"text/plain" MIME类型。

这在DetectContentType实现的match函数(https://golang.org/src/net/http/sniff.go)的第252行可见。

英文:

Looking at the implementation of DetectContentType function they follow the rules described on "MIME Sniffing" guide (https://mimesniff.spec.whatwg.org/).

To determine the MIME Type by the content this specific function use the item "7. Determining the computed MIME type of a resource". That item doesn't have a determination for 'application/json' type and following these rules will result in a 'text/plain' MIME type.

This is visible on the function match on the DetectContentType implementation (https://golang.org/src/net/http/sniff.go) line 252.

huangapple
  • 本文由 发表于 2015年5月19日 02:04:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/30310046.html
匿名

发表评论

匿名网友

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

确定