1
+ #!/usr/bin/env python3
2
+
3
+ """
4
+ Dragon Cafe Microservices Application, with Menu, Login, and Fortune Cookie Microservice
5
+
6
+ Author: Sam Griffith | Org: Alta3 Research Inc.
7
+
8
+ This is a transitional application that has both the old routes and the new /v2 routes available.
9
+
10
+ The /v2 routes are essentially redirects to their respective microservices
11
+ """
12
+
13
+ from aiohttp import web
14
+ import jinja2
15
+ from pathlib import Path
16
+ import random
17
+ import requests
18
+ import socket
19
+ import os
20
+ import json
21
+
22
+ HOST = os .getenv ("DRAGON_HOST" , "0.0.0.0" )
23
+ LOCAL_IP = socket .gethostbyname (socket .gethostname ())
24
+ PORT = os .getenv ("DRAGON_PORT" , 2225 )
25
+ REG_ADDR = os .getenv ("SR_ADDRESS" , "127.0.0.1" )
26
+ REG_PORT = os .getenv ("SR_PORT" , 55555 )
27
+ SERVICE = os .path .basename (__file__ ).rstrip (".py" )
28
+
29
+
30
+ class Page :
31
+ def __init__ (self , filename , templates_dir = Path ("templates" ), args = {}, cookies = {}):
32
+ """
33
+ Create a new instance of an html page to be returned
34
+ :param filename: name of file found in the templates_dir
35
+ """
36
+ self .path = templates_dir
37
+ self .file = templates_dir / filename
38
+ self .args = args
39
+ self .cookies = cookies
40
+
41
+ def render (self ):
42
+ with open (self .file ) as f :
43
+ txt = f .read ()
44
+ print (f"Templating in { self .args } " )
45
+ j2 = jinja2 .Template (txt ).render (self .args )
46
+ resp = web .Response (text = j2 , content_type = 'text/html' )
47
+ for c , j in self .cookies :
48
+ resp .set_cookie (c , j )
49
+ return resp
50
+
51
+
52
+ def routes (app : web .Application ) -> None :
53
+ app .add_routes (
54
+ [
55
+ web .get ("/" , home ),
56
+ web .get ("/login" , login ),
57
+ web .get ("/v2/login" , login_v2 ),
58
+ web .get ("/v2/login/{ex_path}" , login_v2 ),
59
+ web .post ("/logging_in" , logging_in ),
60
+ web .get ("/fortune_cookie" , fortune_cookie ),
61
+ web .get ("/v2/fortune_cookie" , fortune_cookie_v2 ),
62
+ web .get ("/v2/fortune_cookie/{ex_path}" , fortune_cookie_v2 ),
63
+ web .get ("/fortune" , fortune ),
64
+ web .get ("/menu" , menu ),
65
+ web .get ("/v2/menu" , menu_v2 )
66
+ ]
67
+ )
68
+
69
+ async def login_v2 (request ) -> web .Response :
70
+ print (request )
71
+ ex_path = request .match_info .get ('ex_path' , '' )
72
+ login_svc = requests .get ("http://127.0.0.1:55555/get_one/login" ).text
73
+ print (login_svc )
74
+ login_host = json .loads (login_svc )
75
+ login_ip = login_host ['endpoints' ][0 ]
76
+ login_port = login_host ['endpoints' ][1 ]
77
+ if request .method == "POST" :
78
+ data = await request .post ()
79
+ r = requests .post (f"http://{ login_ip } :{ login_port } /login/{ ex_path } " , data = data )
80
+ if ex_path == '' :
81
+ r = requests .get (f"http://{ login_ip } :{ login_port } /login" )
82
+ else :
83
+ r = requests .get (f"http://{ login_ip } :{ login_port } /login/{ ex_path } " )
84
+ return web .Response (text = r .text , content_type = 'text/html' )
85
+
86
+
87
+ async def fortune_cookie_v2 (request ) -> web .Response :
88
+ print (request )
89
+ ex_path = request .match_info .get ('ex_path' , '' )
90
+ fortune_cookie_svc = requests .get ("http://127.0.0.1:55555/get_one/fortune_cookie" ).text
91
+ print (fortune_cookie_svc )
92
+ fortune_cookie_host = json .loads (fortune_cookie_svc )
93
+ fortune_cookie_ip = fortune_cookie_host ['endpoints' ][0 ]
94
+ fortune_cookie_port = fortune_cookie_host ['endpoints' ][1 ]
95
+ if ex_path == '' :
96
+ r = requests .get (f"http://{ fortune_cookie_ip } :{ fortune_cookie_port } /fortune_cookie" )
97
+ else :
98
+ r = requests .get (f"http://{ fortune_cookie_ip } :{ fortune_cookie_port } /fortune_cookie/{ ex_path } " )
99
+ return web .Response (text = r .text , content_type = 'text/html' )
100
+
101
+
102
+ async def menu_v2 (request ):
103
+ print (request )
104
+ menu_svc = requests .get ("http://127.0.0.1:55555/get_one/menu" ).text
105
+ print (menu_svc )
106
+ menu_host = json .loads (menu_svc )
107
+ menu_ip = menu_host ['endpoints' ][0 ]
108
+ menu_port = menu_host ['endpoints' ][1 ]
109
+ r = requests .get (f"http://{ menu_ip } :{ menu_port } /menu" )
110
+ return web .Response (text = r .text , content_type = 'text/html' )
111
+
112
+
113
+ async def home (request ) -> web .Response :
114
+ """
115
+ This is the home page for the website
116
+ """
117
+ print (request )
118
+ page = Page (filename = "index.html" )
119
+ return page .render ()
120
+
121
+
122
+ async def logging_in (request ):
123
+ """
124
+ This is the page that gets POSTED to allow a user to login
125
+ """
126
+ print (request )
127
+ if request .method == 'POST' :
128
+ data = await request .post ()
129
+ name = data ['name' ]
130
+ print ("POSTED" )
131
+ print (name )
132
+ # TODO - Add authentication logic
133
+ get_login = await login (request , name = name )
134
+ return get_login
135
+
136
+
137
+ async def login (request , name = None ):
138
+ """
139
+ This is the login page for the website
140
+ """
141
+ print (request )
142
+ if name is not None :
143
+ page = Page (filename = "hello.html" , args = {"name" : name })
144
+ print ("Cookies Set?" )
145
+ return page .render ()
146
+ else :
147
+ print ("No name has been sent yet!" )
148
+ args = {"name" : name }
149
+ page = Page (filename = "login.html" , args = args )
150
+ return page .render ()
151
+
152
+
153
+ async def fortune_cookie (request ) -> web .Response :
154
+ """
155
+ This is the initial landing page for the fortune_cookie service.
156
+
157
+ Click on the link provided to retrieve your fortune!
158
+ """
159
+ print (request )
160
+ page = Page (filename = "fortune_cookie.html" )
161
+ return page .render ()
162
+
163
+
164
+ async def fortune (request ) -> web .Response :
165
+ """
166
+ This returns a randomly picked aphorism as a part of the fortune_cookie service.
167
+ """
168
+ print (request )
169
+
170
+
171
+ possible = [
172
+ "People are naturally attracted to you." ,
173
+ "You learn from your mistakes... You will learn a lot today." ,
174
+ "If you have something good in your life, don't let it go!" ,
175
+ "What ever you're goal is in life, embrace it visualize it, and for it will be yours." ,
176
+ "Your shoes will make you happy today." ,
177
+ "You cannot love life until you live the life you love." ,
178
+ "Be on the lookout for coming events; They cast their shadows beforehand." ,
179
+ "Land is always on the mind of a flying bird." ,
180
+ "The man or woman you desire feels the same about you." ,
181
+ "Meeting adversity well is the source of your strength." ,
182
+ "A dream you have will come true." ,
183
+ "Our deeds determine us, as much as we determine our deeds." ,
184
+ "Never give up. You're not a failure if you don't give up." ,
185
+ "You will become great if you believe in yourself." ,
186
+ "There is no greater pleasure than seeing your loved ones prosper." ,
187
+ "You will marry your lover." ,
188
+ "A very attractive person has a message for you." ,
189
+ "You already know the answer to the questions lingering inside your head." ,
190
+ "It is now, and in this world, that we must live." ,
191
+ "You must try, or hate yourself for not trying." ,
192
+ "You can make your own happiness." ,
193
+ "The greatest risk is not taking one." ,
194
+ "The love of your life is stepping into your planet this summer." ,
195
+ "Love can last a lifetime, if you want it to." ,
196
+ "Adversity is the parent of virtue." ,
197
+ "Serious trouble will bypass you." ,
198
+ "A short stranger will soon enter your life with blessings to share." ,
199
+ "Now is the time to try something new." ,
200
+ "Wealth awaits you very soon." ,
201
+ "If you feel you are right, stand firmly by your convictions." ,
202
+ "If winter comes, can spring be far behind?" ,
203
+ "Keep your eye out for someone special." ,
204
+ "You are very talented in many ways." ,
205
+ "A stranger, is a friend you have not spoken to yet." ,
206
+ "A new voyage will fill your life with untold memories." ,
207
+ "You will travel to many exotic places in your lifetime." ,
208
+ "Your ability for accomplishment will follow with success." ,
209
+ "Nothing astonishes men so much as common sense and plain dealing." ,
210
+ "Its amazing how much good you can do if you do not care who gets the credit." ,
211
+ "Everyone agrees. You are the best." ,
212
+ "Life consist not in holding good cards, but in playing those you hold well." ,
213
+ "Jealousy doesn't open doors, it closes them!" ,
214
+ "It's better to be alone sometimes." ,
215
+ "When fear hurts you, conquer it and defeat it!" ,
216
+ "Let the deeds speak." ,
217
+ "You will be called in to fulfill a position of high honor and responsibility." ,
218
+ "The man on the top of the mountain did not fall there." ,
219
+ "You will conquer obstacles to achieve success." ,
220
+ "Joys are often the shadows, cast by sorrows." ,
221
+ "Fortune favors the brave." ,
222
+ ]
223
+ fortune_choice = random .choice (possible )
224
+ args = {"fortune" : fortune_choice }
225
+ page = Page (filename = "fortune.html" , args = args )
226
+ return page .render ()
227
+
228
+
229
+ async def menu (request ) -> web .Response :
230
+ """
231
+ This will return the jinja2 templated menu.html file.
232
+ """
233
+ print (request )
234
+ food_items = [
235
+ {"item" : "General Tzo's Chicken" , "description" : "Yummy chicken on rice" , "price" : 12.99 },
236
+ {"item" : "Kung Pao Beef" , "description" : "Spicy Beef on rice" , "price" : 13.99 }
237
+ ] # TODO - Update to a sqlite3 database call
238
+ args = {"foods" : food_items }
239
+ page = Page (filename = "menu.html" , args = args )
240
+ return page .render ()
241
+
242
+
243
+ async def register (add_to_registry = True ):
244
+ print (f"""
245
+ Service Registry { REG_ADDR } :{ REG_PORT }
246
+
247
+ Adding to the Service Registry:
248
+
249
+ service name { SERVICE }
250
+ service IP { LOCAL_IP }
251
+ service port { PORT }
252
+ """ )
253
+ if add_to_registry :
254
+ r = requests .get (f"http://{ REG_ADDR } :{ REG_PORT } /add/{ SERVICE } /{ LOCAL_IP } /{ PORT } " )
255
+ print (r .status_code , r .text )
256
+
257
+
258
+ async def unregister (remove_from_registry = True ):
259
+ if remove_from_registry :
260
+ r = requests .get (f"http://{ REG_ADDR } :{ REG_PORT } /remove/{ SERVICE } /{ LOCAL_IP } /{ PORT } " )
261
+ print (r .status_code )
262
+
263
+
264
+ def main ():
265
+ """
266
+ This is the main process for the aiohttp server.
267
+
268
+ This works by instantiating the app as a web.Application(),
269
+ then applying the setup function we built in our routes
270
+ function to add routes to our app, then by starting the async
271
+ event loop with web.run_app().
272
+ """
273
+
274
+ print ("This aiohttp web server is starting up!" )
275
+ app = web .Application ()
276
+ routes (app )
277
+ app .on_startup .append (register )
278
+ app .on_shutdown .append (unregister )
279
+ web .run_app (app , host = HOST , port = PORT )
280
+
281
+
282
+ if __name__ == "__main__" :
283
+ main ()
0 commit comments