Golang——gorilla-Websocket⼩部分源码注释阅读与翻译
websocket包实现了在RFC 6455中定义的WebSocket协议
包中⽂件:
<\\\\\\\\\\proxy.
\\\x_
<
type HandshakeError&func (HandshakeError) Error
// HandshakeError describes an error with the handshake from the peer.
/@zh HandshakeError(握⼿错误)描述当与节点握⼿时的错误
type HandshakeError struct{
message string
}
func(e HandshakeError)Error()string{ssage }
type Upgrader&func (*Upgrader) returnError
// Upgrader specifies parameters for upgrading an HTTP connection to a
// WebSocket connection.
/@zh Upgrader(协议升级器)指定参数升级⼀个HTTP连接到WebSoket连接
type Upgrader struct{
// HandshakeTimeout specifies the duration for the handshake to complete.
/@zh HandshakeTimeout(握⼿超时)指定完成握⼿所需的时间
HandshakeTimeout time.Duration
// ReadBufferSize and WriteBufferSize specify I/O buffer sizes in bytes. If a buffer
/
/ size is zero, then buffers allocated by the HTTP server are used. The
// I/O buffer sizes do not limit the size of the messages that can be sent
// or received.
/@zh ReadBufferSize(读取缓冲区⼤⼩)和WriteBufferSize(写⼊缓冲区⼤⼩)指定读写缓冲区的字节⼤⼩。
/@zh 如果缓冲区⼤⼩为0,则会使⽤对应HTTP服务器分配的缓冲区。
/@zh 读写缓冲区⼤⼩并不会限制发送和接收消息的⼤⼩。
ReadBufferSize, WriteBufferSize int
// WriteBufferPool is a pool of buffers for write operations. If the value
// is not set, then write buffers are allocated to the connection for the
// lifetime of the connection.
/@zh WriteBufferPool(写缓冲池)是⼀个写操作的缓冲池。
/@zh 如果这个值未设定,则连接的写缓冲区会被分配到它的整个⽣命周期。
//
// A pool is most useful when the application has a modest volume of writes
// across a large number of connections.
/@zh 当应⽤在连接数很⼤的情况下进⾏写⼊时,池是很有⽤的。
//
// Applications should use a single pool for each unique value of
// WriteBufferSize.
/@zh 应⽤要为每个不同的WriteBufferSize(写缓冲区⼤⼩)使⽤独⽴的池。
WriteBufferPool BufferPool
// Subprotocols specifies the server's supported protocols in order of
/
/ preference. If this field is not nil, then the Upgrade method negotiates a
// subprotocol by selecting the first match in this list with a protocol
// requested by the client. If there's no match, then no protocol is
// negotiated (the Sec-Websocket-Protocol header is not included in the
// handshake response).
/@zh ⼦协议按照优先顺序指定了服务器⽀持的协议。
/@zh 如果这个值不为nil,则Upgrade(升级)则Upgrade⽅法通过选择此列表中与客户端请求的协议的第⼀个匹配项来协商⼦协议。
/@zh 如果没有匹配项,则不会协商任何协议(握⼿的响应中不会包含 Sec-Websocket-Protocol头)。
// Error specifies the function for generating HTTP error responses. If Error
// is nil, then http.Error is used to generate the HTTP response.
/
@zh Error(错误)指定了⽣成HTTP错误响应的函数。如果Error(错误)是nil,则使⽤http.Error来⽣成HTTP响应
Error func(w http.ResponseWriter, r *http.Request, status int, reason error)
// CheckOrigin returns true if the request Origin header is acceptable. If
// CheckOrigin is nil, then a safe default is used: return false if the
// Origin request header is present and the origin host is not equal to
// request Host header.
/@zh 如果请求的Origin头是合理的,CheckOrigin(Origin校验)会返回true。
/@zh 如果CheckOrigin(Origin校验)是nil,则使⽤安全默认值:若现有Origin请求头和主机源的请求Host头不符,返回false。//
// A CheckOrigin function should carefully validate the request origin to
// prevent cross-site request forgery.
/@zh ⼀个CheckOrigin(校验Origin)函数应仔细验证请求origin来防⽌伪造的跨站请求。
CheckOrigin func(r *http.Request)bool
// EnableCompression specify if the server should attempt to negotiate per
// message compression (RFC 7692). Setting this value to true does not
// guarantee that compression will be supported. Currently only "no context
// takeover" modes are supported.
/@zh EnableCompression(启⽤压缩)定义了服务器是否应协商每个消息压缩(RFC 7692)。
/@zh 设定此值为true并不能保证能⽀持压缩。当前只⽀持“⽆上下⽂”模式。
EnableCompression bool
}
func(u *Upgrader)returnError(w http.ResponseWriter, r *http.Request, status int, reason string)(*Conn,error){
err := HandshakeError{reason}
if u.Error !=nil{
u.Error(w, r, status, err)
}else{
w.Header().Set("Sec-Websocket-Version","13")
http.Error(w, http.StatusText(status), status)
}
return nil, err
}
func (*Upgrader) Upgrade
// Upgrade upgrades the HTTP server connection to the WebSocket protocol.
/
@zh Upgrader(协议升级器)升级HTTP服务器连接到WebSoket协议
//
// The responseHeader is included in the response to the client's upgrade
// request. Use the responseHeader to specify cookies (Set-Cookie). To specify
// subprotocols supported by the server, set Upgrader.Subprotocols directly.
/@zh 对客户端升级请求的响应中包含了响应头responseHeader。⽤响应头responseHeader来设定cookies(Set-Cookie)。
/@zh 若要指定服务器⽀持的⼦协议,直接设置Upgrader.Subprotocols
//
// If the upgrade fails, then Upgrade replies to the client with an HTTP error
// response.
/@zh 如果升级失败,Upgrader(协议升级器)将会回应⼀个HTTP错误响应给客户端
func(u *Upgrader)Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header)(*Conn,error){
const badHandshake ="websocket: the client is not using the websocket protocol: "
if!tokenListContainsValue(r.Header,"Connection","upgrade"){
urnError(w, r, http.StatusBadRequest, badHandshake+"'upgrade' token not found in 'Connection' header")
}
if!tokenListContainsValue(r.Header,"Upgrade","websocket"){
urnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header")
}
if r.Method !="GET"{
urnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET")
if!tokenListContainsValue(r.Header,"Sec-Websocket-Version","13"){
urnError(w, r, http.StatusBadRequest,"websocket: unsupported version: 13 not found in 'Sec-Websocket-Version' header")
}
if_, ok := responseHeader["Sec-Websocket-Extensions"]; ok {
urnError(w, r, http.StatusInternalServerError,"websocket: application specific 'Sec-WebSocket-Extensions' headers are unsupported") }
checkOrigin := u.CheckOrigin
if checkOrigin ==nil{
checkOrigin = checkSameOrigin
}
if!checkOrigin(r){
urnError(w, r, http.StatusForbidden,"websocket: request origin not allowed by Upgrader.CheckOrigin")
}
challengeKey := r.Header.Get("Sec-Websocket-Key")
if challengeKey ==""{
urnError(w, r, http.StatusBadRequest,"websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank")
}
subprotocol := u.selectSubprotocol(r, responseHeader)
// Negotiate PMCE
var compress bool
if u.EnableCompression {
for_, ext :=range parseExtensions(r.Header){
if ext[""]!="permessage-deflate"{
continue
}
compress =true
break
}
}
h, ok := w.(http.Hijacker)
if!ok {
urnError(w, r, http.StatusInternalServerError,"websocket: response does not implement http.Hijacker")
}
var brw *bufio.ReadWriter
netConn, brw, err := h.Hijack()
if err !=nil{
urnError(w, r, http.StatusInternalServerError, err.Error())
}
if brw.Reader.Buffered()>0{
netConn.Close()
return nil, errors.New("websocket: client sent data before handshake is complete")
}
var br *bufio.Reader
if u.ReadBufferSize ==0&&bufioReaderSize(netConn, brw.Reader)>256{
// Reuse hijacked buffered reader as connection reader.
br = brw.Reader
}
buf :=bufioWriterBuffer(netConn, brw.Writer)
var writeBuf []byte
if u.WriteBufferPool ==nil&& u.WriteBufferSize ==0&&len(buf)>= maxFrameHeaderSize+256{
// Reuse hijacked write buffer as connection buffer.
/@zh 重⽤被劫持的写缓冲器作为连接缓冲区
writeBuf = buf
c :=newConn(netConn,true, u.ReadBufferSize, u.WriteBufferSize, u.WriteBufferPool, br, writeBuf)
c.subprotocol = subprotocol
if compress {
}
// Use larger of hijacked buffer and connection write buffer for header.
p := buf
if len(c.writeBuf)>len(p){
p = c.writeBuf
}
p = p[:0]
p =append(p,"HTTP/1.1 101 Switching Protocols\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Accept: "...) p =append(p,computeAcceptKey(challengeKey)...)
p =append(p,"\r\n"...)
if c.subprotocol !=""{
p =append(p,"Sec-WebSocket-Protocol: "...)
p =append(p, )
p =append(p,"\r\n"...)
}
if compress {
p =append(p,"Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover; client_no_context_takeover\r\n"...) }
for k, vs :=range responseHeader {
if k =="Sec-Websocket-Protocol"{
continue
}
for_, v :=range vs {
server error翻译p =append(p, k...)
p =append(p,": "...)
for i :=0; i <len(v); i++{
b := v[i]
if b <=31{
// prevent response splitting.
b =' '
}
p =append(p, b)
}
p =append(p,"\r\n"...)
}
}
p =append(p,"\r\n"...)
// Clear deadlines set by HTTP server.
netConn.SetDeadline(time.Time{})
if u.HandshakeTimeout >0{
netConn.SetWriteDeadline(time.Now().Add(u.HandshakeTimeout))
}
if_, err = netConn.Write(p); err !=nil{
netConn.Close()
return nil, err
}
if u.HandshakeTimeout >0{
netConn.SetWriteDeadline(time.Time{})
}
return c,nil
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论