Fir让我清楚我不想使用更高级别的API,我只想使用套接字编程
我编写了以下程序,使用POST请求连接到服务器。
import socket
import binascii
host = "localhost"
port = 9000
message = "POST /auth HTTP/1.1\r\n"
parameters = "userName=Ganesh&password=pass\r\n"
contentLength = "Content-Length: " + str(len(parameters))
contentType = "Content-Type: application/x-www-form-urlencoded\r\n"
finalMessage = message + contentLength + contentType + "\r\n"
finalMessage = finalMessage + parameters
finalMessage = binascii.a2b_qp(finalMessage)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
s.sendall(finalMessage)
print(s.recv(1024))
我在网上查看了如何创建POST请求。
不知何故Paramters没有传递给服务器。我是否必须在请求之间添加或删除“\ r \ n”?
提前致谢, 问候, 内甚
答案 0 :(得分:8)
此行finalMessage = binascii.a2b_qp(finalMessage)
肯定是错误的,因此您应该完全删除该行,另一个问题是Content-Length
之后没有新行丢失。在这种情况下,发送到套接字的请求是(我在这里显示CR
和LF
个字符为\r\n
,但为了清晰起见也分割了一行:
POST /auth HTTP/1.1\r\n
Content-Length: 31Content-Type: application/x-www-form-urlencoded\r\n
\r\n
userName=Ganesh&password=pass\r\n
显然,这对网络服务器没有多大意义。
但即使在添加换行符并删除a2b_qp
之后,仍有问题是您不 talking HTTP/1.1
;请求必须具有HTTP {1.1(RFC 2616 14.23)的Host
标头:
客户端必须在所有HTTP / 1.1请求中包含Host header 字段 消息。如果请求的URI不包含Internet主机名 对于所请求的服务,那么Host头字段必须是 给出一个空值。 HTTP / 1.1代理必须确保任何 请求消息它转发确实包含一个适当的主机头 标识代理请求的服务的字段。 所有 基于Internet的HTTP / 1.1服务器必须以400(错误请求)响应 任何缺少Host头的HTTP / 1.1请求消息的状态代码 字段。强>
此外,您不支持分块请求和持久连接,Keepalive或任何内容,因此您必须执行Connection: close
(RFC 2616 14.10):
不支持持久连接的HTTP / 1.1应用程序必须 在每条消息中包含“关闭”连接选项。
因此,任何仍然会对没有HTTP/1.1
标头的邮件做出正常响应的Host:
服务器也会损坏。
这是您应该使用该请求发送到套接字的数据:
POST /auth HTTP/1.1\r\n
Content-Type: application/x-www-form-urlencoded\r\n
Content-Length: 29\r\n
Host: localhost:9000\r\n
Connection: close\r\n
\r\n
userName=Ganesh&password=pass
请注意,您不在身体中添加\r\n
(因此身体29的长度)。此外,您应该阅读响应,以找出您所获得的错误。
在Python 3上,工作代码会说:
host = "localhost"
port = 9000
headers = """\
POST /auth HTTP/1.1\r
Content-Type: {content_type}\r
Content-Length: {content_length}\r
Host: {host}\r
Connection: close\r
\r\n"""
body = 'userName=Ganesh&password=pass'
body_bytes = body.encode('ascii')
header_bytes = headers.format(
content_type="application/x-www-form-urlencoded",
content_length=len(body_bytes),
host=str(host) + ":" + str(port)
).encode('iso-8859-1')
payload = header_bytes + body_bytes
# ...
socket.sendall(payload)