【问题标题】:How to test for the line that separates the body and the header of the POST request?如何测试分隔 POST 请求的正文和标头的行?
【发布时间】:2019-04-18 11:31:56
【问题描述】:

我正在尝试从 POST 请求的正文中获取参数 first 和 last。基本上我有一个套接字服务器。此套接字服务器在连接时获取客户端并生成文件client= connection.makefile("wrb")

...
b'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0\r\n'
b'Accept-Language: en-US,en;q=0.5\r\n'
b'Referer: http://localhost:8080/app-index\r\n'
b'Content-Length: 22\r\n'
b'Upgrade-Insecure-Requests: 1\r\n'
b'first=dasda&last=dasda'

现在我使用 readline() 浏览文件。

while 1:
   line = client.readline()
   print(line)
   if("Content-Length" in line.decode("utf-8")):
      num=line.decode("utf-8")
   "if line doesnt have \n break":
      break
temp = client.read(int(num[16:])) 

num 变量是正文的内容长度。现在我试图找到一种方法来打破当它到达正文并使用read(num) 来读取正文的内容,然后进一步处理它们。

我不知道还能去哪里——如果有更有效的方式来读取原始 POST 数据,我很乐意听到它,但我不能使用任何模块或导入(我很乐意使用requests 模块,但这不是一个选项)。

上面代码的问题是,当涉及到正文时,它永远不会停止,因为它正在寻找最后一个\n。我无法将其附加到客户端,因为client.write() 将标头返回给客户端。

我尝试了很多东西,我尝试了readline()read()readlines(),但事情是一样的——我需要在body() 的开头停止阅读,我需要在没有任何其他模块的情况下这样做

【问题讨论】:

  • 解析 HTTP/1.1 消息很困难,因为标头块的文本性质以及分隔消息的各种方式。尝试编写自定义解析器可能是个坏主意。在任何情况下,请参阅 RFC 7230 (greenbytes.de/tech/webdav/rfc7230.html#rfc.section.3.3.3) 的第 3.3.3 节
  • 您在循环的每次迭代中都调用了两次readline(),这意味着您将丢弃每隔一行!
  • @SamMason 是的,我非常快地起草了代码,感谢您指出。我现在已经编辑过了。谢谢指出

标签: python http post http-post


【解决方案1】:

按照与您如何收集 Content-Length 类似的实现,是否无法执行以下操作?

#Example:
#b'first=john&last=doe'

decoded_line = client.readline().decode("utf-8")
while decoded_line:
   if("first=" in decoded_line):
        first_split = decoded_line.split('first=')
        second_split = first_split[1].split('&last=')
        first_value = second_split[0]

    if("last=" in decoded_line):
        first_split = decoded_line.split('&last=')
        last_value = first_split[1][:-1]

如果线路存在:

first_value:应该保存第一个值(来自示例 'john')

last_value:应该保存最后一个值(来自示例 'doe')

更新

由于误解了第一个问题,我在下面添加了另一个可能的解决方案。如果您需要来自其他标头的数据,则可以扩展实现以处理该问题 - 但是,如果(例如)缺少“Content-Length”,这将中断。

finished_parsing = False
content_length_line = ''

while not finished_parsing:
   line = client.readline().decode("utf-8")
   print(line)
   if("Content-Length" in line.decode("utf-8")):
       content_length_line = line
       finished_parsing = True

if content_length_line != '':
    content_length = content_length_line[16:]

【讨论】:

  • 好问题,不,它不是你所说的 client.readline() 正文没有 \n 因此你不能使用 readline,因为该行永远不会停止 ^^。您需要使用内容长度来获取字节数,然后使用 read(num) 函数读取字节数。然而,阅读身体不是问题。问题是在最后一个 \n 字符的正文之前停止 readline() 循环,然后读取正文。
  • 啊抱歉-我误解了这个问题。我是否正确地认为(鉴于上面的示例)您希望在没有 '\n' 并因此在 'Upgrade-Insecure-Requests' 行之后打破 while 循环?在这种情况下,我会更新我的答案:D
  • 没错,我希望在标题进入正文后立即将其中断,然后使用我在循环中获得的内容长度读取该正文。如果我坦率地说,通过这个任务,我会使用 requests 模块,它写得很好,使用起来也很简单,但限制可能会很糟糕
  • 您对其他标题感兴趣吗?还是只是内容长度?
  • 我只是在检查 Content-Length,这样我就可以获得读取正文的号码。在公开测试中,我看到标题是混合的并且没有完全填充——我想说什么。一项测试具有内容长度以及内容类型和正文。然而,另一个测试具有完整的标题,其中包含您在我的示例中看到的所有内容。这就是为什么我需要 while 并且正在逐行阅读并从中获取信息。
猜你喜欢
  • 2020-12-23
  • 2023-03-04
  • 2020-05-11
  • 2015-02-18
  • 1970-01-01
  • 2019-04-30
  • 2019-12-13
  • 2020-01-02
  • 2021-08-11
相关资源
最近更新 更多