ServeHTTP implements [http.Handler].
(responseWriter http.ResponseWriter, request *http.Request)
| 257 | |
| 258 | // ServeHTTP implements [http.Handler]. |
| 259 | func (h *Handler) ServeHTTP(responseWriter http.ResponseWriter, request *http.Request) { |
| 260 | // We don't need to defer functions to close the request body or read to |
| 261 | // EOF: the stream we construct later on already does that, and we only |
| 262 | // return early when dealing with misbehaving clients. In those cases, it's |
| 263 | // okay if we can't re-use the connection. |
| 264 | isBidi := (h.spec.StreamType & StreamTypeBidi) == StreamTypeBidi |
| 265 | if isBidi && request.ProtoMajor < 2 { |
| 266 | // Clients coded to expect full-duplex connections may hang if they've |
| 267 | // mistakenly negotiated HTTP/1.1. To unblock them, we must close the |
| 268 | // underlying TCP connection. |
| 269 | responseWriter.Header().Set("Connection", "close") |
| 270 | responseWriter.WriteHeader(http.StatusHTTPVersionNotSupported) |
| 271 | return |
| 272 | } |
| 273 | |
| 274 | protocolHandlers := h.protocolHandlers[request.Method] |
| 275 | if len(protocolHandlers) == 0 { |
| 276 | responseWriter.Header().Set("Allow", h.allowMethod) |
| 277 | responseWriter.WriteHeader(http.StatusMethodNotAllowed) |
| 278 | return |
| 279 | } |
| 280 | |
| 281 | contentType := canonicalizeContentType(getHeaderCanonical(request.Header, headerContentType)) |
| 282 | |
| 283 | // Find our implementation of the RPC protocol in use. |
| 284 | var protocolHandler protocolHandler |
| 285 | for _, handler := range protocolHandlers { |
| 286 | if handler.CanHandlePayload(request, contentType) { |
| 287 | protocolHandler = handler |
| 288 | break |
| 289 | } |
| 290 | } |
| 291 | if protocolHandler == nil { |
| 292 | responseWriter.Header().Set("Accept-Post", h.acceptPost) |
| 293 | responseWriter.WriteHeader(http.StatusUnsupportedMediaType) |
| 294 | return |
| 295 | } |
| 296 | |
| 297 | if request.Method == http.MethodGet { |
| 298 | // A body must not be present. |
| 299 | hasBody := request.ContentLength > 0 |
| 300 | if request.ContentLength < 0 { |
| 301 | // No content-length header. |
| 302 | // Test if body is empty by trying to read a single byte. |
| 303 | var b [1]byte |
| 304 | n, _ := request.Body.Read(b[:]) |
| 305 | hasBody = n > 0 |
| 306 | } |
| 307 | if hasBody { |
| 308 | responseWriter.WriteHeader(http.StatusUnsupportedMediaType) |
| 309 | return |
| 310 | } |
| 311 | _ = request.Body.Close() |
| 312 | } |
| 313 | |
| 314 | // Establish a stream and serve the RPC. |
| 315 | setHeaderCanonical(request.Header, headerContentType, contentType) |
| 316 | setHeaderCanonical(request.Header, headerHost, request.Host) |