From 2e6df69489d2ceba049330a2628cb7be3f4f095a Mon Sep 17 00:00:00 2001 From: Di Wu Date: Mon, 18 Jan 2016 22:31:01 -0800 Subject: [PATCH] forwarded for and forwarded protocol --- hc/api/tests/test_ping.py | 69 ++++++++++++++++++++++++--------------- hc/api/urls.py | 1 + hc/api/views.py | 8 +++-- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/hc/api/tests/test_ping.py b/hc/api/tests/test_ping.py index 23194888..ca942550 100644 --- a/hc/api/tests/test_ping.py +++ b/hc/api/tests/test_ping.py @@ -5,33 +5,28 @@ from hc.api.models import Check, Ping class PingTestCase(TestCase): - def test_it_works(self): - check = Check() - check.save() + def setUp(self): + super(PingTestCase, self).setUp() + self.check = Check.objects.create() - r = self.client.get("/ping/%s/" % check.code) + def test_it_works(self): + r = self.client.get("/ping/%s/" % self.check.code) assert r.status_code == 200 - same_check = Check.objects.get(code=check.code) + same_check = Check.objects.get(code=self.check.code) assert same_check.status == "up" - pings = list(Ping.objects.all()) - assert pings[0].scheme == "http" + ping = Ping.objects.latest("id") + assert ping.scheme == "http" def test_post_works(self): - check = Check() - check.save() - csrf_client = Client(enforce_csrf_checks=True) - r = csrf_client.post("/ping/%s/" % check.code) + r = csrf_client.post("/ping/%s/" % self.check.code) assert r.status_code == 200 def test_head_works(self): - check = Check() - check.save() - csrf_client = Client(enforce_csrf_checks=True) - r = csrf_client.head("/ping/%s/" % check.code) + r = csrf_client.head("/ping/%s/" % self.check.code) assert r.status_code == 200 assert Ping.objects.count() == 1 @@ -44,22 +39,44 @@ class PingTestCase(TestCase): "AppleWebKit/537.36 (KHTML, like Gecko) " "Chrome/44.0.2403.89 Safari/537.36") - check = Check() - check.save() - r = self.client.get("/ping/%s/" % check.code, HTTP_USER_AGENT=ua) + r = self.client.get("/ping/%s/" % self.check.code, HTTP_USER_AGENT=ua) assert r.status_code == 200 - pings = list(Ping.objects.all()) - assert pings[0].ua == ua + ping = Ping.objects.latest("id") + assert ping.ua == ua def test_it_truncates_long_ua(self): ua = "01234567890" * 30 - check = Check() - check.save() - r = self.client.get("/ping/%s/" % check.code, HTTP_USER_AGENT=ua) + r = self.client.get("/ping/%s/" % self.check.code, HTTP_USER_AGENT=ua) + assert r.status_code == 200 + + ping = Ping.objects.latest("id") + assert len(ping.ua) == 200 + assert ua.startswith(ping.ua) + + def test_it_reads_forwarded_ip(self): + ip = "1.1.1.1" + r = self.client.get("/ping/%s/" % self.check.code, + HTTP_X_FORWARDED_FOR=ip) + ping = Ping.objects.latest("id") + assert r.status_code == 200 + assert ping.remote_addr == "1.1.1.1" + + ip = "1.1.1.1, 2.2.2.2" + r = self.client.get("/ping/%s/" % self.check.code, + HTTP_X_FORWARDED_FOR=ip, REMOTE_ADDR="3.3.3.3") + ping = Ping.objects.latest("id") + assert r.status_code == 200 + assert ping.remote_addr == "1.1.1.1" + + def test_it_reads_forwarded_protocol(self): + r = self.client.get("/ping/%s/" % self.check.code, + HTTP_X_FORWARDED_PROTO="https") + ping = Ping.objects.latest("id") assert r.status_code == 200 + assert ping.scheme == "https" - pings = list(Ping.objects.all()) - assert len(pings[0].ua) == 200 - assert ua.startswith(pings[0].ua) + def test_it_never_caches(self): + r = self.client.get("/ping/%s/" % self.check.code) + assert "no-cache" in r.get("Cache-Control") diff --git a/hc/api/urls.py b/hc/api/urls.py index 75d37066..ab8c5842 100644 --- a/hc/api/urls.py +++ b/hc/api/urls.py @@ -1,4 +1,5 @@ from django.conf.urls import url + from hc.api import views urlpatterns = [ diff --git a/hc/api/views.py b/hc/api/views.py index 372129bb..e6eed57f 100644 --- a/hc/api/views.py +++ b/hc/api/views.py @@ -4,13 +4,16 @@ from django.contrib.humanize.templatetags.humanize import naturaltime from django.db.models import F from django.http import HttpResponse, HttpResponseBadRequest from django.utils import timezone +from django.views.decorators.cache import never_cache from django.views.decorators.csrf import csrf_exempt + from hc.api.decorators import uuid_or_400 from hc.api.models import Check, Ping @csrf_exempt @uuid_or_400 +@never_cache def ping(request, code): try: check = Check.objects.get(code=code) @@ -28,8 +31,9 @@ def ping(request, code): ping = Ping(owner=check) headers = request.META ping.n = check.n_pings - ping.remote_addr = headers.get("HTTP_X_REAL_IP", headers["REMOTE_ADDR"]) - ping.scheme = headers.get("HTTP_X_SCHEME", "http") + remote_addr = headers.get("HTTP_X_FORWARDED_FOR", headers["REMOTE_ADDR"]) + ping.remote_addr = remote_addr.split(",")[0] + ping.scheme = headers.get("HTTP_X_FORWARDED_PROTO", "http") ping.method = headers["REQUEST_METHOD"] # If User-Agent is longer than 200 characters, truncate it: ping.ua = headers.get("HTTP_USER_AGENT", "")[:200]