Skip to content
This repository has been archived by the owner on Jul 13, 2023. It is now read-only.

Commit

Permalink
refactor: extract a simple BaseHandler
Browse files Browse the repository at this point in the history
  • Loading branch information
pjenvey committed Aug 29, 2016
1 parent 031e144 commit a794e20
Show file tree
Hide file tree
Showing 12 changed files with 76 additions and 131 deletions.
46 changes: 46 additions & 0 deletions autopush/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import uuid

import cyclone.web
from twisted.logger import Logger
from twisted.python import failure


class BaseHandler(cyclone.web.RequestHandler):
"""Base cyclone RequestHandler for autopush"""

log = Logger()

def initialize(self, ap_settings):
"""Setup basic attributes from AutopushSettings"""
self.ap_settings = ap_settings
self._client_info = self._init_info()

def _init_info(self):
return dict(
ami_id=self.ap_settings.ami_id,
request_id=str(uuid.uuid4()),
user_agent=self.request.headers.get('user-agent', ""),
remote_ip=self.request.headers.get('x-forwarded-for',
self.request.remote_ip),
authorization=self.request.headers.get('authorization', ""),
message_ttl=self.request.headers.get('ttl', ""),
)

def write_error(self, code, **kwargs):
"""Write the error (otherwise unhandled exception when dealing with
unknown method specifications.)
This is a Cyclone API Override method used by endpoint and
websocket.
"""
self.set_status(code)
if 'exc_info' in kwargs:
self.log.failure(
format=kwargs.get('format', "Exception"),
failure=failure.Failure(*kwargs['exc_info']),
**self._client_info)
else:
self.log.failure("Error in handler: %s" % code,
**self._client_info)
self.finish()
24 changes: 4 additions & 20 deletions autopush/endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from twisted.internet.defer import Deferred
from twisted.internet.threads import deferToThread

