good morning!!!!
Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
W
websocket
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package Registry
Container Registry
Harbor Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
open
websocket
Commits
a01afeac
Unverified
Commit
a01afeac
authored
5 years ago
by
Anmol Sethi
Browse files
Options
Downloads
Patches
Plain Diff
Support x-webkit-deflate-frame extension for Safari
parent
2cf6c288
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
handshake.go
+93
-37
93 additions, 37 deletions
handshake.go
with
93 additions
and
37 deletions
handshake.go
+
93
−
37
View file @
a01afeac
...
...
@@ -152,7 +152,7 @@ func accept(w http.ResponseWriter, r *http.Request, opts *AcceptOptions) (*Conn,
return
nil
,
err
}
if
copts
!=
nil
{
copts
.
setHeader
(
w
.
Header
())
copts
.
setHeader
(
w
.
Header
()
,
false
)
}
}
...
...
@@ -190,7 +190,7 @@ func headerContainsToken(h http.Header, key, token string) bool {
}
for
_
,
v
:=
range
h
[
key
]
{
if
searchHeaderTokens
(
v
,
match
)
!=
""
{
if
searchHeaderTokens
(
v
,
match
)
{
return
true
}
}
...
...
@@ -198,36 +198,54 @@ func headerContainsToken(h http.Header, key, token string) bool {
return
false
}
func
headerTokenHasPrefix
(
h
http
.
Header
,
key
,
prefix
string
)
string
{
key
=
textproto
.
CanonicalMIMEHeaderKey
(
key
)
prefix
=
strings
.
ToLower
(
prefix
)
// readCompressionExtensionHeader extracts compression extension info from h.
// The standard says we should support multiple compression extension configurations
// from the client but we don't need to as there is only a single deflate extension
// and we support every configuration without error so we only need to check the first
// and thus preferred configuration.
func
readCompressionExtensionHeader
(
h
http
.
Header
)
(
xWebkitDeflateFrame
bool
,
params
[]
string
,
ok
bool
)
{
match
:=
func
(
t
string
)
bool
{
return
strings
.
HasPrefix
(
t
,
prefix
)
vals
:=
strings
.
Split
(
t
,
";"
)
for
i
:=
range
vals
{
vals
[
i
]
=
strings
.
TrimSpace
(
vals
[
i
])
}
params
=
vals
[
1
:
]
if
vals
[
0
]
==
"permessage-deflate"
{
return
true
}
// See https://bugs.webkit.org/show_bug.cgi?id=115504
if
vals
[
0
]
==
"x-webkit-deflate-frame"
{
xWebkitDeflateFrame
=
true
return
true
}
return
false
}
key
:=
textproto
.
CanonicalMIMEHeaderKey
(
"Sec-WebSocket-Extensions"
)
for
_
,
v
:=
range
h
[
key
]
{
found
:=
searchHeaderTokens
(
v
,
match
)
if
found
!=
""
{
return
found
if
searchHeaderTokens
(
v
,
match
)
{
return
xWebkitDeflateFrame
,
params
,
true
}
}
return
""
return
false
,
nil
,
false
}
func
searchHeaderTokens
(
v
string
,
match
func
(
val
string
)
bool
)
string
{
func
searchHeaderTokens
(
v
string
,
match
func
(
val
string
)
bool
)
bool
{
v
=
strings
.
ToLower
(
v
)
v
=
strings
.
TrimSpace
(
v
)
for
_
,
v2
:=
range
strings
.
Split
(
v
,
","
)
{
v2
=
strings
.
TrimSpace
(
v2
)
v2
=
strings
.
ToLower
(
v2
)
if
match
(
v2
)
{
return
v2
return
true
}
}
return
""
return
false
}
func
selectSubprotocol
(
r
*
http
.
Request
,
subprotocols
[]
string
)
string
{
...
...
@@ -332,6 +350,10 @@ type CompressionOptions struct {
//
// Defaults to 256.
Threshold
int
// This is used for supporting Safari as it still uses x-webkit-deflate-frame.
// See negotiateCompression.
xWebkitDeflateFrame
bool
}
// Dial performs a WebSocket handshake on the given url with the given options.
...
...
@@ -407,7 +429,7 @@ func dial(ctx context.Context, u string, opts *DialOptions) (_ *Conn, _ *http.Re
req
.
Header
.
Set
(
"Sec-WebSocket-Protocol"
,
strings
.
Join
(
opts
.
Subprotocols
,
","
))
}
if
opts
.
Compression
!=
nil
{
opts
.
Compression
.
setHeader
(
req
.
Header
)
opts
.
Compression
.
setHeader
(
req
.
Header
,
true
)
}
resp
,
err
:=
opts
.
HTTPClient
.
Do
(
req
)
...
...
@@ -529,24 +551,30 @@ func makeSecWebSocketKey() (string, error) {
}
func
negotiateCompression
(
h
http
.
Header
,
copts
*
CompressionOptions
)
(
*
CompressionOptions
,
error
)
{
deflate
:=
h
ead
erTokenHasPrefix
(
h
,
"Sec-WebSocket-Extensions"
,
"permessage-deflate"
)
if
deflate
==
""
{
xWebkitDeflateFrame
,
params
,
ok
:=
r
ead
CompressionExtensionHeader
(
h
)
if
!
ok
{
return
nil
,
nil
}
// Ensures our changes do not modify the real compression options.
copts
=
&*
copts
params
:=
strings
.
Split
(
deflate
,
";"
)
for
i
:=
range
params
{
params
[
i
]
=
strings
.
TrimSpace
(
params
[
i
])
}
if
params
[
0
]
!=
"permessage-deflate"
{
return
nil
,
fmt
.
Errorf
(
"unexpected header format for permessage-deflate extension: %q"
,
deflate
)
copts
.
xWebkitDeflateFrame
=
xWebkitDeflateFrame
// We are the client if the header contains the accept header, meaning its from the server.
client
:=
h
.
Get
(
"Sec-WebSocket-Accept"
)
==
""
if
copts
.
xWebkitDeflateFrame
{
// The other endpoint dictates whether or not we can
// use context takeover on our side. We cannot force it.
// Likewise, we tell the other side so we can force that.
if
client
{
copts
.
ClientNoContextTakeover
=
false
}
else
{
copts
.
ServerNoContextTakeover
=
false
}
}
for
_
,
p
:=
range
params
[
1
:
]
{
for
_
,
p
:=
range
params
{
switch
p
{
case
"client_no_context_takeover"
:
copts
.
ClientNoContextTakeover
=
true
...
...
@@ -555,27 +583,55 @@ func negotiateCompression(h http.Header, copts *CompressionOptions) (*Compressio
copts
.
ServerNoContextTakeover
=
true
continue
case
"client_max_window_bits"
,
"server-max-window-bits"
:
server
:=
h
.
Get
(
"Sec-WebSocket-Key"
)
!=
""
if
server
{
if
!
client
{
// If we are the server, we are allowed to ignore these parameters.
// However, if we are the client, we must obey them but because of
// https://github.com/golang/go/issues/3155 we cannot.
continue
}
case
"no_context_takeover"
:
if
copts
.
xWebkitDeflateFrame
{
if
client
{
copts
.
ClientNoContextTakeover
=
true
}
else
{
copts
.
ServerNoContextTakeover
=
true
}
continue
}
// We explicitly fail on x-webkit-deflate-frame's max_window_bits parameter instead
// of ignoring it as the draft spec is unclear. It says the server can ignore it
// but the server has no way of signalling to the client it was ignored as parameters
// are set one way.
// Thus us ignoring it would make the client think we understood it which would cause issues.
// See https://tools.ietf.org/html/draft-tyoshino-hybi-websocket-perframe-deflate-06#section-4.1
//
// Either way, we're only implementing this for webkit which never sends the max_window_bits
// parameter so we don't need to worry about it.
}
return
nil
,
fmt
.
Errorf
(
"unsupported permessage-deflate parameter %q in header: %q"
,
p
,
deflate
)
return
nil
,
fmt
.
Errorf
(
"unsupported permessage-deflate parameter: %q"
,
p
)
}
return
copts
,
nil
}
func
(
copts
*
CompressionOptions
)
setHeader
(
h
http
.
Header
)
{
s
:=
"permessage-deflate"
if
copts
.
ClientNoContextTakeover
{
s
+=
"; client_no_context_takeover"
}
if
copts
.
ServerNoContextTakeover
{
s
+=
"; server_no_context_takeover"
func
(
copts
*
CompressionOptions
)
setHeader
(
h
http
.
Header
,
client
bool
)
{
var
s
string
if
!
copts
.
xWebkitDeflateFrame
{
s
:=
"permessage-deflate"
if
copts
.
ClientNoContextTakeover
{
s
+=
"; client_no_context_takeover"
}
if
copts
.
ServerNoContextTakeover
{
s
+=
"; server_no_context_takeover"
}
}
else
{
s
=
"x-webkit-deflate-frame"
// We can only set no context takeover for the peer.
if
client
&&
copts
.
ServerNoContextTakeover
||
!
client
&&
copts
.
ClientNoContextTakeover
{
s
+=
"; no_context_takeover"
}
}
h
.
Set
(
"Sec-WebSocket-Extensions"
,
s
)
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment