Repository: django/channels

Issue:
request.META['SERVER_PORT'] should be a string (?)
Found while debugging an issue with Opbeat: https://github.com/opbeat/opbeat_python/issues/131

ASGI request in django channels initialises `request.META['SERVER_PORT']` using an integer value: https://github.com/django/channels/blob/master/channels/handler.py#L68

```
ipdb> self.message['server']
['127.0.0.1', 7000]
```

This later results in:

```
ipdb> request.META['SERVER_PORT']
7000
```

This appears to be in contradiction with the django docs (https://docs.djangoproject.com/en/1.10/ref/request-response/#django.http.HttpRequest.META) that state:

> SERVER_PORT – The port of the server (as a string).

Which causes the mismatch and failure to validate when posting to opbeat.

To me it feels that port should be handled as an integer rather than a string, but I see that using a string goes back to the WSGI spec https://www.python.org/dev/peps/pep-0333/#environ-variables and probably is a heritage from CGI times.

I wonder which is the correct way forward. If this should be a string in ASGI requests as well, I'm happy to volunteer a PR.



Discussion:
The correct response to this is to just change the handler to make it a string in the `META` dictionary for backwards-compat; there's no need to change ASGI, it uses an int because it's not basing directly off CGI and it's string-based interface.

Yeah, makes sense. I'll look at making a PR tomorrow.

I see there is an open PR for this in #370 

@andrewgodwin  Is this issue is fixed ?

Indeed it is! Forgot to cross close.

Are you sure it is? The PR with a preliminary fix #370 was closed unmerged, and I don't see a relevant change in the [history of `handler.py`](https://github.com/django/channels/commits/master/channels/handler.py) where @andrewgodwin suggested the fix should go.

Happy to volunteer a more thorough fix.

Urgh, sorry, I saw it was closed and forgot how it had been. Re-opening - and my comment about text types on that ticket still applies if you'd like to have a crack at it!

Sure, I'll give it a go tomorrow.


Resolving patch:
diff --git a/channels/handler.py b/channels/handler.py
--- a/channels/handler.py
+++ b/channels/handler.py
@@ -66,7 +66,7 @@ def __init__(self, message):
             self.META['REMOTE_PORT'] = self.message['client'][1]
         if self.message.get('server', None):
             self.META['SERVER_NAME'] = self.message['server'][0]
-            self.META['SERVER_PORT'] = self.message['server'][1]
+            self.META['SERVER_PORT'] = six.text_type(self.message['server'][1])
         # Handle old style-headers for a transition period
         if "headers" in self.message and isinstance(self.message['headers'], dict):
             self.message['headers'] = [


Test patch:
diff --git a/channels/tests/test_request.py b/channels/tests/test_request.py
--- a/channels/tests/test_request.py
+++ b/channels/tests/test_request.py
@@ -63,7 +63,7 @@ def test_extended(self):
         self.assertEqual(request.META["REMOTE_HOST"], "10.0.0.1")
         self.assertEqual(request.META["REMOTE_PORT"], 1234)
         self.assertEqual(request.META["SERVER_NAME"], "10.0.0.2")
-        self.assertEqual(request.META["SERVER_PORT"], 80)
+        self.assertEqual(request.META["SERVER_PORT"], "80")
         self.assertEqual(request.GET["x"], "1")
         self.assertEqual(request.GET["y"], "&foo bar+baz")
         self.assertEqual(request.COOKIES["test-time"], "1448995585123")