牢骚

坚持写作确实是很难的事情 还记得最早折腾自己的博客,还是在上大学的时候,那时充满了新鲜感,觉得什么都好有趣,研究了很多东西,也写了很多 写得多了,慢慢不知道该写些什么了,可能是被学业绊住了脚,也可能只是懒散了,博客也就慢慢不再更新 也不知道当时经历了些什么,不想让身边的人看到我的博客,可能是怕写的内容过于浅薄被朋友笑话吧,来来回回搬迁了好几次,真爱折腾 也许只是测试不同的部署方案呢,是吧,就像现在已经只需要写好文档提交到 Github, Action 就自动集成 Vercel 自动部署了,相比于最早期的全手动,确实现代了很多 也正是因为好几次的搬迁,很多以前的文章遗失在了历史尘埃中,或者能找到文字但是嵌入的图片也没有了,也就算了吧 前段时间看到一篇文章,讲写作其实是思考的过程,写,不应该是为了给谁看,而仅仅是因为在思考,我思故我写,给人看只是副产物罢了。截图分享到朋友圈表示了赞同,有朋友问起我的博客地址,才发现自己已经很久不思考啦 还好我仍然会对此感到焦虑,至少还没能心安理得地放下自己的脑子,那还是捡起来吧,应该不丢人的 最近又看到一篇以前的文章,讲虽然现在技术很发达,可是互联网却像封建时代,大的公司垄断了数据,用户只是生产数据的数字农奴,每天发朋友圈发帖子,其实是免费劳动给这些公司增加资产,深觉如此 是不是很傻,别人文章怎么写我就怎么信,都没点自己的思考 不过傻就傻吧,我又要开始发神经了,要守护好自己的一片地方,哪怕没人看呢,并不重要,我自己留下思考的痕迹就好了

June 3, 2025 · 1 min · 🦉

Crypto Scam