from autopush.base import BaseHandler
from autopush.db import (
generate_last_connect,
hasher,
Expand All @@ -51,7 +52,6 @@
from autopush.utils import (
generate_hash,
validate_uaid,
ErrorLogger,
extract_jwt,
base64url_encode,
)
Expand Down Expand Up @@ -119,7 +119,7 @@ def parse_request_params(request):
return version, data


class AutoendpointHandler(ErrorLogger, cyclone.web.RequestHandler):
class AutoendpointHandler(BaseHandler):
"""Common overrides for Autoendpoint handlers"""
cors_methods = ""
cors_request_headers = ()
Expand All @@ -130,13 +130,9 @@ class AutoendpointHandler(ErrorLogger, cyclone.web.RequestHandler):
#############################################################
def initialize(self, ap_settings):
"""Setup basic aliases and attributes"""
self.uaid_hash = ""
self._uaid = ""
self._chid = ""
self.ap_settings = ap_settings
super(AutoendpointHandler, self).initialize(ap_settings)
self.uaid_hash = self._uaid = self._chid = ""
self.metrics = ap_settings.metrics
self.request_id = str(uuid.uuid4())
self._client_info = self._init_info()

def prepare(self):
"""Common request preparation"""
Expand Down Expand Up @@ -184,18 +180,6 @@ def chid(self, value):
self._chid = normalize_id(value)
self._client_info["channelID"] = self._chid

def _init_info(self):
"""Returns a dict of additional client data"""
return {
"ami_id": self.ap_settings.ami_id,
"request_id": self.request_id,
"user_agent": self.request.headers.get("user-agent", ""),
"remote_ip": self.request.headers.get("x-forwarded-for",
self.request.remote_ip),
"authorization": self.request.headers.get("authorization", ""),
"message_ttl": self.request.headers.get("ttl", ""),
}

#############################################################
# Error Callbacks
#############################################################
Expand Down
14 changes: 3 additions & 11 deletions autopush/health.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
"""Health Check HTTP Handler"""
import cyclone.web
from autopush.endpoint import AutoendpointHandler
from autopush.base import BaseHandler

from boto.dynamodb2.exceptions import (
InternalServerError,
)
from twisted.internet.defer import DeferredList
from twisted.internet.threads import deferToThread
from twisted.logger import Logger

from autopush import __version__

Expand All @@ -17,12 +16,8 @@ class MissingTableException(Exception):
pass


class HealthHandler(AutoendpointHandler):
class HealthHandler(BaseHandler):
"""HTTP Health Handler"""
log = Logger()

def initialize(self, ap_settings):
self.ap_settings = ap_settings

@cyclone.web.asynchronous
def get(self):
Expand Down Expand Up @@ -83,12 +78,9 @@ def _finish_response(self, results):
self.finish()


class StatusHandler(cyclone.web.RequestHandler):
class StatusHandler(BaseHandler):
"""HTTP Status Handler"""

def initialize(self, ap_settings):
self.ap_settings = ap_settings

def get(self):
"""HTTP Get
Expand Down
3 changes: 0 additions & 3 deletions autopush/log_check.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import uuid

import cyclone.web

from autopush.endpoint import AutoendpointHandler
Expand All @@ -13,7 +11,6 @@ class LogCheckHandler(AutoendpointHandler):

def initialize(self, ap_settings):
self.ap_settings = ap_settings
self.request_id = str(uuid.uuid4())
self._client_info = self._init_info()

@cyclone.web.asynchronous
Expand Down
6 changes: 3 additions & 3 deletions autopush/tests/test_endpoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ class EndpointTestCase(unittest.TestCase):
["location", "www-authenticate"]
)

@patch('uuid.uuid4', return_value=uuid.UUID(dummy_request_id))
def setUp(self, t):
def setUp(self):
from twisted.logger import Logger
# this timeout *should* be set to 0.5, however Travis runs
# so slow, that many of these tests will time out leading
Expand Down Expand Up @@ -454,7 +453,8 @@ def handle_finish(value):
self.finish_deferred.addCallback(handle_finish)
return self.finish_deferred

def test_init_info(self):
@patch('uuid.uuid4', return_value=uuid.UUID(dummy_request_id))
def test_init_info(self, t):
d = self.endpoint._init_info()
eq_(d["request_id"], dummy_request_id)
h = self.request_mock.headers
Expand Down
14 changes: 7 additions & 7 deletions autopush/tests/test_web_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,8 @@ class TestBase(unittest.TestCase):
["location", "www-authenticate"]
)

@patch('uuid.uuid4', return_value=uuid.UUID(dummy_request_id))
def setUp(self, t):
from autopush.web.base import BaseHandler
def setUp(self):
from autopush.web.base import BaseWebHandler

settings = AutopushSettings(
hostname="localhost",
Expand All @@ -59,9 +58,9 @@ def setUp(self, t):
headers={"ttl": "0"},
host='example.com:8080')

self.base = BaseHandler(Application(),
self.request_mock,
ap_settings=settings)
self.base = BaseWebHandler(Application(),
self.request_mock,
ap_settings=settings)
self.status_mock = self.base.set_status = Mock()
self.write_mock = self.base.write = Mock()
self.base.log = Mock(spec=Logger)
Expand Down Expand Up @@ -157,7 +156,8 @@ def test_write_error_no_exc(self):
self.status_mock.assert_called_with(999)
eq_(self.base.log.failure.called, True)

def test_init_info(self):
@patch('uuid.uuid4', return_value=uuid.UUID(dummy_request_id))
def test_init_info(self, t):
h = self.request_mock.headers
h["user-agent"] = "myself"
self.request_mock.remote_ip = "local1"
Expand Down
6 changes: 2 additions & 4 deletions autopush/tests/test_web_webpush.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from cryptography.fernet import Fernet
from cyclone.web import Application
from mock import Mock, patch
from mock import Mock
from moto import mock_dynamodb2
from nose.tools import eq_
from twisted.internet.defer import Deferred
Expand All @@ -16,7 +16,6 @@
from autopush.router.interface import IRouter, RouterResponse
from autopush.settings import AutopushSettings

dummy_request_id = "11111111123412341234567812345678"
dummy_uaid = str(uuid.UUID("abad1dea00000000aabbccdd00000000"))
dummy_chid = str(uuid.UUID("deadbeef00000000decafbad00000000"))
dummy_token = dummy_uaid + ":" + dummy_chid
Expand All @@ -33,8 +32,7 @@ def tearDown():


class TestWebpushHandler(unittest.TestCase):
@patch('uuid.uuid4', return_value=uuid.UUID(dummy_request_id))
def setUp(self, t):
def setUp(self):
from autopush.web.webpush import WebPushHandler

settings = AutopushSettings(
Expand Down
25 changes: 0 additions & 25 deletions autopush/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import ecdsa
import requests
from jose import jws
from twisted.logger import Logger
from twisted.python import failure
from ua_parser import user_agent_parser


Expand Down Expand Up @@ -196,26 +194,3 @@ def parse_user_agent(agent_string):
raw_info["ua_browser_ver"] = ".".join(filter(None, browser_bits))

return dd_info, raw_info


class ErrorLogger(object):
log = Logger()

def write_error(self, code, **kwargs):
"""Write the error (otherwise unhandled exception when dealing with
unknown method specifications.)
This is a Cyclone API Override method used by endpoint and websocket.
"""
self.set_status(code)
if "exc_info" in kwargs:
fmt = kwargs.get("format", "Exception")
self.log.failure(
format=fmt,
failure=failure.Failure(*kwargs["exc_info"]),
**self._client_info)
else:
self.log.failure("Error in handler: %s" % code,
**self._client_info)
self.finish()
48 changes: 4 additions & 44 deletions autopush/web/base.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import json
import time
import uuid
from collections import namedtuple

import cyclone.web
from boto.dynamodb2.exceptions import (
ProvisionedThroughputExceededException,
)
from boto.exception import BotoServerError
from twisted.logger import Logger
from twisted.python import failure

from autopush.base import BaseHandler
from autopush.db import (
hasher,
normalize_id,
Expand Down Expand Up @@ -41,30 +38,23 @@ class Notification(namedtuple("Notification",

class VapidAuthException(Exception):
"""Exception if the VAPID Auth token fails"""
pass


class BaseHandler(cyclone.web.RequestHandler):
class BaseWebHandler(BaseHandler):
"""Common overrides for Push web API's"""
cors_methods = ""
cors_request_headers = ()
cors_response_headers = ()

log = Logger()

#############################################################
# Cyclone API Methods
#############################################################
def initialize(self, ap_settings):
"""Setup basic aliases and attributes"""
self.uaid_hash = ""
self._uaid = ""
self._chid = ""
super(BaseWebHandler, self).initialize(ap_settings)
self.uaid_hash = self._uaid = self._chid = ""
self.start_time = time.time()
self.ap_settings = ap_settings
self.metrics = ap_settings.metrics
self.request_id = str(uuid.uuid4())
self._client_info = self._init_info()

def prepare(self):
"""Common request preparation"""
Expand All @@ -77,25 +67,6 @@ def prepare(self):
self.set_header("Access-Control-Expose-Headers",
",".join(self.cors_response_headers))

def write_error(self, code, **kwargs):
"""Write the error (otherwise unhandled exception when dealing with
unknown method specifications.)
This is a Cyclone API Override.
"""
self.set_status(code)
if "exc_info" in kwargs:
fmt = kwargs.get("format", "Exception")
self.log.failure(
format=fmt,
failure=failure.Failure(*kwargs["exc_info"]),
**self._client_info)
else:
self.log.failure("Error in handler: %s" % code,
**self._client_info)
self.finish()

#############################################################
# Cyclone HTTP Methods
#############################################################
Expand Down Expand Up @@ -131,17 +102,6 @@ def chid(self, value):
self._chid = normalize_id(value)
self._client_info["channelID"] = self._chid

def _init_info(self):
"""Returns a dict of additional client data"""
return {
"request_id": self.request_id,
"user_agent": self.request.headers.get("user-agent", ""),
"remote_ip": self.request.headers.get("x-forwarded-for",
self.request.remote_ip),
"authorization": self.request.headers.get("authorization", ""),
"message_ttl": self.request.headers.get("ttl", ""),
}

#############################################################
# Error Callbacks
#############################################################
Expand Down
4 changes: 2 additions & 2 deletions autopush/web/simplepush.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from twisted.internet.defer import Deferred

from autopush.web.base import (
BaseHandler,
BaseWebHandler,
Notification,
)
from autopush.web.validation import (
Expand All @@ -12,7 +12,7 @@
)


class SimplePushHandler(BaseHandler):
class SimplePushHandler(BaseWebHandler):
cors_methods = "PUT"

@threaded_validate(SimplePushRequestSchema)
Expand Down
Loading

0 comments on commit a794e20

Please sign in to comment.