Skip to content

Commit 39d804b

Browse files
authored
Merge pull request #6 from feliphebueno/develop
Promoção
2 parents 51de289 + a8ffe71 commit 39d804b

8 files changed

Lines changed: 248 additions & 22 deletions

File tree

CHANGELOG

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
Version 1.15.2:
2+
Update v1.15.2
3+
Adição do sistema de log
4+
15
Version 1.12.0:
26
Update v1.12.0
37
Adição de documentação

README.md

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Django-based REST Framework
44

5-
# Requires
5+
# Install requires
66

77
```PHP
88
pip install rinzler
@@ -12,30 +12,45 @@ pip install rinzler
1212
```Python
1313

1414
# urls.py
15+
16+
import os
17+
import rinzler
18+
19+
from rinzler.core.main_controller import MainController
1520
from your_controller import Controller
16-
from rinzler.core.url_assembler import UrlAssembler
1721

18-
assembler = UrlAssembler()
22+
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
23+
24+
app = rinzler.boot(BASE_DIR)
25+
assembler = app['url_assembler']
1926

2027
urlpatterns = [
21-
assembler.mount('', Controller)
28+
assembler.mount('hello', Controller),
29+
assembler.mount('', MainController),
2230
]
2331

32+
```
2433

34+
```Python
2535
# your_controller.py
36+
from collections import OrderedDict
2637

2738
from django.http.request import HttpRequest
2839
from django.views.generic import TemplateView
2940

3041
from rinzler.core.response import Response
3142

43+
3244
class Controller(TemplateView):
3345

3446
def connect(self, app):
3547

3648
router = app['router']
3749

38-
router.get('/', self.hello_world)
50+
# Definir end-points aqui
51+
router.get('/world/', self.hello_world)
52+
router.get('/{name}/', self.hello_user)
53+
3954
return app
4055

