41
41
42
42
# Version control:
43
43
__author__ = 'SweetPalma'
44
- __version__ = '0.25 '
44
+ __version__ = '0.30 '
45
45
46
46
47
47
# Custom internal exceptions:
@@ -61,8 +61,7 @@ def __init__(self, server):
61
61
self .server = server
62
62
63
63
# Handling requests:
64
- @asyncio .coroutine
65
- def handle_request (self , reader , writer ):
64
+ async def handle_request (self , reader , writer ):
66
65
67
66
# Preparing basic values:
68
67
peername = writer .get_extra_info ('peername' )
@@ -93,7 +92,7 @@ def handle_request(self, reader, writer):
93
92
try :
94
93
95
94
# Reading:
96
- line = yield from reader .readline ()
95
+ line = await reader .readline ()
97
96
98
97
# Setting request type and maximal request size at start:
99
98
if len (header ) == 0 :
@@ -122,15 +121,15 @@ def handle_request(self, reader, writer):
122
121
# Reading content:
123
122
content = b''
124
123
if 0 < length < request_max :
125
- content = yield from reader .readexactly (length )
124
+ content = await reader .readexactly (length )
126
125
127
126
# Close connection in case of big file:
128
127
elif length > request_max :
129
128
self .writer .close ()
130
129
raise killer ('REQUEST IS TOO BIG' )
131
130
132
131
# Parsing data:
133
- self .client = yield from self .build_client (header , content )
132
+ self .client = await self .build_client (header , content )
134
133
client = self .client
135
134
136
135
# In case of disconnection:
@@ -148,70 +147,66 @@ def handle_request(self, reader, writer):
148
147
route_post = self .check_route (client .path , self .server .route_post )
149
148
route_get = self .check_route (client .path , self .server .route_get )
150
149
if client .type == 'POST' and route_post :
151
- raise killer ((yield from self .respond_script (* route_post )))
150
+ raise killer ((await self .respond_script (* route_post )))
152
151
if client .type == 'GET' and route_get :
153
- raise killer ((yield from self .respond_script (* route_get )))
152
+ raise killer ((await self .respond_script (* route_get )))
154
153
155
154
# Checking static files:
156
155
for dir , real in self .server .route_static .items ():
157
156
if client .path .startswith (dir ):
158
157
filepath = client .path .replace (dir , real , 1 )
159
- raise killer ((yield from self .respond_file (filepath [1 :])))
158
+ raise killer ((await self .respond_file (filepath [1 :])))
160
159
161
160
# Routing 404 error:
162
- raise killer ((yield from self .respond_error (404 )))
161
+ raise killer ((await self .respond_error (404 )))
163
162
164
163
# Timeout/Cancelled:
165
164
except concurrent .futures ._base .CancelledError :
166
- yield from self .respond_error (500 )
165
+ await self .respond_error (500 )
167
166
log .info (client_info + ' TIMED OUT' )
168
167
169
168
# Terminator:
170
169
except killer as exception :
171
170
log .info (client_info + ' ' + exception .message )
172
171
173
172
# Sending file:
174
- @asyncio .coroutine
175
- def respond_file (self , path ):
173
+ async def respond_file (self , path ):
176
174
try :
177
175
with open (path , "rb" ) as file :
178
176
size = os .path .getsize (path )
179
- return (yield from self .respond (
177
+ return (await self .respond (
180
178
status = 200 ,
181
179
content = file .read (),
182
180
type = self .get_mime (path ),
183
181
length = size
184
182
))
185
183
# No file found:
186
184
except IOError :
187
- return (yield from self .respond_error (404 ))
185
+ return (await self .respond_error (404 ))
188
186
189
187
# Sending error message:
190
- @asyncio .coroutine
191
- def respond_error (self , number , custom = None ):
188
+ async def respond_error (self , number , custom = None ):
192
189
error = {
193
190
400 : 'Bad Request' ,
194
191
404 : 'Not Found' ,
195
192
500 : 'Internal Error' ,
196
193
}
197
194
error_text = number in error and error [number ] or 'Unknown Error'
198
195
error_cont = str (number ) + ' ' + error_text
199
- return (yield from self .respond (number , error_cont ))
196
+ return (await self .respond (number , error_cont ))
200
197
201
198
# Executing client script and sending it response:
202
- @asyncio .coroutine
203
- def respond_script (self , script , keys = {}):
204
- script_result = (yield from script (self .client , ** keys )) or b''
205
- return (yield from self .respond (
199
+ async def respond_script (self , script , keys = {}):
200
+ script_result = (await script (self .client , ** keys )) or b''
201
+ return (await self .respond (
206
202
status = self .client .status ,
207
203
content = script_result ,
208
204
header = self .client .header ,
209
205
type = self .client .mime
210
206
))
211
207
212
208
# Pure data response:
213
- @asyncio .coroutine
214
- def respond (self , status , content = b'' , type = 'text/html' , length = None , header = {}):
209
+ async def respond (self , status , content = b'' , type = 'text/html' , length = None , header = {}):
215
210
216
211
# Forming header:
217
212
encoding = self .server .encoding
@@ -302,8 +297,7 @@ def get_mime(self, path):
302
297
return guess_type (path )[0 ] or 'application'
303
298
304
299
# Parsing GET and COOKIES:
305
- @asyncio .coroutine
306
- def parse (self , path ):
300
+ async def parse (self , path ):
307
301
# Preparing %key%=%value% regex:
308
302
try :
309
303
get_word = '[^=;&?]'
@@ -323,8 +317,7 @@ def parse(self, path):
323
317
return dict (matched )
324
318
325
319
# Parsing POST multipart:
326
- @asyncio .coroutine
327
- def parse_post (self , content , types , boundary ):
320
+ async def parse_post (self , content , types , boundary ):
328
321
329
322
# Establishing default encoding:
330
323
encoding = self .server .encoding
@@ -376,11 +369,10 @@ def parse_post(self, content, types, boundary):
376
369
else :
377
370
if isinstance (content , bytes ):
378
371
content = content .decode (encoding )
379
- return self .parse (content )
372
+ return await self .parse (content )
380
373
381
374
# Parsing client data:
382
- @asyncio .coroutine
383
- def build_client (self , header_raw , content_raw = b'' ):
375
+ async def build_client (self , header_raw , content_raw = b'' ):
384
376
385
377
# Safe dict values:
386
378
def safe_dict (dictionary , value , default ):
@@ -441,9 +433,9 @@ def safe_dict(dictionary, value, default):
441
433
boundary = b''
442
434
443
435
# POST/GET/COOKIES:
444
- client .get = yield from self .parse (GET )
445
- client .post = yield from self .parse_post (content_raw , client .form_type , boundary )
446
- client .cookie = yield from self .parse (safe_dict (header , 'Cookie' , '' ))
436
+ client .get = await self .parse (GET )
437
+ client .post = await self .parse_post (content_raw , client .form_type , boundary )
438
+ client .cookie = await self .parse (safe_dict (header , 'Cookie' , '' ))
447
439
448
440
# Client ID cookie, can be overrided later:
449
441
client .header ['Set-Cookie' ] = 'id=' + client .id
@@ -463,7 +455,7 @@ def safe_dict(dictionary, value, default):
463
455
# In case of fail:
464
456
except BaseException as exc :
465
457
log .warning ('Error parsing user request.' )
466
- yield from self .respond_error (400 )
458
+ await self .respond_error (400 )
467
459
raise exc
468
460
469
461
# Script client:
@@ -596,8 +588,8 @@ def get(self, path):
596
588
""" Binds all GET requests from path to certain function. """
597
589
def decorator (func ):
598
590
@wraps (func )
599
- def wrapper (* args , ** kwds ):
600
- return asyncio . coroutine ( func ) (* args , ** kwds )
591
+ async def wrapper (* args , ** kwds ):
592
+ return func (* args , ** kwds )
601
593
self .route_get [path ] = wrapper
602
594
return wrapper
603
595
return decorator
@@ -608,8 +600,8 @@ def post(self, path):
608
600
""" Binds all POST requests from path to certain function. """
609
601
def decorator (func ):
610
602
@wraps (func )
611
- def wrapper (* args , ** kwds ):
612
- return asyncio . coroutine ( func ) (* args , ** kwds )
603
+ async def wrapper (* args , ** kwds ):
604
+ return func (* args , ** kwds )
613
605
self .route_post [path ] = wrapper
614
606
return wrapper
615
607
return decorator
@@ -620,8 +612,8 @@ def route(self, path):
620
612
""" Binds all POST/GET requests from path to certain function. """
621
613
def decorator (func ):
622
614
@wraps (func )
623
- def wrapper (* args , ** kwds ):
624
- return asyncio . coroutine ( func ) (* args , ** kwds )
615
+ async def wrapper (* args , ** kwds ):
616
+ return func (* args , ** kwds )
625
617
self .route_post [path ] = wrapper
626
618
self .route_get [path ] = wrapper
627
619
return wrapper
@@ -676,11 +668,10 @@ def stop(self):
676
668
self ._loop .stop ()
677
669
678
670
# HTTP request handler:
679
- @asyncio .coroutine
680
- def handler (self , reader , writer ):
671
+ async def handler (self , reader , writer ):
681
672
try :
682
673
handler = PerverHandler (self )
683
- yield from asyncio .wait_for (
674
+ await asyncio .wait_for (
684
675
handler .handle_request (reader , writer ),
685
676
timeout = self .timeout
686
677
)
0 commit comments