MCPcopy
hub / github.com/grpc-ecosystem/grpc-gateway / ServeHTTP

Method ServeHTTP

runtime/mux.go:407–553  ·  view source on GitHub ↗

ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.URL.Path.

(w http.ResponseWriter, r *http.Request)

Source from the content-addressed store, hash-verified

405
406// ServeHTTP dispatches the request to the first handler whose pattern matches to r.Method and r.URL.Path.
407func (s *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
408 ctx := r.Context()
409
410 path := r.URL.Path
411 if !strings.HasPrefix(path, "/") {
412 _, outboundMarshaler := MarshalerForRequest(s, r)
413 s.routingErrorHandler(ctx, s, outboundMarshaler, w, r, http.StatusBadRequest)
414 return
415 }
416
417 // TODO(v3): remove UnescapingModeLegacy
418 if s.unescapingMode != UnescapingModeLegacy && r.URL.RawPath != "" {
419 path = r.URL.RawPath
420 }
421
422 if override := r.Header.Get("X-HTTP-Method-Override"); override != "" && !s.disableHTTPMethodOverride && s.isPathLengthFallback(r) {
423 if err := r.ParseForm(); err != nil {
424 _, outboundMarshaler := MarshalerForRequest(s, r)
425 sterr := status.Error(codes.InvalidArgument, err.Error())
426 s.errorHandler(ctx, s, outboundMarshaler, w, r, sterr)
427 return
428 }
429 r.Method = strings.ToUpper(override)
430 }
431
432 var pathComponents []string
433 // since in UnescapeModeLegacy, the URL will already have been fully unescaped, if we also split on "%2F"
434 // in this escaping mode we would be double unescaping but in UnescapingModeAllCharacters, we still do as the
435 // path is the RawPath (i.e. unescaped). That does mean that the behavior of this function will change its default
436 // behavior when the UnescapingModeDefault gets changed from UnescapingModeLegacy to UnescapingModeAllExceptReserved
437 if s.unescapingMode == UnescapingModeAllCharacters {
438 pathComponents = encodedPathSplitter.Split(path[1:], -1)
439 } else {
440 pathComponents = strings.Split(path[1:], "/")
441 }
442
443 lastPathComponent := pathComponents[len(pathComponents)-1]
444
445 for _, h := range s.handlers[r.Method] {
446 // If the pattern has a verb, explicitly look for a suffix in the last
447 // component that matches a colon plus the verb. This allows us to
448 // handle some cases that otherwise can't be correctly handled by the
449 // former LastIndex case, such as when the verb literal itself contains
450 // a colon. This should work for all cases that have run through the
451 // parser because we know what verb we're looking for, however, there
452 // are still some cases that the parser itself cannot disambiguate. See
453 // the comment there if interested.
454
455 var verb string
456 patVerb := h.pat.Verb()
457
458 idx := -1
459 if patVerb != "" && strings.HasSuffix(lastPathComponent, ":"+patVerb) {
460 idx = len(lastPathComponent) - len(patVerb) - 1
461 }
462 if idx == 0 {
463 _, outboundMarshaler := MarshalerForRequest(s, r)
464 s.routingErrorHandler(ctx, s, outboundMarshaler, w, r, http.StatusNotFound)

Calls 6

isPathLengthFallbackMethod · 0.95
handleHandlerMethod · 0.95
MarshalerForRequestFunction · 0.85
VerbMethod · 0.80
MatchAndEscapeMethod · 0.80
ErrorMethod · 0.45