Golang Net/Http中的雕虫小技

开发 前端
浏览器认定该cookie没有domain,属性值被重置当前页面,该Cookie为HostOnly Cookie,后续请求只有host与cookie的domain完全相等,才能携带这个cookie。

以后会开一个板块,摸鱼快报,快速记录这几周开发中雕虫小技, 也算一个错题集。

1. 向开发环境localhost:3000种植cookie

前端使用Create React App脚手架,默认以localhost:3000端口启动;后端使用golang-gin框架,使用8034端口启动。登录模块走的是sso,前后端分离,后端需要向前端写入认证cookie

c.SetSameSite(http.SameSiteLaxMode)
c.SetCookie("userInfo", userInfoMapString, 60*60*12, "/", cfg.CookieDomain, false, false)
c.SetCookie("access_token", accessToken.(string), 60*60*12, "/", cfg.CookieDomain, false, false)

若种植cookie时设置domain=localhost:3000​,实际会发现该cookie被种为domain=localhost

① golang给出日志提示:2023/01/12 19:10:48 net/http: invalid Cookie.Domain "localhost:3000"; dropping domain attribute, 该cookie domain属性被丢弃:

图片

② 浏览器认定该cookie没有domain,属性值被重置当前页面,该Cookie为HostOnly Cookie,后续请求只有host与cookie的domain完全相等,才能携带这个cookie。

react配置后端地址,要配置为localhost:8034​,而不能是127.0.0.1:8034​

图片

经此一役:

图片

  • • 源(Origin)是由 URL 中协议、主机名(域名 domain)以及端口共同组成的部分
  • • 本次出现的问题在于两个关键cookie属性 :

cookie domain:cookie被种植到哪个域名下?

cookie samesite:请求时,哪些资源能携带该cookie?

2. httpclient timeout报错经验

golang net/http httpclientTimeout:Timeout specifies a time limit for requests made by this Client. The timeout includes connection time, any redirects, and reading the response body. The timer remains running after Get, Head, Post, or Do return and will interrupt reading of the Response.Body.

HttpClient Timeout包括连接、重定向(如果有)、从Response Body读取的时间,内置定时器会在Get,Head、Post、Do 方法之后继续运行,并有能力中断读取Response.Body.

图片

如果upstream服务器处理超时(upstream_response_time> client设置的timeout),则会返回context deadline exceeded (Client.Timeout exceeded while awaiting headers)。

如果客户端使用io.ReadAll读取body超时,则会返回context deadline exceeded (Client.Timeout or context cancellation while reading body)。

3. url 大小写敏感

大家使用net/http 建立的http server,默认的请求url path是大小写敏感的:

s.mux.HandleFunc("/leader", func(w http.ResponseWriter, r *http.Request) {

}

s.mux.HandleFunc("/LEADER", func(w http.ResponseWriter, r *http.Request) {

}

以上会被认定为不同的路由path。探究源码:ServeMux使用​map[string]muxEntry 哈希表来存储路由。

这与aspnet core的路由行为是不一样的,/hello、/HELLO都会命中下面的路由。

 app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/hello", async context =>
{
await context.Response.WriteAsync("Hello!");
});
}

w3c官方建议:url大小写敏感。

URLs in general are case-sensitive (with the exception of machine names). There may be URLs, or parts of URLs, where case doesn't matter, but identifying these may not be easy. Users should always consider that URLs are case-sensitive。大意是说:除了​domain主机名是大小写不敏感,url一般被认为是大小写敏感。

stackoverflow有更清晰的描述:

The scheme and host are case-insensitive and normally provided in lowercase; all other components are compared in a case-sensitive manner.

4. golang statuscode被作为header,一直很费解。

在 Go 语言中,客户端请求信息都封装到了Request​对象,但是发送给客户端的响应并不是 Response 对象,而是ResponseWriter:

func Home(w http.ResponseWriter, r *http.Request)  {
io.WriteString(w, "Welcome to my blog site")
}

ResponseWriter是处理器用来创建 HTTP 响应的接口,其源码结构如下所示:

type ResponseWriter interface {
// 用于设置/获取所有响应头信息
Header() Header
// 用于写入数据到响应实体
Write([]byte) (int, error)
// 用于设置响应状态码
WriteHeader(statusCode int)
}

WriteHeader这个方法名有点误导,其实它并不是用来设置响应头的,该方法支持传入一个整型数据用来表示响应状态码,如果不调用该方法的话,默认响应状态码是 200 OK。

在fasthttp中,设置请求谓词:req.Header.SetMethod("POST"), 这种将谓词作为header的行为,我也是服气。

只能设置一次statuscode, 若多次设置statuscode,以前者优先。

例如尝试以如下方式:

http.NotFound(w, r)   # 会调用WriteHeader(404);Write()写入body
w.WriteHeader(http.StatusInternalServerError)

会产生一个告警:2023/01/06 19:19:43 http: superfluous response.WriteHeader call from main.ProxyHandler (proxy.go:25), 同时产生404状态码。

可以采用如下方式清晰定义状态码和body

w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "404 page not found")

责任编辑:武晓燕 来源: 精益码农
相关推荐

2021-09-23 14:55:57

.NETHTTP服务器

2009-07-23 16:20:48

HTTP协议ASP.NET

2009-07-28 15:29:03

实现HTTP请求ASP.NET

2024-02-05 08:50:57

Golang标准库客户端

2024-01-29 08:04:48

Golang标准库服务端

2023-10-22 20:20:37

FiberGo

2021-07-20 10:30:46

Golanghttp语言

2022-07-20 08:04:06

net包DNScontext

2023-11-13 21:55:12

Go编程

2024-11-07 11:46:41

2024-09-30 08:43:33

HttpgolangTimeout

2022-03-07 16:30:10

数据库ORM开发人员

2021-10-18 05:00:38

语言GoRequestHTTP

2022-04-29 11:52:02

API代码HTTP

2015-09-15 13:48:01

网络协议HTTP Client

2011-04-13 15:18:10

.htmHTTP请求处理

2022-08-12 12:23:55

golangmap数据结构

2023-08-14 08:34:14

GolangHttp

2010-02-24 08:59:50

HTTP报头状态码

2023-11-30 07:15:36

GolangRecover
点赞
收藏

51CTO技术栈公众号