Passed
Push — master ( bb2a1a...1d7190 )
by Mingyu
01:27
created

app.views.Router.after_request()   A

Complexity

Conditions 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
cc 1
nop 1
1
from functools import wraps
2
import ujson
3
import time
4
5
from flask import Response, request
6
from flask_restful import Resource, abort
7
8
9
def auth_required(fn):
10
    """
11
    View decorator for access control.
12
13
    ### TODO
14
    If you want to access control easily with this decorator,
15
    fill 'wrapper()' function included (1) aborting when access denied client (2) Set user object to flask.g
16
17
    - About custom view decorator
18
    -> http://flask-docs-kr.readthedocs.io/ko/latest/patterns/viewdecorators.html
19
    """
20
    @wraps(fn)
21
    def wrapper(*args, **kwargs):
22
        return fn(*args, **kwargs)
23
24
    return wrapper
25
26
27
def json_required(*required_keys):
28
    """
29
    View decorator for JSON validation.
30
31
    - If content-type is not application/json : returns status code 406
32
    - If required_keys are not exist on request.json : returns status code 400
33
34
    :type required_keys: str
35
    """
36
    def decorator(fn):
37
        if fn.__name__ == 'get':
38
            print('[WARN] JSON with GET method? on "{}()"'.format(fn.__qualname__))
39
40
        @wraps(fn)
41
        def wrapper(*args, **kwargs):
42
            if not request.is_json:
43
                abort(406)
44
45
            for required_key in required_keys:
46
                if required_key not in request.json:
47
                    abort(400)
48
49
            return fn(*args, **kwargs)
50
        return wrapper
51
    return decorator
52
53
54
class BaseResource(Resource):
55
    """
56
    BaseResource with some helper functions based flask_restful.Resource
57
    """
58
    def __init__(self):
59
        self.now = time.strftime('%Y-%m-%d %H:%M:%S')
60
61
    @classmethod
62
    def unicode_safe_json_dumps(cls, data, status_code=200, **kwargs):
63
        """
64
        Helper function which processes json response with unicode using ujson
65
66
        :type data: dict or list
67
        :type status_code: int
68
69
        :rtype: Response
70
        """
71
        return Response(
72
            ujson.dumps(data, ensure_ascii=False),
73
            status_code,
74
            content_type='application/json; charset=utf8',
75
            **kwargs
76
        )
77
78
79
class Router(object):
80
    """
81
    REST resource routing helper class like standard flask 3-rd party libraries
82
    """
83
    def __init__(self, app=None):
84
        if app is not None:
85
            self.init_app(app)
86
87
    @staticmethod
88
    def after_request(response):
89
        """
90
        Set header - X-Content-Type-Options=nosniff, X-Frame-Options=deny before response
91
        """
92
        response.headers['X-Content-Type-Options'] = 'nosniff'
93
        response.headers['X-Frame-Options'] = 'deny'
94
95
        return response
96
97
    def init_app(self, app):
98
        """
99
        Routes resources. Use app.register_blueprint() aggressively
100
        """
101
        app.after_request(self.after_request)
102
103
        from app.views import sample
104
        app.register_blueprint(sample.api.blueprint)
105