docs: def match(self, environ):
          ''' Return a (target, url_agrs) tuple or raise HTTPError(400/404/405). '''
          verb = environ['REQUEST_METHOD'].upper()
          path = environ['PATH_INFO'] or '/'
          target = None
          if verb == 'HEAD':
              methods = ['PROXY', verb, 'GET', 'ANY']
          else:
              methods = ['PROXY', verb, 'ANY']
  
          for method in methods:
              if method in self.static and path in self.static[method]:
                  target, getargs = self.static[method][path]
                  return target, getargs(path) if getargs else {}
              elif method in self.dyna_regexes:
                  for combined, rules in self.dyna_regexes[method]:
                      match = combined(path)
                      if match:
                          target, getargs = rules[match.lastindex - 1]
                          return target, getargs(path) if getargs else {}
  
          # No matching route found. Collect alternative methods for 405 response
          allowed = set([])
          nocheck = set(methods)
          for method in set(self.static) - nocheck:
              if path in self.static[method]:
                  allowed.add(verb)
          for method in set(self.dyna_regexes) - allowed - nocheck:
              for combined, rules in self.dyna_regexes[method]:
                  match = combined(path)
                  if match:
                      allowed.add(method)
          if allowed:
              allow_header = ",".join(sorted(allowed))
              raise HTTPError(405, "Method not allowed.", Allow=allow_header)
  
          # No matching route and no alternative method found. We give up
          raise HTTPError(404, "Not found: " + repr(path))