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']
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
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, '', ''))