2
2
import socket
3
3
import ssl
4
4
import zlib
5
+
5
6
try :
6
7
import brotli
7
8
except ImportError :
10
11
11
12
def request (url ):
12
13
# 1. Parse scheme
13
- scheme , url = url .split (' ://' , 1 )
14
- assert scheme in [' http' , ' https' ], f' Unknown scheme { scheme } '
15
- port = 80 if scheme == ' http' else 443
14
+ scheme , url = url .split (" ://" , 1 )
15
+ assert scheme in [" http" , " https" ], f" Unknown scheme { scheme } "
16
+ port = 80 if scheme == " http" else 443
16
17
17
18
# 2. Parse host
18
- host , path = url .split ('/' , 1 )
19
- path = '/' + path
19
+ host , path = url .split ("/" , 1 )
20
+ path = "/" + path
20
21
21
22
# 3. Parse port
22
- if ':' in host :
23
- host , port = host .split (':' , 1 )
23
+ if ":" in host :
24
+ host , port = host .split (":" , 1 )
24
25
port = int (port )
25
26
26
27
# 4. Connect
27
28
with socket .socket (socket .AF_INET , socket .SOCK_STREAM , socket .IPPROTO_TCP ) as s :
28
- if scheme == ' https' :
29
+ if scheme == " https" :
29
30
ctx = ssl .create_default_context ()
30
31
s = ctx .wrap_socket (s , server_hostname = host )
31
32
32
33
s .connect ((host , port ))
33
34
34
35
# 5. Send request
35
- s .send (f' GET { path } HTTP/1.0\r \n ' .encode ())
36
- s .send (f' Host: { host } \r \n ' .encode ())
37
- s .send (' Accept-Encoding: br,gzip,deflate\r \n ' .encode ())
38
- s .send (' \r \n ' .encode ())
36
+ s .send (f" GET { path } HTTP/1.0\r \n " .encode ())
37
+ s .send (f" Host: { host } \r \n " .encode ())
38
+ s .send (" Accept-Encoding: br,gzip,deflate\r \n " .encode ())
39
+ s .send (" \r \n " .encode ())
39
40
40
41
# 6. Receive response
41
- response = s .makefile ('rb' , newline = ' \r \n ' )
42
+ response = s .makefile ("rb" , newline = " \r \n " )
42
43
43
44
# 7. Read status line
44
45
line = response .readline ().decode ()
45
46
# 8. Parse status line
46
- version , status , explanation = line .split (' ' , 2 )
47
+ version , status , explanation = line .split (" " , 2 )
47
48
48
49
# 9. Check status
49
- assert status == "200" , f' { status } : { explanation } '
50
+ assert status == "200" , f" { status } : { explanation } "
50
51
51
52
# 10. Parse headers
52
53
headers = {}
53
54
while True :
54
55
line = response .readline ().decode ()
55
- if line == ' \r \n ' :
56
+ if line == " \r \n " :
56
57
break
57
- header , value = line .split (':' , 1 )
58
+ header , value = line .split (":" , 1 )
58
59
headers [header .lower ()] = value .strip ()
59
60
60
61
body = response .read ()
61
- if ' content-encoding' in headers :
62
- encoding = headers [' content-encoding' ]
62
+ if " content-encoding" in headers :
63
+ encoding = headers [" content-encoding" ]
63
64
body = decompress (body , encoding )
64
65
body = body .decode ()
65
66
@@ -68,28 +69,28 @@ def request(url):
68
69
69
70
70
71
def decompress (data , encoding ):
71
- if encoding == ' gzip' :
72
+ if encoding == " gzip" :
72
73
return gzip .decompress (data )
73
- elif encoding == ' deflate' :
74
+ elif encoding == " deflate" :
74
75
return zlib .decompress (data , wbits = - zlib .MAX_WBITS )
75
- elif encoding == 'br' :
76
+ elif encoding == "br" :
76
77
if brotli is None :
77
- raise RuntimeError (' please install brotli package: pip install brotli' )
78
+ raise RuntimeError (" please install brotli package: pip install brotli" )
78
79
return brotli .decompress (data )
79
- elif encoding == ' identity' :
80
+ elif encoding == " identity" :
80
81
return data
81
82
else :
82
- raise RuntimeError (f' unexpected content-encoding: { encoding } ' )
83
+ raise RuntimeError (f" unexpected content-encoding: { encoding } " )
83
84
84
85
85
86
def lex (body ):
86
- text = ''
87
+ text = ""
87
88
in_angle = False
88
89
for c in body :
89
- if c == '<' :
90
+ if c == "<" :
90
91
in_angle = True
91
- elif c == '>' :
92
+ elif c == ">" :
92
93
in_angle = False
93
94
elif not in_angle :
94
- text += c
95
+ text += c
95
96
return text
0 commit comments