text: import re
  import threading
  from urllib.parse import parse_qs, urlencode, urlsplit, urlunsplit
  
  from seleniumwire.utils import is_list_alike
  
  
  class RequestModifier:
      """This class is responsible for modifying request and response attributes.
  
      DEPRECATED. Use request and response interceptors instead.
  
      Instances of this class are designed to be stateful and threadsafe.
      """
  
      def __init__(self):
          """Initialise a new RequestModifier."""
          self._lock = threading.Lock()
          self._headers = {}
          self._params = {}
          self._querystring = None
          self._rewrite_rules = []
  
      @property
      def headers(self):
          """The header overrides for outgoing browser requests.
  
          The value of the headers can be a dictionary or list of sublists,
          with each sublist having two elements - a URL pattern and headers.
          Where a header in the dictionary exists in the request, the dictionary
          value will overwrite the one in the request. Where a header in the dictionary
          does not exist in the request, it will be added to the request as a
          new header. To filter out a header from the request, set that header
          in the dictionary to None. Header names are case insensitive.
          For response headers, prefix the header name with 'response:'.
  
          For example:
  
              headers = {
                  'User-Agent': 'Firefox',
                  'response:Cache-Control': 'none'
              }
              headers = [
                  ('.*somewhere.com.*', {'User-Agent': 'Firefox', 'response:Cache-Control': 'none'}),
                  ('*.somewhere-else.com.*', {'User-Agent': 'Chrome'})
          """
          with self._lock:
              if is_list_alike(self._headers):
                  return self._headers
              else:
                  return dict(self._headers)
  
      @headers.setter
      def headers(self, headers):
          """Sets the headers to override request headers.
  
          Args:
              headers: The dictionary of headers or list of sublists,
              with each sublist having two elements - the pattern and headers
              to set.
          """
          with self._lock:
              self._headers = headers
  
      @headers.deleter
      def headers(self):
          """Clears the headers being used to override request headers.
  
          After this is called, request headers will pass through unmodified.
          """
          with self._lock:
              self._headers.clear()
  
      @property
      def params(self):
          """The params that should be used to override the request params.
  
          For POST requests, the parameters are assumed to be encoded in the
          request body.
  
          The value of the params can be a dictionary or list of sublists,
          with each sublist having two elements - a URL pattern and params.
          Where a param in the dictionary exists in the request, the dictionary
          value will overwrite the one in the request. Where a param in the dictionary
          does not exist in the request, it will be added to the request as a
          new param. To filter out a param from the request, set that param
          in the dictionary to None.
  
          For example:
              params = {'foo': 'bar'}
              params = [
                  ('.*somewhere.com.*', {'foo': 'bar'}),
                  ('*.somewhere-else.com.*', {'x': 'y'}),
              ]
          """
          with self._lock:
              if is_list_alike(self._params):
                  return self._params
              else:
                  return dict(self._params)
  
      @params.setter
      def params(self, params):
          """Sets the params to override request params.
  
          Args:
              params: The dictionary of params or list of sublists,
              with each sublist having two elements - the pattern and params
              to set.
          """
          with self._lock:
              self._params = params
  
      @params.deleter
      def params(self):
          """Clears the params being used to override request params.
  
          After this is called, request params will pass through unmodified.
          """
          with self._lock:
              self._params.clear()
  
      @property
      def querystring(self):
          """The querystring overrides for outgoing browser requests.
  
          The value of the querystring override can be a string or a list of sublists,
          with each sublist having two elements, a URL pattern and the querystring.
          The querystring override will overwrite the querystring in the request
          or will be added to the request if the request has no querystring. To
          remove a querystring from the request, set the value to empty string.
  
          For example:
              querystring = 'foo=bar&x=y'
              querystring = [
                  ('.*somewhere.com.*', 'foo=bar&x=y'),
                  ('*.somewhere-else.com.*', 'a=b&c=d'),
              ]
          """
          with self._lock:
              return self._querystring
  
      @querystring.setter
      def querystring(self, querystring):
          """Sets the querystring to override request querystring.
  
          Args:
              querystring: The querystring.
          """
          with self._lock:
              self._querystring = querystring
  
      @querystring.deleter
      def querystring(self):
          """Clears the querystring being used to override request querystring."""
          with self._lock:
              self._querystring = None
  
      @property
      def rewrite_rules(self):
          """The rules used to rewrite request URLs.
  
          The value of the rewrite rules should be a list of sublists (or tuples)
          with each sublist containing the pattern and replacement.
  
          For example:
              rewrite_rules = [
                  (r'(https?://)www.google.com/', r'\1www.bing.com/'),
                  (r'https://docs.python.org/2/', r'https://docs.python.org/3/'),
              ]
          """
          with self._lock:
              return [(pat.pattern, repl) for pat, repl in self._rewrite_rules]
  
      @rewrite_rules.setter
      def rewrite_rules(self, rewrite_rules):
          """Sets the rewrite rules used to modify request URLs.
  
          Args:
              rewrite_rules: The list of rewrite rules, which should
                  be a list of sublists, with each sublist having two
                  elements - the pattern and replacement.
          """
          compiled = []
          for pattern, replacement in rewrite_rules:
              compiled.append((re.compile(pattern), replacement))
  
          with self._lock:
              self._rewrite_rules = compiled
  
      @rewrite_rules.deleter
      def rewrite_rules(self):
          """Clears the rewrite rules being used to modify request URLs.
  
          After this is called, request URLs will no longer be modified.
          """
          with self._lock:
              self._rewrite_rules.clear()
  
      def modify_request(self, request, urlattr='url', methodattr='method', headersattr='headers', bodyattr='body'):
          """Performs modifications to the request.
  
          Args:
              request: The request to modify.
              urlattr: The name of the url attribute on the request object.
              methodattr: The name of the method attribute on the request object.
              headersattr: The name of the headers attribute on the request object.
              bodyattr: The name of the body attribute on the request object.
          """
          override_headers = self._get_matching_overrides(self._headers, getattr(request, urlattr))
          if override_headers:
              # We're only interested in request headers
              override_headers = {
                  name: value
                  for name, value in (override_headers or {}).items()
                  if not name.lower().startswith('response:')
              }
              self._modify_headers(getattr(request, headersattr), override_headers)
          self._modify_params(request, urlattr, methodattr, headersattr, bodyattr)
          self._modify_querystring(request, urlattr)
          self._rewrite_url(request, urlattr, headersattr)
  
      def modify_response(self, response, request, urlattr='url', headersattr='headers'):
          """Performs modifications to the response.
  
          Args:
              response: The response to modify.
              request: The original request.
              urlattr: The name of the url attribute on the response object.
              headersattr: The name of the headers attribute on the response object.
          """
          override_headers = self._get_matching_overrides(self._headers, getattr(request, urlattr))
  
          # We're only interested in response headers
          override_headers = {
              name.split(':', maxsplit=1)[1].strip(): value
              for name, value in (override_headers or {}).items()
              if name.lower().startswith('response:')
          }
  
          if override_headers:
              self._modify_headers(getattr(response, headersattr), override_headers)
  
      def _modify_headers(self, headers, override_headers):
          headers_lc = {h.lower(): (h, v) for h, v in override_headers.items()}
  
          # Remove/replace any header that already exists in the request/response
          for header in list(headers):
              try:
                  value = headers_lc.pop(header.lower())[1]
              except KeyError:
                  pass
              else:
                  del headers[header]
                  if value is not None:
                      headers[header] = value
  
          # Add new headers to the request/response that don't already exist
          for header, value in headers_lc.values():
              if value is not None:
                  headers[header] = value
  
      def _modify_params(self, request, urlattr, methodattr, headersattr, bodyattr):
          request_url = getattr(request, urlattr)
          params = self._get_matching_overrides(self._params, request_url)
  
          if not params:
              return
  
          method = getattr(request, methodattr)
          headers = getattr(request, headersattr)
          query = urlsplit(request_url).query
          is_form_data = headers.get('Content-Type') == 'application/x-www-form-urlencoded'
  
          if method == 'POST' and is_form_data:
              query = getattr(request, bodyattr).decode('utf-8', errors='replace')
  
          request_params = parse_qs(query, keep_blank_values=True)
  
          with self._lock:
              # Override the params in the request
              request_params.update(params)
  
          # Remove existing params where they have a 'None' value
          for name, value in list(request_params.items()):
              if value is None:
                  request_params.pop(name)
  
          query = urlencode(request_params, doseq=True)
  
          # Update the request with the new params
          if method == 'POST' and is_form_data:
              query = query.encode('utf-8')
              headers['Content-Length'] = str(len(query))
              setattr(request, bodyattr, query)
          else:
              scheme, netloc, path, _, fragment = urlsplit(request_url)
              setattr(request, urlattr, urlunsplit((scheme, netloc, path, query, fragment)))
  
      def _modify_querystring(self, request, urlattr):
          request_url = getattr(request, urlattr)
          querystring = self._get_matching_overrides(self._querystring, request_url)
  
          if querystring is None:
              return
  
          scheme, netloc, path, _, fragment = urlsplit(request_url)
          setattr(request, urlattr, urlunsplit((scheme, netloc, path, querystring or '', fragment)))
  
      def _rewrite_url(self, request, urlattr, headersattr):
          request_headers = getattr(request, headersattr)
          request_url = getattr(request, urlattr)
  
          with self._lock:
              rewrite_rules = self._rewrite_rules[:]
  
          original_netloc = urlsplit(request_url).netloc
  
          for pattern, replacement in rewrite_rules:
              modified, count = pattern.subn(replacement, request_url)
  
              if count > 0:
                  setattr(request, urlattr, modified)
                  break
  
          request_url = getattr(request, urlattr)
          modified_netloc = urlsplit(request_url).netloc
  
          if original_netloc != modified_netloc:
              # Modify the Host header if it exists
              if 'Host' in request_headers:
                  request_headers['Host'] = modified_netloc
  
      def _get_matching_overrides(self, overrides, url):
          with self._lock:
              # If the overrides is tuple or list, we need to match against the URL
              if is_list_alike(overrides):
                  for pat, ov in overrides:
                      match = re.search(pat, url)
                      if match:
                          return ov
              else:
                  return overrides
  