前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >摸鱼快报:golang net/http中的雕虫小技

摸鱼快报:golang net/http中的雕虫小技

作者头像
有态度的马甲
发布2023-04-27 15:52:04
3590
发布2023-04-27 15:52:04
举报
文章被收录于专栏:精益码农精益码农
以后会开一个板块,摸鱼快报,快速记录这几周开发中雕虫小技, 也算一个错题集。
1. 向开发环境localhost:3000种植cookie

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

代码语言:javascript
复制
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是大小写敏感的:

代码语言:javascript
复制
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都会命中下面的路由。

代码语言:javascript
复制
 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

代码语言:javascript
复制
func Home(w http.ResponseWriter, r *http.Request)  {
    io.WriteString(w, "Welcome to my blog site")
}

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

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

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

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

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

例如尝试以如下方式:

代码语言:javascript
复制
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

代码语言:javascript
复制
w.WriteHeader(http.StatusInternalServerError)
fmt.Fprintln(w, "404 page not found")
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-01-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 精益码农 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 向开发环境localhost:3000种植cookie
  • 2. httpclient timeout报错经验
  • 3. url 大小写敏感
  • 4. golang statuscode被作为header,一直很费解。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档