简介 每年都有很多很多人因为各种骗局而损失惨重,这里主要讨论一些最近比较常见的骗局。 各大种类 Crypto Drainers ( the most common link 表现形式 通常是是模仿官方的网页布局和风格,页面内容就是领取空投之类的。 一种是点击按钮就会连接钱包弹出签名。 link 另一种是连接钱包的时候提示连接失败或者繁忙,然后让自己填助记词或者私钥上去,就很直接… 传播方式,会在哪里看到 推特的评论区,是最常见的,通常会取一个和官方很像的名字头像,链接也是和官方网页很像的。 link link 链上发名字里带链接的币,批量转给各个地址。 link link 因为各大浏览器,钱包,追踪 ERC20 代币都是根据 ERC20 的 Transfer 事件来的。所以钓鱼方只要在合约上不断触发 Transfer 事件就可以伪造出很多转账记录,任意地址转到任意地址都可以。 1function airdrop(address[] calldata _to, uint256 _value) public { 2 for (uint256 i = 0; i < _to.length; i++) { 3 emit Transfer(address(0x0), _to[i], _value); 4 } 5} 比较常见的 from 地址就是各大交易所热钱包,各种 Deployer 之类的。上图就是 uniswap v4 pool manager,都是为了骗取信任。 ...

February 28, 2025 · 18 min · 🦉

net/http Transport

$ go version go version go1.20.5 darwin/arm64 DefaultTransport 看一下 DefaultTransport 的 RoundTrip 方法。 1// src/net/http/roundtrip.go#L8 2// RoundTrip implements the RoundTripper interface. 3// 4// For higher-level HTTP client support (such as handling of cookies 5// and redirects), see Get, Post, and the Client type. 6// 7// Like the RoundTripper interface, the error types returned 8// by RoundTrip are unspecified. 9func (t *Transport) RoundTrip(req *Request) (*Response, error) { 10 return t.roundTrip(req) 11} 12 13// src/net/http/transport.go#L510 14// roundTrip implements a RoundTripper over HTTP. 15func (t *Transport) roundTrip(req *Request) (*Response, error) { 16 t.nextProtoOnce.Do(t.onceSetNextProtoDefaults) 17 ctx := req.Context() 18 trace := httptrace.ContextClientTrace(ctx) 19 20 if req.URL == nil { 21 req.closeBody() 22 return nil, errors.New("http: nil Request.URL") 23 } 24 if req.Header == nil { 25 req.closeBody() 26 return nil, errors.New("http: nil Request.Header") 27 } 28 scheme := req.URL.Scheme 29 isHTTP := scheme == "http" || scheme == "https" 30 if isHTTP { 31 for k, vv := range req.Header { 32 if !httpguts.ValidHeaderFieldName(k) { 33 req.closeBody() 34 return nil, fmt.Errorf("net/http: invalid header field name %q", k) 35 } 36 for _, v := range vv { 37 if !httpguts.ValidHeaderFieldValue(v) { 38 req.closeBody() 39 // Don't include the value in the error, because it may be sensitive. 40 return nil, fmt.Errorf("net/http: invalid header field value for %q", k) 41 } 42 } 43 } 44 } 45 46 origReq := req 47 cancelKey := cancelKey{origReq} 48 req = setupRewindBody(req) 49 50 if altRT := t.alternateRoundTripper(req); altRT != nil { 51 if resp, err := altRT.RoundTrip(req); err != ErrSkipAltProtocol { 52 return resp, err 53 } 54 var err error 55 req, err = rewindBody(req) 56 if err != nil { 57 return nil, err 58 } 59 } 60 if !isHTTP { 61 req.closeBody() 62 return nil, badStringError("unsupported protocol scheme", scheme) 63 } 64 if req.Method != "" && !validMethod(req.Method) { 65 req.closeBody() 66 return nil, fmt.Errorf("net/http: invalid method %q", req.Method) 67 } 68 if req.URL.Host == "" { 69 req.closeBody() 70 return nil, errors.New("http: no Host in request URL") 71 } 72 73 for { 74 select { 75 case <-ctx.Done(): 76 req.closeBody() 77 return nil, ctx.Err() 78 default: 79 } 80 81 // treq gets modified by roundTrip, so we need to recreate for each retry. 82 treq := &transportRequest{Request: req, trace: trace, cancelKey: cancelKey} 83 cm, err := t.connectMethodForRequest(treq) 84 if err != nil { 85 req.closeBody() 86 return nil, err 87 } 88 89 // Get the cached or newly-created connection to either the 90 // host (for http or https), the http proxy, or the http proxy 91 // pre-CONNECTed to https server. In any case, we'll be ready 92 // to send it requests. 93 pconn, err := t.getConn(treq, cm) 94 if err != nil { 95 t.setReqCanceler(cancelKey, nil) 96 req.closeBody() 97 return nil, err 98 } 99 100 var resp *Response 101 if pconn.alt != nil { 102 // HTTP/2 path. 103 t.setReqCanceler(cancelKey, nil) // not cancelable with CancelRequest 104 resp, err = pconn.alt.RoundTrip(req) 105 } else { 106 resp, err = pconn.roundTrip(treq) 107 } 108 if err == nil { 109 resp.Request = origReq 110 return resp, nil 111 } 112 113 // Failed. Clean up and determine whether to retry. 114 if http2isNoCachedConnError(err) { 115 if t.removeIdleConn(pconn) { 116 t.decConnsPerHost(pconn.cacheKey) 117 } 118 } else if !pconn.shouldRetryRequest(req, err) { 119 // Issue 16465: return underlying net.Conn.Read error from peek, 120 // as we've historically done. 121 if e, ok := err.(nothingWrittenError); ok { 122 err = e.error 123 } 124 if e, ok := err.(transportReadFromServerError); ok { 125 err = e.err 126 } 127 return nil, err 128 } 129 testHookRoundTripRetried() 130 131 // Rewind the body if we're able to. 132 req, err = rewindBody(req) 133 if err != nil { 134 return nil, err 135 } 136 } 137} 因为 RoundTripper 说明了请求的 URL 和 Header 必须初始化,所以一开始检查报错。再往后,如果 schema 是 http 的话,检查了一下 header 的键值对的非法字符。再往后,注意到有一个 setupRewindBody,是用于恢复请求 body 的 ...

August 29, 2023 · 23 min · 🦉

net/http Client

$ go version go version go1.20.5 darwin/arm64 如果一个文件一个文件挨着看未免也太枯燥了,并且没有和实践结合,感觉看了也体会不深。这里从发起一个请求到最后收到应答的整个流程,跟随一个 http.Request 的生命周期去探索相关的源码。 http.Client 开始发请求之前先看一下 http.Client 结构体 1// src/net/http/client.go#L29 2// A Client is an HTTP client. Its zero value (DefaultClient) is a 3// usable client that uses DefaultTransport. 4// 5// The Client's Transport typically has internal state (cached TCP 6// connections), so Clients should be reused instead of created as 7// needed. Clients are safe for concurrent use by multiple goroutines. 8// 9// A Client is higher-level than a RoundTripper (such as Transport) 10// and additionally handles HTTP details such as cookies and 11// redirects. 12// 13// When following redirects, the Client will forward all headers set on the 14// initial Request except: 15// 16// • when forwarding sensitive headers like "Authorization", 17// "WWW-Authenticate", and "Cookie" to untrusted targets. 18// These headers will be ignored when following a redirect to a domain 19// that is not a subdomain match or exact match of the initial domain. 20// For example, a redirect from "foo.com" to either "foo.com" or "sub.foo.com" 21// will forward the sensitive headers, but a redirect to "bar.com" will not. 22// 23// • when forwarding the "Cookie" header with a non-nil cookie Jar. 24// Since each redirect may mutate the state of the cookie jar, 25// a redirect may possibly alter a cookie set in the initial request. 26// When forwarding the "Cookie" header, any mutated cookies will be omitted, 27// with the expectation that the Jar will insert those mutated cookies 28// with the updated values (assuming the origin matches). 29// If Jar is nil, the initial cookies are forwarded without change. 30type Client struct { 31 // Transport specifies the mechanism by which individual 32 // HTTP requests are made. 33 // If nil, DefaultTransport is used. 34 Transport RoundTripper 35 36 // CheckRedirect specifies the policy for handling redirects. 37 // If CheckRedirect is not nil, the client calls it before 38 // following an HTTP redirect. The arguments req and via are 39 // the upcoming request and the requests made already, oldest 40 // first. If CheckRedirect returns an error, the Client's Get 41 // method returns both the previous Response (with its Body 42 // closed) and CheckRedirect's error (wrapped in a url.Error) 43 // instead of issuing the Request req. 44 // As a special case, if CheckRedirect returns ErrUseLastResponse, 45 // then the most recent response is returned with its body 46 // unclosed, along with a nil error. 47 // 48 // If CheckRedirect is nil, the Client uses its default policy, 49 // which is to stop after 10 consecutive requests. 50 CheckRedirect func(req *Request, via []*Request) error 51 52 // Jar specifies the cookie jar. 53 // 54 // The Jar is used to insert relevant cookies into every 55 // outbound Request and is updated with the cookie values 56 // of every inbound Response. The Jar is consulted for every 57 // redirect that the Client follows. 58 // 59 // If Jar is nil, cookies are only sent if they are explicitly 60 // set on the Request. 61 Jar CookieJar 62 63 // Timeout specifies a time limit for requests made by this 64 // Client. The timeout includes connection time, any 65 // redirects, and reading the response body. The timer remains 66 // running after Get, Head, Post, or Do return and will 67 // interrupt reading of the Response.Body. 68 // 69 // A Timeout of zero means no timeout. 70 // 71 // The Client cancels requests to the underlying Transport 72 // as if the Request's Context ended. 73 // 74 // For compatibility, the Client will also use the deprecated 75 // CancelRequest method on Transport if found. New 76 // RoundTripper implementations should use the Request's Context 77 // for cancellation instead of implementing CancelRequest. 78 Timeout time.Duration 79} 80 81// DefaultClient is the default Client and is used by Get, Head, and Post. 82var DefaultClient = &Client{} 83 84// RoundTripper is an interface representing the ability to execute a 85// single HTTP transaction, obtaining the Response for a given Request. 86// 87// A RoundTripper must be safe for concurrent use by multiple 88// goroutines. 89type RoundTripper interface { 90 // RoundTrip executes a single HTTP transaction, returning 91 // a Response for the provided Request. 92 // 93 // RoundTrip should not attempt to interpret the response. In 94 // particular, RoundTrip must return err == nil if it obtained 95 // a response, regardless of the response's HTTP status code. 96 // A non-nil err should be reserved for failure to obtain a 97 // response. Similarly, RoundTrip should not attempt to 98 // handle higher-level protocol details such as redirects, 99 // authentication, or cookies. 100 // 101 // RoundTrip should not modify the request, except for 102 // consuming and closing the Request's Body. RoundTrip may 103 // read fields of the request in a separate goroutine. Callers 104 // should not mutate or reuse the request until the Response's 105 // Body has been closed. 106 // 107 // RoundTrip must always close the body, including on errors, 108 // but depending on the implementation may do so in a separate 109 // goroutine even after RoundTrip returns. This means that 110 // callers wanting to reuse the body for subsequent requests 111 // must arrange to wait for the Close call before doing so. 112 // 113 // The Request's URL and Header fields must be initialized. 114 RoundTrip(*Request) (*Response, error) 115} 简单翻译一下注释。 ...

August 29, 2023 · 18 min · 🦉