|
1 | 1 | ''' Start of Application. This function is the gunicorn server '''
|
2 |
| -import os |
3 |
| -import re |
4 |
| - |
5 |
| -# Load environment variable from .env file |
6 |
| -from dotenv import find_dotenv, load_dotenv |
7 |
| -load_dotenv(find_dotenv()) |
8 |
| - |
9 |
| -from masonite.request import Request |
10 |
| -from masonite.routes import Route |
11 |
| -from masonite.storage import Storage |
12 |
| -from masonite.app import App |
13 |
| -from config import middleware, application |
14 | 2 | from pydoc import locate
|
15 | 3 |
|
16 |
| - |
17 |
| -# Run once and only once the server is ran |
18 |
| -# This will not actually compile if the libsass module in not installed |
19 |
| -Storage().compile_sass() |
20 |
| - |
21 | 4 | def app(environ, start_response):
|
22 |
| - ''' Framework Engine ''' |
23 |
| - os.environ.setdefault('REQUEST_METHOD', environ['REQUEST_METHOD']) |
24 |
| - os.environ.setdefault('URI_PATH', environ['PATH_INFO']) |
25 |
| - |
26 |
| - # Instantiate the Service Container |
27 |
| - app = App() |
28 |
| - |
29 |
| - # Instantiate the Request object. |
30 |
| - # This is the `request` object passed into controller methods |
31 |
| - request = Request(environ) |
32 |
| - |
33 |
| - # Bind the Request object into the container |
34 |
| - app.bind('Request', request) |
35 |
| - |
36 |
| - # Execute all the register methods in all containers |
37 |
| - for provider in application.PROVIDERS: |
38 |
| - locate(provider)().load_app(app).register() |
39 |
| - |
40 |
| - # Execute all the boot methods in all containers |
41 |
| - for provider in application.PROVIDERS: |
42 |
| - app.resolve(locate(provider)().boot) |
43 |
| - |
44 |
| - # Load the container into the request |
45 |
| - app.make('Request').load_app(app) |
46 |
| - |
47 |
| - router = Route(environ) |
48 |
| - |
49 |
| - if router.is_post(): |
50 |
| - # Set POST parameters given into the query string to centralize parsing and retrieval. |
51 |
| - # This was made to directly support the Request.input() method. |
52 |
| - # There is no known reason to differentiate between GET and POST when retrieving |
53 |
| - # form paramters. This line below simply puts both POST form params in the |
54 |
| - # same query_string as GET params. |
55 |
| - environ['QUERY_STRING'] = router.set_post_params() |
56 |
| - |
57 |
| - # Get all routes from the routes/web.py file |
58 |
| - import routes.web |
59 |
| - routes = routes.web.ROUTES |
60 |
| - |
61 |
| - # Check all http routes |
62 |
| - for route in routes: |
63 |
| - # Compiles the given route to regex |
64 |
| - regex = router.compile_route_to_regex(route) |
65 |
| - |
66 |
| - # Make a better match trailing slashes `/` at the end of routes |
67 |
| - # Sometimes a user will end with a trailing slash. Because the |
68 |
| - # user may create routes like `/url/route` and `/url/route/` |
69 |
| - # and how the regex is compiled down, we may need to adjust for |
70 |
| - # urls that end or dont end with a trailing slash. This is sort |
71 |
| - # of a quirk and could possibly be fixed. |
72 |
| - if route.route_url.endswith('/'): |
73 |
| - matchurl = re.compile(regex.replace(r'\/\/$', r'\/$')) |
74 |
| - else: |
75 |
| - matchurl = re.compile(regex.replace(r'\/$', r'$')) |
76 |
| - |
77 |
| - # This will create a dictionary of paramters given. This is a sort of a short |
78 |
| - # but complex way to retrieve the url paramters. This is the code used to |
79 |
| - # convert /url/@firstname/@lastname to {'firstmane': 'joseph', 'lastname': 'mancuso'} |
80 |
| - try: |
81 |
| - parameter_dict = {} |
82 |
| - for index, value in enumerate(matchurl.match(router.url).groups()): |
83 |
| - parameter_dict[router.generated_url_list()[index]] = value |
84 |
| - request.set_params(parameter_dict) |
85 |
| - except AttributeError: |
86 |
| - pass |
87 |
| - |
88 |
| - # If the route url matches the regex and the method type and the route can continue |
89 |
| - # (will be used with middleware later) |
90 |
| - if matchurl.match(router.url) and route.method_type == environ['REQUEST_METHOD'] and route.continueroute is True: |
91 |
| - |
92 |
| - # Execute HTTP Before Middleware |
93 |
| - for http_middleware in middleware.HTTP_MIDDLEWARE: |
94 |
| - located_middleware = locate(http_middleware) |
95 |
| - if hasattr(located_middleware, 'before'): |
96 |
| - located_middleware(request).before() |
97 |
| - |
98 |
| - # Show a helper in the terminal of which route has been visited |
99 |
| - print(route.method_type + ' Route: ' + router.url) |
100 |
| - |
101 |
| - # Loads the request in so the middleware specified is able to use the |
102 |
| - # request object. This is before middleware and is ran before the request |
103 |
| - route.load_request(request).run_middleware('before') |
104 |
| - |
105 |
| - # Get the data from the route. This data is typically the output |
106 |
| - # of the controller method |
107 |
| - if not request.redirect_url: |
108 |
| - data = router.get(route.route, app.resolve(route.output)) |
109 |
| - |
110 |
| - # Loads the request in so the middleware specified is able to use the |
111 |
| - # request object. This is after middleware and is ran after the request |
112 |
| - route.load_request(request).run_middleware('after') |
113 |
| - |
114 |
| - # Execute HTTP After Middleware |
115 |
| - for http_middleware in middleware.HTTP_MIDDLEWARE: |
116 |
| - located_middleware = locate(http_middleware) |
117 |
| - if hasattr(located_middleware, 'after'): |
118 |
| - located_middleware(request).after() |
119 |
| - break |
120 |
| - else: |
121 |
| - data = 'Route not found. Error 404' |
122 |
| - |
123 |
| - ## Check all API Routes |
124 |
| - if data == 'Route not found. Error 404': |
125 |
| - # Look at the API routes files |
126 |
| - import routes.api |
127 |
| - routes = routes.api.ROUTES |
128 |
| - |
129 |
| - for route in routes: |
130 |
| - |
131 |
| - # If the base url matches |
132 |
| - if route.url in router.url: |
133 |
| - data = route.fetch(request).output |
134 |
| - if data: |
135 |
| - break |
136 |
| - else: |
137 |
| - data = 'Route not found. Error 404' |
138 |
| - else: |
139 |
| - data = 'Route not found. Error 404' |
140 |
| - |
141 |
| - # Set redirection if a route has been called to redirect to. |
142 |
| - # redirect_route is a property set on the request object when |
143 |
| - # methods like request.redirectTo('nameRoute') are called |
144 |
| - if request.redirect_route: |
145 |
| - for route in routes: |
146 |
| - if route.named_route == request.redirect_route: |
147 |
| - print(route.method_type + ' Named Route: ' + router.url) |
148 |
| - data = router.get(route.route, route.output(request)) |
149 |
| - request.redirect_url = route.route_url |
150 |
| - |
151 |
| - if not request.redirect_url: |
152 |
| - # Convert the data that is retrieved above to bytes so the wsgi server can handle it. |
153 |
| - data = bytes(data, 'utf-8') |
154 |
| - |
155 |
| - # Normal HTTP response. |
156 |
| - start_response("200 OK", [ |
157 |
| - ("Content-Type", "text/html; charset=utf-8"), |
158 |
| - ("Content-Length", str(len(data))) |
159 |
| - ] + request.get_cookies()) |
160 |
| - else: |
161 |
| - data = bytes('redirecting ..', 'utf-8') |
162 |
| - # Redirection. In order to redirect the response types need to be 302 instead of 200 |
163 |
| - start_response("302 OK", [ |
164 |
| - ('Location', request.compile_route_to_url()) |
165 |
| - ] + request.get_cookies()) |
166 |
| - |
167 |
| - # This will output the data to the browser. |
168 |
| - return iter([data]) |
| 5 | + from wsgi import container |
| 6 | + |
| 7 | + ''' |
| 8 | + |-------------------------------------------------------------------------- |
| 9 | + | Startup the Service Container |
| 10 | + |-------------------------------------------------------------------------- |
| 11 | + | |
| 12 | + | Instantiate the Service Container so we can bind classes into it and |
| 13 | + | bind the environ variable that is created by the WSGI server into |
| 14 | + | the container. |
| 15 | + | |
| 16 | + ''' |
| 17 | + |
| 18 | + container.bind('Environ', environ) |
| 19 | + |
| 20 | + ''' |
| 21 | + |-------------------------------------------------------------------------- |
| 22 | + | Execute All Service Providers |
| 23 | + |-------------------------------------------------------------------------- |
| 24 | + | |
| 25 | + | Run all service provider boot methods if the wsgi attribute is true. |
| 26 | + | |
| 27 | + ''' |
| 28 | + |
| 29 | + for provider in container.make('Application').PROVIDERS: |
| 30 | + located_provider = locate(provider)().load_app(container) |
| 31 | + if located_provider.wsgi is True: |
| 32 | + container.resolve(located_provider.boot) |
| 33 | + |
| 34 | + ''' |
| 35 | + |-------------------------------------------------------------------------- |
| 36 | + | We Are Ready For Launch |
| 37 | + |-------------------------------------------------------------------------- |
| 38 | + | |
| 39 | + | If we have a solid response and not redirecting then we need to return |
| 40 | + | a 200 status code along with the data. If we don't, then we'll have |
| 41 | + | to return a 302 and redirect to where the developer would like to |
| 42 | + | go next. |
| 43 | + | |
| 44 | + ''' |
| 45 | + |
| 46 | + start_response(container.make('StatusCode'), container.make('Headers')) |
| 47 | + |
| 48 | + ''' |
| 49 | + |-------------------------------------------------------------------------- |
| 50 | + | Final Step |
| 51 | + |-------------------------------------------------------------------------- |
| 52 | + | |
| 53 | + | This will take the data variable from above and return it to the WSGI |
| 54 | + | server. |
| 55 | + | |
| 56 | + ''' |
| 57 | + |
| 58 | + return iter([bytes(container.make('Response'), 'utf-8')]) |
0 commit comments