带套接字的Python GET请求-400错误的请求

时间:2019-12-07 23:11:01

标签: python sockets http https http-status-code-400

我编写了这段代码,以仅使用python套接字手动发出GET请求。早在2016年,当我编写它时,它的运行情况就很好了,但是现在我再次需要它,并且我不断收到错误代码400错误的请求。我尝试切换python版本,但仍然相同。我一直在研究Stackoverflow的问题,或多或少地询问与我相同的事情,但是我无法使其正常工作。如果有人可以帮助我,我将不胜感激。这是我的代码,我删除了所有IO,仅发布了网络代码。

URL_PATTERN = re.compile("^(.*://)?([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$")
HEADER_END = re.compile("\r\n\r\n")

URL_DATA = re.match(URL_PATTERN, INPUT_URL)
PROTOCOL = URL_DATA.groups()[0][:-3]
HOSTNAME = URL_DATA.groups()[1]
PATHNAME = URL_DATA.groups()[3] if URL_DATA.groups()[3] != "" else "/"
PORT = 80 if PROTOCOL == "http" else 443
BUFFER_SIZE = 4096

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOSTNAME, PORT))

s.send("GET " + PATHNAME + " HTTP/1.1\r\nHost: " + HOSTNAME + "\r\nConnection: close\r\n\r\n")

resp = s.recv(BUFFER_SIZE)
HEADER_INDEX = re.search(HEADER_END, resp).start()
HTTP_RESPONSE_HEADER = resp[:HEADER_INDEX]

s.close()

当我在URL https://doc.rust-lang.org/book/2018-edition/foreword.html上运行程序时

我程序中的变量具有值:

端口:443

协议:https

主机名:doc.rust-lang.org

PATHNAME :/ book / 2018-edition / foreword.html

然后我得到了400错误的请求代码。我不明白自己在做错什么,将不胜感激。

1 个答案:

答案 0 :(得分:2)

我认为这全都与SSL有关。作为参考,您可以检查此问题Python socket server handle HTTPS request

我建议您使用:

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)

并创建一个安全套接字:

s_sock = context.wrap_socket(s, server_hostname=HOSTNAME)
s_sock.connect((HOSTNAME, PORT))

另外,您可能需要对消息进行编码。

最后,您的代码如下所示:

import re
import socket
import ssl

URL_PATTERN = re.compile("^(.*://)?([A-Za-z0-9\-\.]+)(:[0-9]+)?(.*)$")
HEADER_END = re.compile("\r\n\r\n")

INPUT_URL = "https://doc.rust-lang.org/book/2018-edition/foreword.html"

context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)

URL_DATA = re.match(URL_PATTERN, INPUT_URL)
PROTOCOL = URL_DATA.groups()[0][:-3]
HOSTNAME = URL_DATA.groups()[1]
PATHNAME = URL_DATA.groups()[3] if URL_DATA.groups()[3] != "" else "/"
PORT = 80 if PROTOCOL == "http" else 443
BUFFER_SIZE = 4096

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_sock = context.wrap_socket(s, server_hostname=HOSTNAME)
s_sock.connect((HOSTNAME, PORT))

message = "GET " + PATHNAME + " HTTP/1.1\r\nHost: " + HOSTNAME + "\r\nConnection: close\r\n\r\n"
s_sock.send(message.encode('utf-8'))

resp = bytearray()
while True:
    part = s_sock.recv(BUFFER_SIZE)
    if not part:
        break
    resp += part

s_sock.close()

resp_string = str(resp, 'utf-8')
HEADER_INDEX = re.search(HEADER_END, resp_string).start()
HTTP_RESPONSE_HEADER = resp_string[:HEADER_INDEX]