def test_http_no_payload(server, method):
    with HttpClient(
        "localhost", server.port, disable_certificate_validation=True
    ) as client:
        connection = client._connection_attr
        status, data = client.send_request(method=method, headers={"foo": "bar"})

    assert status == 200
    data = ensure_str(data)
    data = data.split("\n")

    # Verify connection has been closed
    assert client._connection_attr is None
    assert connection.pool is None

    # Verify request line
    assert data[0].startswith(method + " /agent_listener/invoke_raw_method ")

    # Verify headers
    user_agent_header = ""
    foo_header = ""

    for header in data[1:-1]:
        if header.lower().startswith("user-agent:"):
            _, value = header.split(":", 1)
            value = value.strip()
            user_agent_header = value
        elif header.startswith("foo:"):
            _, value = header.split(":", 1)
            value = value.strip()
            foo_header = value

    assert user_agent_header.startswith("NewRelic-PythonAgent/")
    assert foo_header == "bar"
    def _process_synthetics_header(self):
        # Check for Synthetics header

        settings = self._settings

        if settings.synthetics.enabled and \
                settings.trusted_account_ids and \
                settings.encoding_key:

            encoded_header = self._request_headers.get('x-newrelic-synthetics')
            encoded_header = encoded_header and ensure_str(encoded_header)
            if not encoded_header:
                return

            decoded_header = decode_newrelic_header(encoded_header,
                                                    settings.encoding_key)
            synthetics = _parse_synthetics_header(decoded_header)

            if synthetics and \
                    synthetics['account_id'] in \
                    settings.trusted_account_ids:

                # Save obfuscated header, because we will pass it along
                # unchanged in all external requests.

                self.synthetics_header = encoded_header
                self.synthetics_resource_id = synthetics['resource_id']
                self.synthetics_job_id = synthetics['job_id']
                self.synthetics_monitor_id = synthetics['monitor_id']
예제 #3
0
 def _process_context_headers(self):
     # Process the New Relic cross process ID header and extract
     # the relevant details.
     if self._settings.distributed_tracing.enabled:
         distributed_header = self._request_headers.get('newrelic')
         distributed_header = ensure_str(distributed_header)
         if distributed_header is not None:
             self.accept_distributed_trace_payload(distributed_header)
     else:
         client_cross_process_id = \
                 self._request_headers.get('x-newrelic-id')
         txn_header = self._request_headers.get('x-newrelic-transaction')
         self._process_incoming_cat_headers(client_cross_process_id,
                                            txn_header)
    def _process_queue_time(self):
        for queue_time_header in self.QUEUE_TIME_HEADERS:
            value = self._request_headers.get(queue_time_header)
            if not value:
                continue
            value = ensure_str(value)

            try:
                if value.startswith('t='):
                    self.queue_start = _parse_time_stamp(float(value[2:]))
                else:
                    self.queue_start = _parse_time_stamp(float(value))
            except Exception:
                pass

            if self.queue_start > 0.0:
                break
예제 #5
0
def fetch_app_id(app_name, client, headers):
    status, data = client.send_request(
        "GET",
        "/v2/applications.json",
        params={"filter[name]": app_name},
        headers=headers,
    )

    if not 200 <= status < 300:
        raise RuntimeError("Status not OK", status)

    response_json = encoding_utils.json_decode(encoding_utils.ensure_str(data))
    if "applications" not in response_json:
        return

    for application in response_json["applications"]:
        if application["name"] == app_name:
            return application["id"]
    def process_response(self, status_code, response_headers):
        """Processes response status and headers, extracting any
        details required and returning a set of additional headers
        to merge into that being returned for the web transaction.

        """

        if not self.enabled:
            return []

        # Extract response headers
        if response_headers:
            try:
                response_headers = response_headers.items()
            except Exception:
                pass

            for header, value in response_headers:
                header = ensure_str(header)
                if header is not None:
                    self._response_headers[header.lower()] = value

        try:
            self._response_code = int(status_code)

            # If response code is 304 do not insert CAT headers. See:
            # https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
            if self._response_code == 304:
                return []
        except Exception:
            pass

        if self.client_cross_process_id is None:
            return []

        # Generate CAT response headers
        try:
            read_length = int(self._request_headers.get('content-length'))
        except Exception:
            read_length = -1

        return self._generate_response_headers(read_length)
    def __init__(self,
                 application,
                 name,
                 group=None,
                 scheme=None,
                 host=None,
                 port=None,
                 request_method=None,
                 request_path=None,
                 query_string=None,
                 headers=None,
                 enabled=None):

        super(WebTransaction, self).__init__(application, enabled)

        # Flags for tracking whether RUM header and footer have been
        # generated.

        self.rum_header_generated = False
        self.rum_footer_generated = False

        if not self.enabled:
            return

        # Inputs
        self._request_uri = request_path
        self._request_method = request_method
        self._request_scheme = scheme
        self._request_host = host
        self._request_params = {}
        self._request_headers = {}

        try:
            self._port = int(port)
        except Exception:
            self._port = None

        # Response
        self._response_headers = {}
        self._response_code = None

        if headers is not None:
            try:
                headers = headers.items()
            except Exception:
                pass

            for k, v in headers:
                k = ensure_str(k)
                if k is not None:
                    self._request_headers[k.lower()] = v

        # Capture query request string parameters, unless we're in
        # High Security Mode.
        if query_string and not self._settings.high_security:
            query_string = ensure_str(query_string)
            try:
                params = urlparse.parse_qs(query_string,
                                           keep_blank_values=True)
                self._request_params.update(params)
            except Exception:
                pass

        self._process_queue_time()
        self._process_synthetics_header()
        self._process_context_headers()

        if name is not None:
            self.set_transaction_name(name, group, priority=1)
        elif request_path is not None:
            self.set_transaction_name(request_path, 'Uri', priority=1)
def _remove_query_string(url):
    url = ensure_str(url)
    out = urlparse.urlsplit(url)
    return urlparse.urlunsplit((out.scheme, out.netloc, out.path, '', ''))