Skip to content

Commit 340cf14

Browse files
committed
chore: init files
1 parent 4fe3ad0 commit 340cf14

File tree

7 files changed

+436
-0
lines changed

7 files changed

+436
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,6 @@ dmypy.json
127127

128128
# Pyre type checker
129129
.pyre/
130+
131+
# additional files
132+
secrets.py

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"python.formatting.provider": "black"
3+
}

app/__init__.py

Whitespace-only changes.

app/httpclient.py

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import usocket, os
2+
class Response:
3+
4+
def __init__(self, socket, saveToFile=None):
5+
self._socket = socket
6+
self._saveToFile = saveToFile
7+
self._encoding = 'utf-8'
8+
if saveToFile is not None:
9+
CHUNK_SIZE = 512 # bytes
10+
with open(saveToFile, 'w') as outfile:
11+
data = self._socket.read(CHUNK_SIZE)
12+
while data:
13+
outfile.write(data)
14+
data = self._socket.read(CHUNK_SIZE)
15+
outfile.close()
16+
17+
self.close()
18+
19+
def close(self):
20+
if self._socket:
21+
self._socket.close()
22+
self._socket = None
23+
24+
@property
25+
def content(self):
26+
if self._saveToFile is not None:
27+
raise SystemError('You cannot get the content from the response as you decided to save it in {}'.format(self._saveToFile))
28+
29+
try:
30+
result = self._socket.read()
31+
return result
32+
finally:
33+
self.close()
34+
35+
@property
36+
def text(self):
37+
return str(self.content, self._encoding)
38+
39+
def json(self):
40+
try:
41+
import ujson
42+
result = ujson.load(self._socket)
43+
return result
44+
finally:
45+
self.close()
46+
47+
48+
class HttpClient:
49+
50+
def __init__(self, headers={}):
51+
self._headers = headers
52+
53+
def request(self, method, url, data=None, json=None, file=None, custom=None, saveToFile=None, headers={}, stream=None):
54+
def _write_headers(sock, _headers):
55+
for k in _headers:
56+
sock.write(b'{}: {}\r\n'.format(k, _headers[k]))
57+
58+
try:
59+
proto, dummy, host, path = url.split('/', 3)
60+
except ValueError:
61+
proto, dummy, host = url.split('/', 2)
62+
path = ''
63+
if proto == 'http:':
64+
port = 80
65+
elif proto == 'https:':
66+
import ussl
67+
port = 443
68+
else:
69+
raise ValueError('Unsupported protocol: ' + proto)
70+
71+
if ':' in host:
72+
host, port = host.split(':', 1)
73+
port = int(port)
74+
75+
ai = usocket.getaddrinfo(host, port, 0, usocket.SOCK_STREAM)
76+
if len(ai) < 1:
77+
raise ValueError('You are not connected to the internet...')
78+
ai = ai[0]
79+
80+
s = usocket.socket(ai[0], ai[1], ai[2])
81+
try:
82+
s.connect(ai[-1])
83+
if proto == 'https:':
84+
s = ussl.wrap_socket(s, server_hostname=host)
85+
s.write(b'%s /%s HTTP/1.0\r\n' % (method, path))
86+
if not 'Host' in headers:
87+
s.write(b'Host: %s\r\n' % host)
88+
# Iterate over keys to avoid tuple alloc
89+
_write_headers(s, self._headers)
90+
_write_headers(s, headers)
91+
92+
# add user agent
93+
s.write(b'User-Agent: MicroPython Client\r\n')
94+
if json is not None:
95+
assert data is None
96+
import ujson
97+
data = ujson.dumps(json)
98+
s.write(b'Content-Type: application/json\r\n')
99+
100+
if data:
101+
s.write(b'Content-Length: %d\r\n' % len(data))
102+
s.write(b'\r\n')
103+
s.write(data)
104+
elif file:
105+
s.write(b'Content-Length: %d\r\n' % os.stat(file)[6])
106+
s.write(b'\r\n')
107+
with open(file, 'r') as file_object:
108+
for line in file_object:
109+
s.write(line + '\n')
110+
elif custom:
111+
custom(s)
112+
else:
113+
s.write(b'\r\n')
114+
115+
l = s.readline()
116+
# print(l)
117+
l = l.split(None, 2)
118+
status = int(l[1])
119+
reason = ''
120+
if len(l) > 2:
121+
reason = l[2].rstrip()
122+
while True:
123+
l = s.readline()
124+
if not l or l == b'\r\n':
125+
break
126+
# print(l)
127+
if l.startswith(b'Transfer-Encoding:'):
128+
if b'chunked' in l:
129+
raise ValueError('Unsupported ' + l)
130+
elif l.startswith(b'Location:') and not 200 <= status <= 299:
131+
raise NotImplementedError('Redirects not yet supported')
132+
except OSError:
133+
s.close()
134+
raise
135+
136+
resp = Response(s, saveToFile)
137+
resp.status_code = status
138+
resp.reason = reason
139+
return resp
140+
141+
def head(self, url, **kw):
142+
return self.request('HEAD', url, **kw)
143+
144+
def get(self, url, **kw):
145+
return self.request('GET', url, **kw)
146+
147+
def post(self, url, **kw):
148+
return self.request('POST', url, **kw)
149+
150+
def put(self, url, **kw):
151+
return self.request('PUT', url, **kw)
152+
153+
def patch(self, url, **kw):
154+
return self.request('PATCH', url, **kw)
155+
156+
def delete(self, url, **kw):
157+
return self.request('DELETE', url, **kw)

0 commit comments

Comments
 (0)