使用Socket发送原始POST请求

7

我正在尝试向一个chromedriver服务器发送原始的POST请求。

以下是我尝试启动一个新会话的方法:

import socket

s = socket.socket(
    socket.AF_INET, socket.SOCK_STREAM)

s.connect(("127.0.0.1", 9515))

s.send(b'POST /session HTTP/1.1\r\nContent-Type:application/json\r\n{"capabilities": {}, "desiredCapabilities": {}}\r\n\r\n')
response = s.recv(4096)
print(response)

输出:

b'HTTP/1.1 200 OK\r\nContent-Length:270\r\nContent-Type:application/json; charset=utf-8\r\nConnection:close\r\n\r\n{"sessionId":"b26166c2aac022566917db20260500bb","status":33,"value":{"message":"session not created exception: Missing or invalid capabilities\\n  (Driver info: chromedriver=2.31.488763 (092de99f48a300323ecf8c2a4e2e7cab51de5ba8),platform=Linux 4.4.0-91-generic x86_64)"}}'

错误概要:发送的 JSON 对象没有被正确解析。当我使用相同的 JSON 对象通过 requests 库发送时,一切正常。
import requests

params = {
        'capabilities': {},
        'desiredCapabilities': {}
    }


headers = {'Content-type': 'application/json'}

URL = "http://127.0.0.1:9515"

r = requests.post(URL + "/session", json=params)

print("Status: " + str(r.status_code))
print("Body: " + str(r.content))

输出:

Status: 200
Body: b'{"sessionId":"e03189a25d099125a541f3044cb0ee42","status":0,"value":{"acceptSslCerts":true,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"browserName":"chrome","chrome":{"chromedriverVersion":"2.31.488763 (092de99f48a300323ecf8c2a4e2e7cab51de5ba8)","userDataDir":"/tmp/.org.chromium.Chromium.LBeQkw"},"cssSelectorsEnabled":true,"databaseEnabled":false,"handlesAlerts":true,"hasTouchScreen":false,"javascriptEnabled":true,"locationContextEnabled":true,"mobileEmulationEnabled":false,"nativeEvents":true,"networkConnectionEnabled":false,"pageLoadStrategy":"normal","platform":"Linux","rotatable":false,"setWindowRect":true,"takesHeapSnapshot":true,"takesScreenshot":true,"unexpectedAlertBehaviour":"","version":"60.0.3112.90","webStorageEnabled":true}}'

输出摘要: json对象已被chromedriver成功解析,并创建了一个新的会话

各位有没有想法,为什么使用socket发送原始POST请求时不能按预期工作?


你在POST请求中拼写了"Content"错误。 - President James K. Polk
嗨@JamesKPolk,我修好了,抱歉。不过它仍然表现得一样。 - CuriousGuy
你可以记录requests实际发送的内容,并将其与套接字重用:https://dev59.com/4mkv5IYBdhLWcg3wdQdT - u354356007
1个回答

12

关于您的HTTP请求,存在几个问题:

  • HTTP请求的正文应该由\r\n\r\n与首部分隔开。
  • 您需要指定Content-Length字段,否则远程主机无法知道何时接收到完整的请求体。
  • Host字段在HTTP 1.1中是必须的(因为您的第一个请求已经得到了200的响应,您的服务器可能并没有强制要求添加此字段)。

我已经通过以下方式让您的示例正常工作(使用了Apache Web服务器):

s.send(b'POST /session HTTP/1.1\r\nHost: 127.0.0.1:9515\r\nContent-Type: application/json\r\nContent-Length: 47\r\n\r\n{"capabilities": {}, "desiredCapabilities": {}}')
为了更加直观清晰,有效的 HTTP 请求如下:
POST /session HTTP/1.1
Host: 127.0.0.1:9515
Content-Type: application/json
Content-Length: 47

{"capabilities": {}, "desiredCapabilities": {}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接