// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package websocketimport ()var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")func computeAcceptKey( string) string { := sha1.New() .Write([]byte()) .Write(keyGUID)returnbase64.StdEncoding.EncodeToString(.Sum(nil))}func generateChallengeKey() (string, error) { := make([]byte, 16)if , := io.ReadFull(rand.Reader, ); != nil {return"", }returnbase64.StdEncoding.EncodeToString(), nil}// Token octets per RFC 2616.var isTokenOctet = [256]bool{'!': true,'#': true,'$': true,'%': true,'&': true,'\'': true,'*': true,'+': true,'-': true,'.': true,'0': true,'1': true,'2': true,'3': true,'4': true,'5': true,'6': true,'7': true,'8': true,'9': true,'A': true,'B': true,'C': true,'D': true,'E': true,'F': true,'G': true,'H': true,'I': true,'J': true,'K': true,'L': true,'M': true,'N': true,'O': true,'P': true,'Q': true,'R': true,'S': true,'T': true,'U': true,'W': true,'V': true,'X': true,'Y': true,'Z': true,'^': true,'_': true,'`': true,'a': true,'b': true,'c': true,'d': true,'e': true,'f': true,'g': true,'h': true,'i': true,'j': true,'k': true,'l': true,'m': true,'n': true,'o': true,'p': true,'q': true,'r': true,'s': true,'t': true,'u': true,'v': true,'w': true,'x': true,'y': true,'z': true,'|': true,'~': true,}// skipSpace returns a slice of the string s with all leading RFC 2616 linear// whitespace removed.func skipSpace( string) ( string) { := 0for ; < len(); ++ {if := []; != ' ' && != '\t' {break } }return [:]}// nextToken returns the leading RFC 2616 token of s and the string following// the token.func nextToken( string) (, string) { := 0for ; < len(); ++ {if !isTokenOctet[[]] {break } }return [:], [:]}// nextTokenOrQuoted returns the leading token or quoted string per RFC 2616// and the string following the token or quoted string.func nextTokenOrQuoted( string) ( string, string) {if !strings.HasPrefix(, "\"") {returnnextToken() } = [1:]for := 0; < len(); ++ {switch [] {case'"':return [:], [+1:]case'\\': := make([]byte, len()-1) := copy(, [:]) := truefor = + 1; < len(); ++ { := []switch {case : = false [] = ++case == '\\': = truecase == '"':returnstring([:]), [+1:]default: [] = ++ } }return"", "" } }return"", ""}// equalASCIIFold returns true if s is equal to t with ASCII case folding as// defined in RFC 4790.func equalASCIIFold(, string) bool {for != "" && != "" { , := utf8.DecodeRuneInString() = [:] , := utf8.DecodeRuneInString() = [:]if == {continue }if'A' <= && <= 'Z' { = + 'a' - 'A' }if'A' <= && <= 'Z' { = + 'a' - 'A' }if != {returnfalse } }return == }// tokenListContainsValue returns true if the 1#token header with the given// name contains a token equal to value with ASCII case folding.func tokenListContainsValue( http.Header, string, string) bool {:for , := range [] {for {varstring , = nextToken(skipSpace())if == "" {continue } = skipSpace()if != "" && [0] != ',' {continue }ifequalASCIIFold(, ) {returntrue }if == "" {continue } = [1:] } }returnfalse}// parseExtensions parses WebSocket extensions from a header.func parseExtensions( http.Header) []map[string]string {// From RFC 6455: // // Sec-WebSocket-Extensions = extension-list // extension-list = 1#extension // extension = extension-token *( ";" extension-param ) // extension-token = registered-token // registered-token = token // extension-param = token [ "=" (token | quoted-string) ] // ;When using the quoted-string syntax variant, the value // ;after quoted-string unescaping MUST conform to the // ;'token' ABNF.var []map[string]string:for , := range ["Sec-Websocket-Extensions"] {for {varstring , = nextToken(skipSpace())if == "" {continue } := map[string]string{"": }for { = skipSpace()if !strings.HasPrefix(, ";") {break }varstring , = nextToken(skipSpace([1:]))if == "" {continue } = skipSpace()varstringifstrings.HasPrefix(, "=") { , = nextTokenOrQuoted(skipSpace([1:])) = skipSpace() }if != "" && [0] != ',' && [0] != ';' {continue } [] = }if != "" && [0] != ',' {continue } = append(, )if == "" {continue } = [1:] } }return}// isValidChallengeKey checks if the argument meets RFC6455 specification.func isValidChallengeKey( string) bool {// From RFC6455: // // A |Sec-WebSocket-Key| header field with a base64-encoded (see // Section 4 of [RFC4648]) value that, when decoded, is 16 bytes in // length.if == "" {returnfalse } , := base64.StdEncoding.DecodeString()return == nil && len() == 16}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.