摸鱼快报:golang net/http中的雕虫小技
Posted 有态度马甲-- 精益码农
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了摸鱼快报:golang net/http中的雕虫小技相关的知识,希望对你有一定的参考价值。
以后会开一个板块,摸鱼快报,快速记录这几周开发中雕虫小技。
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: 请求哪些资源domain时能携带该cookie?
2. httpclient timeout报错经验
golang net/http httpclient
Timeout
:
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!");
);
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一般被认为是大小写敏感。
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")
本周摸鱼快报,阅读时间3min;难度星:3(满星5星);价值度:3(满分5分)。
本文来自博客园,作者:有态度的马甲,转载请注明原文链接:https://www.cnblogs.com/JulianHuang/p/17050485.html
欢迎关注我的原创技术、职场公众号, 加好友谈天说地,一起进化以上是关于摸鱼快报:golang net/http中的雕虫小技的主要内容,如果未能解决你的问题,请参考以下文章