4156
# end-point callbacks here:
@@ -48,10 +63,82 @@ class Controller(TemplateView):
4863
:param params dict url params, if present
4964
:rtype: Response
5065
"""
51-
response = {
52-
"status": True,
53-
"data": "Hello World!"
54-
}
66+
try:
67+
response = OrderedDict()
68+
response["status"] = True
69+
response["data"] = "Hello World!"
70+
71+
return Response(response, content_type="application/json")
72+
except BaseException as e:
73+
response = OrderedDict()
74+
response["status"] = False
75+
response["mensagem"] = str(e)
76+
77+
return Response(response, content_type="application/json", status=500)\
78+
79+
@staticmethod
80+
def hello_user(request: HttpRequest, app: dict(), **params: dict):
81+
"""
82+
Default route callback
83+
:param request HttpRequest
84+
:param app Rinzler's object
85+
:param params dict url params, if present
86+
:rtype: Response
87+
"""
88+
try:
89+
user = params['name']
90+
response = OrderedDict()
91+
response["status"] = True
92+
response["data"] = "Hello {0}!".format(user)
93+
94+
return Response(response, content_type="application/json")
95+
except BaseException as e:
96+
response = OrderedDict()
97+
response["status"] = False
98+
response["mensagem"] = str(e)
99+
100+
return Response(response, content_type="application/json", status=500)
55101

56-
return Response(response, content_type="application/json")
57102
```
103+
### Run django
104+
```shell
105+
python manage.py runserver
106+
August 02, 2017 - 18:48:00
107+
Django version 1.10.4, using settings 'Demo.settings'
108+
Starting development server at http://127.0.0.1:8000/
109+
Quit the server with CONTROL-C.
110+
```
111+
112+
### Sample requests
113+
114+
```shell
115+
curl http://localhost:8000/
116+
<center><h1>HTTP/1.1 200 OK RINZLER FRAMEWORK</h1></center>
117+
118+
curl http://localhost:8000/hello/world/
119+
{
120+
"status": true,
121+
"data": "Hello World!"
122+
}
123+
124+
curl http://localhost:8000/hello/bob/
125+
{
126+
"status": true,
127+
"data": "Hello bob!"
128+
}
129+
130+
curl http://localhost:8000/foo/bar/
131+
{
132+
"status": false,
133+
"exceptions": {
134+
"message": "No route found for GET foo/bar/"
135+
},
136+
"request": {
137+
"content": "",
138+
"method": "GET",
139+
"path_info": "foo/bar/"
140+
},
141+
"message": "We are sorry, but something went terribly wrong."
142+
}
143+
144+
```

rinzler/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
import os
2+
3+
from .logger.log import Log
4+
from .core.url_assembler import UrlAssembler
5+
16
__name__ = "Rinzler REST Framework"
27
__version__ = "1.12.0"
38
__author__ = "Rinzler"
9+
10+
11+
def boot(base_path: str()):
12+
logger = Log(os.path.realpath(base_path) + "/log").get_logger()
13+
url_assembler = UrlAssembler().set_logger(logger)
14+
15+
logger.info("App booted =)")
16+
17+
return {
18+
'url_assembler': url_assembler,
19+
'log': logger
20+
}

rinzler/core/router.py

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
"""
22
CallbackResolver service module
33
"""
4+
import codecs
5+
import os
46
import re
57
from collections import OrderedDict
68

@@ -18,9 +20,10 @@ class Router(TemplateView):
1820
__request = None
1921
__callable = None
2022
__app = dict()
21-
__route = None
22-
__uri = None
23-
__method = None
23+
__route = str()
24+
__end_point_uri = str()
25+
__uri = str()
26+
__method = str()
2427
__bound_routes = dict()
2528
__auth_service = None
2629
__allowed_headers = "Authorization, Content-Type, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since," \
@@ -30,7 +33,6 @@ class Router(TemplateView):
3033
def __init__(self, route, controller):
3134
self.__route = route
3235
self.__callable = controller
33-
self.__app['router'] = object()
3436

3537
@csrf_exempt
3638
def route(self, request: HttpRequest):
@@ -44,28 +46,33 @@ def route(self, request: HttpRequest):
4446
self.__method = request.method
4547
self.__app['router'] = RouteMapping()
4648
self.__bound_routes = dict()
49+
self.__app['log'].set_signature(codecs.encode(os.urandom(3), "hex").decode("utf-8").upper())
4750

4851
routes = self.__callable().connect(self.__app)
4952

5053
self.__bound_routes = routes['router'].get__routes()
5154

52-
end_point = self.get_end_point_uri()
53-
acutal_params = self.get_url_params(end_point)
54-
5555
request_headers = request.META
5656
indent = 2 if re.match("[Mozilla]{7}", request_headers['HTTP_USER_AGENT']) else 0
5757

58+
if self.set_end_point_uri() is False:
59+
return self.set_response_headers(self.no_route_found(self.__request).render(indent))
60+
61+
acutal_params = self.get_url_params(self.get_end_point_uri())
62+
5863
try:
5964
response = self.exec_route_callback(acutal_params)
6065
if type(response) == Response:
6166
return self.set_response_headers(response.render(indent))
6267
else:
6368
return self.set_response_headers(response)
6469
except AuthException as e:
70+
self.__app['log'].warning("< {0}: 403".format(str(e)), exc_info=True)
6571
response = Response(OrderedDict({"status": False, "message": str(e)}), content_type="application/json",
6672
status=403, charset="utf-8")
6773
return self.set_response_headers(response.render(indent))
6874
except BaseException as e:
75+
self.__app['log'].error("< {0}: 500".format(str(e)), exc_info=True)
6976
response = Response(OrderedDict({"status": False, "message": str(e)}), content_type="application/json",
7077
status=500, charset="utf-8")
7178
return self.set_response_headers(response.render(indent))
@@ -74,7 +81,7 @@ def exec_route_callback(self, actual_params):
7481
"""
7582
Executes the resolved end-point callback, or its fallback
7683
:param actual_params dict
77-
:rtype: Object
84+
:rtype: object
7885
"""
7986
if self.__method.lower() in self.__bound_routes:
8087
for bound in self.__bound_routes[self.__method.lower()]:
@@ -83,6 +90,7 @@ def exec_route_callback(self, actual_params):
8390
expected_params = self.get_url_params(route)
8491

8592
if self.request_matches_route(self.get_end_point_uri(), route):
93+
self.__app['log'].info("> {0} {1}".format(self.__method, self.__uri))
8694
authenticate = self.authenticate(route, actual_params)
8795
if authenticate:
8896
pattern_params = self.get_callback_pattern(expected_params, actual_params)
@@ -91,6 +99,7 @@ def exec_route_callback(self, actual_params):
9199
return authenticate
92100

93101
if self.__method == "OPTIONS":
102+
self.__app['log'].info("Route matched: {0} {1}".format(self.__method, self.__uri))
94103
return self.default_route_options(self.__request)
95104

96105
if self.__route == '' and self.__uri == '':
@@ -131,7 +140,8 @@ def authenticate(self, bound_route, actual_params):
131140
auth_route = "{0}_{1}{2}".format(self.__method, self.__route, bound_route)
132141
auth_data = self.__auth_service.authenticate(self.__request, auth_route, actual_params)
133142
self.__app['auth_data'] = auth_data
134-
return True
143+
144+
return True
135145

136146
@staticmethod
137147
def get_callback_pattern(expected_params, actual_params):
@@ -171,12 +181,29 @@ def get_url_params(end_point):
171181
return params
172182

173183
def get_end_point_uri(self):
184+
"""
185+
Returns the value of __end_point_uri
186+
:rtype: str
187+
"""
188+
return self.__end_point_uri
189+
190+
def set_end_point_uri(self):
174191
"""
175192
Gets the route from the accessed URL
176193
:rtype: str
177194
"""
195+
expected_parts = self.__route.split("/")
196+
actual_parts = self.__uri.split("/")
197+
198+
i = 0
199+
for part in expected_parts:
200+
if part != actual_parts[i]:
201+
return False
202+
i = i + 1
203+
178204
uri_prefix = len(self.__route)
179-
return self.__uri[uri_prefix:]
205+
self.__end_point_uri = self.__uri[uri_prefix:]
206+
return True
180207

181208
def no_route_found(self, request):
182209
"""
@@ -240,6 +267,10 @@ def set_response_headers(self, response: HttpResponse):
240267
for key in response_headers:
241268
response[key] = response_headers[key]
242269

