def METHOD_NAME(self, method, url, body=None, headers=None):
    """
    This will send a request to the server using the HTTP request method
    ``method`` and the selector ``url``. If the ``body`` argument is
    present, it should be string or bytes object of data to send after the
    headers are finished. Strings are encoded as UTF-8. To use other
    encodings, pass a bytes object. The Content-Length header is set to the
    length of the body field.
    :param method: The request method, e.g. ``'GET'``.
    :param url: The URL to contact, e.g. ``'/path/segment'``.
    :param body: (optional) The request body to send. Must be a bytestring
        or a file-like object.
    :param headers: (optional) The headers to send on the request.
    :returns: A stream ID for the request, or ``None`` if the request is
        made over HTTP/1.1.
    """
    headers = headers or {}
    try:
        return self._conn.METHOD_NAME(
            method=method, url=url, body=body, headers=headers
        )
    except TLSUpgrade as e:
        # We upgraded in the NPN/ALPN handshake. We can just go straight to
        # the world of HTTP/2. Replace the backing object and insert the
        # socket into it.
        assert e.negotiated in H2_NPN_PROTOCOLS
        self._conn = HTTP20Connection(
            self._host, self._port, **self._h2_kwargs
        )
        self._conn._sock = e.sock
        # Because we skipped the connecting logic, we need to send the
        # HTTP/2 preamble.
        self._conn._send_preamble()
        return self._conn.METHOD_NAME(
            method=method, url=url, body=body, headers=headers
        )