(w http.ResponseWriter, r *http.Request)
| 182 | } |
| 183 | |
| 184 | func verifyClientRequest(w http.ResponseWriter, r *http.Request) (errCode int, _ error) { |
| 185 | if !r.ProtoAtLeast(1, 1) { |
| 186 | return http.StatusUpgradeRequired, fmt.Errorf("WebSocket protocol violation: handshake request must be at least HTTP/1.1: %q", r.Proto) |
| 187 | } |
| 188 | |
| 189 | if !headerContainsTokenIgnoreCase(r.Header, "Connection", "Upgrade") { |
| 190 | w.Header().Set("Connection", "Upgrade") |
| 191 | w.Header().Set("Upgrade", "websocket") |
| 192 | return http.StatusUpgradeRequired, fmt.Errorf("WebSocket protocol violation: Connection header %q does not contain Upgrade", r.Header.Get("Connection")) |
| 193 | } |
| 194 | |
| 195 | if !headerContainsTokenIgnoreCase(r.Header, "Upgrade", "websocket") { |
| 196 | w.Header().Set("Connection", "Upgrade") |
| 197 | w.Header().Set("Upgrade", "websocket") |
| 198 | return http.StatusUpgradeRequired, fmt.Errorf("WebSocket protocol violation: Upgrade header %q does not contain websocket", r.Header.Get("Upgrade")) |
| 199 | } |
| 200 | |
| 201 | if r.Method != "GET" { |
| 202 | return http.StatusMethodNotAllowed, fmt.Errorf("WebSocket protocol violation: handshake request method is not GET but %q", r.Method) |
| 203 | } |
| 204 | |
| 205 | if r.Header.Get("Sec-WebSocket-Version") != "13" { |
| 206 | w.Header().Set("Sec-WebSocket-Version", "13") |
| 207 | return http.StatusBadRequest, fmt.Errorf("unsupported WebSocket protocol version (only 13 is supported): %q", r.Header.Get("Sec-WebSocket-Version")) |
| 208 | } |
| 209 | |
| 210 | websocketSecKeys := r.Header.Values("Sec-WebSocket-Key") |
| 211 | if len(websocketSecKeys) == 0 { |
| 212 | return http.StatusBadRequest, errors.New("WebSocket protocol violation: missing Sec-WebSocket-Key") |
| 213 | } |
| 214 | |
| 215 | if len(websocketSecKeys) > 1 { |
| 216 | return http.StatusBadRequest, errors.New("WebSocket protocol violation: multiple Sec-WebSocket-Key headers") |
| 217 | } |
| 218 | |
| 219 | // The RFC states to remove any leading or trailing whitespace. |
| 220 | websocketSecKey := strings.TrimSpace(websocketSecKeys[0]) |
| 221 | if v, err := base64.StdEncoding.DecodeString(websocketSecKey); err != nil || len(v) != 16 { |
| 222 | return http.StatusBadRequest, fmt.Errorf("WebSocket protocol violation: invalid Sec-WebSocket-Key %q, must be a 16 byte base64 encoded string", websocketSecKey) |
| 223 | } |
| 224 | |
| 225 | return 0, nil |
| 226 | } |
| 227 | |
| 228 | func authenticateOrigin(r *http.Request, originHosts []string) error { |
| 229 | origin := r.Header.Get("Origin") |
searching dependent graphs…