270+
status = response.status_code
271+
if status != 404:
272+
self.__app['log'].info("< {0}".format(status))
273+
243274
return response
244275

245276
def auth_config(self, auth_service: object):
@@ -250,3 +281,12 @@ def auth_config(self, auth_service: object):
250281
"""
251282
self.__auth_service = auth_service
252283
return self
284+
285+
def register(self, name: str(), handler: object(), force=False):
286+
if name in self.__app:
287+
if force is True:
288+
self.__app[name] = handler
289+
else:
290+
self.__app[name] = handler
291+
292+
return self

rinzler/core/url_assembler.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,18 @@
66
class UrlAssembler(object):
77

88
auth_service = None
9+
base_path = str()
10+
logger = object
911

1012
def mount(self, route, callback):
1113
"""
1214
Mounts a route with the given params
1315
:rtype: urls
1416
"""
15-
return url(r'{0}'.format(route), Router(route, callback).auth_config(self.auth_service).route)
17+
return url(
18+
r'{0}'.format(route),
19+
Router(route, callback).register('log', self.logger).auth_config(self.auth_service).route
20+
)
1621

1722
def set_auth_service(self, auth_service):
1823
"""
@@ -21,3 +26,7 @@ def set_auth_service(self, auth_service):
2126
"""
2227
self.auth_service = auth_service
2328
return self
29+
30+
def set_logger(self, logger: object()):
31+
self.logger = logger
32+
return self

rinzler/logger/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)