Repository: elastic/apm-agent-python

Issue:
Crash with wrong URL
**Describe the bug**: 

Crash due to someone sending the wrong URL format:

```

ValueError: Port could not be cast to integer value as '${port}'
  File "elasticapm/contrib/django/middleware/__init__.py", line 176, in process_response
    elasticapm.set_context(
  File "elasticapm/traces.py", line 1155, in set_context
    data = data()
  File "elasticapm/contrib/django/middleware/__init__.py", line 177, in <lambda>
    lambda: self.client.get_data_from_request(request, constants.TRANSACTION), "request"
  File "elasticapm/contrib/django/client.py", line 155, in get_data_from_request
    result["url"] = get_url_dict(url)
  File "elasticapm/utils/__init__.py", line 118, in get_url_dict
    port = None if parse_result.port is None else str(parse_result.port)
  File "urllib/parse.py", line 175, in port
    raise ValueError(message) from None
```

**To Reproduce**

1. Send `${ip}:${port}` as URL (or any other not valid URL). Here's a copy of the headers that were sent from nginx to our gunicorn server. 

```
request_headers | 
{'accept': '*/*', 
'connection': 'close', 
'host': '${ip}:${port}', 
'user-agent': 'curl/7.64.1', 
'x-forwarded-for': '152.32.255.215', 
'x-forwarded-host': 'mydomain_here', 
'x-forwarded-proto': 'https', 'x-real-ip': '152.32.255.215'}
```
**Environment (please complete the following information)**
- OS: Linux
- Python version: 3.10
- Framework and version: Django/3.2.13
- Agent version: 6.9.1



Discussion:

Resolving patch:
diff --git a/elasticapm/contrib/django/client.py b/elasticapm/contrib/django/client.py
--- a/elasticapm/contrib/django/client.py
+++ b/elasticapm/contrib/django/client.py
@@ -152,7 +152,10 @@ def get_data_from_request(self, request, event_type):
                     result["body"] = data
 
         url = get_raw_uri(request)
-        result["url"] = get_url_dict(url)
+        try:
+            result["url"] = get_url_dict(url)
+        except ValueError as exc:
+            self.logger.warning(f"URL parsing failed: {exc}")
         return result
 
     def get_data_from_response(self, response, event_type):


Test patch:
diff --git a/tests/contrib/django/django_tests.py b/tests/contrib/django/django_tests.py
--- a/tests/contrib/django/django_tests.py
+++ b/tests/contrib/django/django_tests.py
@@ -1671,3 +1671,26 @@ def test_transaction_name_from_class_based_view(client, django_elasticapm_client
         client.get(reverse("elasticapm-class-based"))
         transaction = django_elasticapm_client.events[TRANSACTION][0]
         assert transaction["name"] == "GET tests.contrib.django.testapp.views.ClassBasedView"
+
+
+def test_request_bad_port(django_elasticapm_client):
+    request = WSGIRequest(
+        environ={
+            "wsgi.input": io.BytesIO(),
+            "REQUEST_METHOD": "POST",
+            "SERVER_NAME": "testserver",
+            "SERVER_PORT": "${port}",
+            "CONTENT_TYPE": "text/html",
+            "ACCEPT": "text/html",
+        }
+    )
+    request.read(1)
+
+    django_elasticapm_client.capture("Message", message="foo", request=request)
+
+    assert len(django_elasticapm_client.events[ERROR]) == 1
+    event = django_elasticapm_client.events[ERROR][0]
+
+    assert "request" in event["context"]
+    request = event["context"]["request"]
+    assert "url" not in request