Skip to content

Commit ac72bf2

Browse files
authored
Merge pull request #8 from troublegum/dev
Release 1.4
2 parents 522797c + 7aeebd9 commit ac72bf2

File tree

3 files changed

+156
-1
lines changed

3 files changed

+156
-1
lines changed

README.md

+36-1
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,30 @@ server.add_route("/404", not_found)
201201
server.start()
202202
```
203203

204+
### Parse HTTP request. Get query params from request.
205+
Type in browser http://IP_ADDRESS_ESP/?param_one=one&param_two=two
206+
207+
```
208+
''' Example of HTTP request: GET /?param_one=one&param_two=two HTTP/1.1\r\nHost: localhost\r\n\r\n '''
209+
from micropyserver import MicroPyServer
210+
import utils
211+
212+
''' there should be a wi-fi connection code here '''
213+
214+
def show_params(request):
215+
''' request handler '''
216+
params = utils.get_request_query_params(request)
217+
print(params)
218+
''' will return {"param_one": "one", "param_two": "two"} '''
219+
220+
server = MicroPyServer()
221+
''' add route '''
222+
server.add_route("/", show_params)
223+
''' start server '''
224+
server.start()
225+
226+
```
227+
204228

205229
## MicroPyServer methods
206230

@@ -220,8 +244,19 @@ Set handler on 404 - server.on_not_found(handler)
220244

221245
Set handler on server error - server.on_error(handler)
222246

247+
223248
## Utils methods
224249

225250
Send response to client - utils.send_response(server, response, http_code=200, content_type="text/html", extend_headers=None)
226251

227-
Get HTTP request method - utils.get_request_method(request)
252+
Get HTTP request method (example of return value: POST) - utils.get_request_method(request)
253+
254+
Return http request query string (example of return value: param_one=one&param_two=two) - utils.get_request_query_string(request)
255+
256+
Return params from query string (example of return value: {"param_one": "one", "param_two": "two"}) - utils.parse_query_string(query_string)
257+
258+
Return http request query params (example of return value: {"param_one": "one", "param_two": "two"}) - utils.get_request_query_params(request)
259+
260+
Return params from POST request (example of return value: {"param_one": "one", "param_two": "two"}) - utils.get_request_post_params(request)
261+
262+
Unquote string - unquote(string)

test_utils.py

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import unittest
2+
import utils
3+
4+
5+
class TestUtils(unittest.TestCase):
6+
def test_get_request_method_should_return_get(self):
7+
request = "GET / HTTP/1.1\r\nHost: localhost"
8+
self.assertEqual(utils.get_request_method(request), "GET", "Should be GET")
9+
10+
def test_get_request_method_should_return_post(self):
11+
request = "POST /post HTTP/1.1\r\nHost: localhost\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 0\r\n\r\n"
12+
self.assertEqual(utils.get_request_method(request), "POST", "Should be POST")
13+
14+
def test_get_request_query_string_method_should_return_string(self):
15+
request = "GET /?param_one=one&param_two=two HTTP/1.1\r\nHost: localhost\r\n\r\n"
16+
self.assertEqual(utils.get_request_query_string(request), "param_one=one&param_two=two",
17+
"Should be 'param_one=one&param_two=two'")
18+
19+
def test_parse_query_string_method_should_return_two_params(self):
20+
query_string = "param_one=one&param_two=two"
21+
self.assertEqual(utils.parse_query_string(query_string), {"param_one": "one", "param_two": "two"},
22+
"Should be result with two params")
23+
24+
def test_get_request_query_params_method_should_return_two_params(self):
25+
request = "GET /?param_one=one&param_two=two HTTP/1.1\r\nHost: localhost\r\n\r\n"
26+
self.assertEqual(utils.get_request_query_params(request), {"param_one": "one", "param_two": "two"},
27+
"Should be 'param_one=one&param_two=two'")
28+
29+
def test_get_request_post_params_method_should_return_two_params(self):
30+
request = "POST /post HTTP/1.1\r\nHost: localhost\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: 27\r\n\r\nparam_one=one&param_two=two"
31+
self.assertEqual(utils.get_request_post_params(request), {"param_one": "one", "param_two": "two"},
32+
"Should be 'param_one=one&param_two=two'")
33+
34+
def test_unquote_method_should_return_empty_string(self):
35+
self.assertEqual(utils.unquote(""), "", "Should be empty string")
36+
37+
def test_unquote_method_should_return_string(self):
38+
self.assertEqual(utils.unquote("param"), "param", "Should be 'param'")
39+
40+
def test_unquote_method_should_return_unquoted_string(self):
41+
self.assertEqual(utils.unquote(
42+
"%D0%BF%D0%B0%D1%80%D0%B0%D0%BC%D0%B5%D1%82%D1%80%20%D0%B8%20%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D0%B5%20%25"),
43+
"параметр и значение %",
44+
"Should be 'параметр и значение %'")
45+
46+
47+
if __name__ == "__main__":
48+
unittest.main()

utils.py

+72
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,75 @@ def get_request_method(request):
106106
""" return http request method """
107107
lines = request.split("\r\n")
108108
return re.search("^([A-Z]+)", lines[0]).group(1)
109+
110+
111+
def get_request_query_string(request):
112+
""" return http request query string """
113+
lines = request.split("\r\n")
114+
match = re.search("\\?(.+)\\s", lines[0])
115+
if match is None:
116+
return ""
117+
else:
118+
return match.group(1)
119+
120+
121+
def parse_query_string(query_string):
122+
""" return params from query string """
123+
if len(query_string) == 0:
124+
return {}
125+
query_params_string = query_string.split("&")
126+
query_params = {}
127+
for param_string in query_params_string:
128+
param = param_string.split("=")
129+
key = param[0]
130+
if len(param) == 1:
131+
value = ""
132+
else:
133+
value = param[1]
134+
query_params[key] = value
135+
return query_params
136+
137+
138+
def get_request_query_params(request):
139+
""" return http request query params """
140+
query_string = get_request_query_string(request)
141+
return parse_query_string(query_string)
142+
143+
144+
def get_request_post_params(request):
145+
""" return params from POST request """
146+
request_method = get_request_method(request)
147+
if request_method != "POST":
148+
return None
149+
match = re.search("\r\n\r\n(.+)", request)
150+
if match is None:
151+
return {}
152+
query_string = match.group(1)
153+
return parse_query_string(query_string)
154+
155+
156+
def unquote(string):
157+
""" unquote string """
158+
if not string:
159+
return ""
160+
161+
if isinstance(string, str):
162+
string = string.encode("utf-8")
163+
164+
bits = string.split(b"%")
165+
if len(bits) == 1:
166+
return string.decode("utf-8")
167+
168+
res = bytearray(bits[0])
169+
append = res.append
170+
extend = res.extend
171+
172+
for item in bits[1:]:
173+
try:
174+
append(int(item[:2], 16))
175+
extend(item[2:])
176+
except KeyError:
177+
append(b"%")
178+
extend(item)
179+
180+
return bytes(res).decode("utf-8")

0 commit comments

Comments
 (0)