【问题标题】:Getting a 400 Bad Request Error Using Socket in Python 3在 Python 3 中使用 Socket 获取 400 错误请求错误
【发布时间】:2017-11-30 02:42:53
【问题描述】:

我刚刚开始使用 Python 3.6.1 中的 Python Web 数据。我正在学习套接字,但我的代码有问题,我无法弄清楚。我的代码中的网站运行良好,但是当我运行此代码时,我收到 400 Bad Request 错误。我不确定我的代码有什么问题。提前致谢。

import socket

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

mysock.connect(('data.pr4e.org', 80))

mysock.send(('GET http://data.pr4e.org/romeo.txt HTTP/1.0 \n\n').encode())

while True:
    data = mysock.recv(512)
    if ( len(data) < 1 ):
        break
    print (data)

mysock.close()

【问题讨论】:

  • 404 从技术上讲并不是一个糟糕的请求代码
  • 您正在请求一些不存在或路径错误的东西。检查文本文件是否存在于您请求的路径中
  • 事实上,我试过你的代码,它工作得很好,你能告诉我们回溯吗?
  • 哎呀我的 400 @mehulmpt
  • 400 Bad Request

    Bad Request

    您的浏览器发送了一个此服务器无法理解的请求。


    Apache/2.4.7 (Ubuntu) 服务器在 do1 .dr-chuck.com 端口 80
    @be_good_do_good 这是我收到的消息

标签: python python-3.x sockets networking web


【解决方案1】:

这段代码对我有用:

GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n
  1. 将\n\n 更改为\r\n\r\n
  2. 删除HTTP/1.0和\r\n\r\n之间的空格

【讨论】:

    【解决方案2】:
    'GET http://data.pr4e.org/romeo.txt HTTP/1.0\r\n\r\n'.encode()
    

    为我工作。

    【讨论】:

      【解决方案3】:
      GET http://data.pr4e.org/romeo.txt HTTP/1.0 \n\n
      

      欢迎来到 HTTP 的美妙世界,大多数用户认为这是一个简单的协议,因为它是人类可读的,但实际上它可能是一个非常复杂的协议。鉴于您的上述要求,存在几个问题:

      • 路径不应是完整的 URL,而只能是 /romeo.txt。只有在向代理发出请求时才会使用完整的 URL。
      • 行尾必须是\r\n 而不是\n。
      • HTTP/1.0 之后和行尾之前不应有空格。
      • 虽然只有 HTTP/1.1 需要 Host 标头,但许多服务器(包括您尝试访问的服务器)也需要 HTTP/1.0,因为它们在同一 IP 地址上有多个主机名,并且需要区分您使用的名称想要。

      考虑到这一点,您发送的数据应该改为

      GET /romeo.txt HTTP/1.0\r\nHost: data.pr4e.org\r\n\r\n
      

      并且我已经测试过它可以完美地与此修改配合使用。

      但是,鉴于 HTTP 并不像看起来那么简单,我真的建议使用请求之类的库来访问目标。如果这对您来说开销太大,请研究HTTP standard 以正确实现它,而不是仅仅从一些示例中猜测 HTTP 是如何工作的 - 并且猜测它是错误的。

      另请注意,服务器对像您这样的损坏实现的宽容程度有所不同。因此,曾经在一台服务器上工作的东西可能无法在下一台服务器上工作,甚至在某些软件升级后也不能在同一台服务器上工作。使用健壮且经过良好测试和维护的库,而不是自己做所有事情,这样也可以为您以后省去很多麻烦。

      【讨论】:

        【解决方案4】:

        您不将协议发送到 Web 服务器,您只在 Host 标头中单独发送主机名,然后才在 HTTP 1.1 中发送。

        对于 HTTP 1.0,应该是:

        mysock.send('GET /romeo.txt HTTP/1.0\r\n\r\n')
        

        或者,您可以尝试发送 HTTP 1.1 请求:

        mysock.send('GET /romeo.txt HTTP/1.1\r\n')
        mysock.send('Host: data.pr4e.org\r\n\r\n')
        

        【讨论】:

        • 谢谢。我试过了,但我似乎仍然在 HTML 代码中收到 400 Bad Request 错误
        • 尝试将回车更改为\r\n 对,就像我在上面所做的那样。
        • 使用HTTP/1.1 和上面的代码来读取正文是一个坏主意,在使用特定服务器实际测试它时可以看出这一点。由于 HTTP/1.1 隐式启用 HTTP keep-alive,因此服务器不会在按代码预期发送主体后立即关闭连接,而是会等待同一 TCP 连接中的下一个请求 - 即程序挂起。即使添加显式Connection: close 来禁用此功能,服务器仍可能使用与HTTP/1.1 分块的传输编码,这也不是预期的。因此,最好使用 HTTP/1.0 以保持简单。
        • "...一个 Host 标头,只有在 HTTP 1.1 中。" - 尽管标准没有明确要求,但 HTTP/1.0 实际上允许 Host 标头使用 HTTP/1.1。尽管如此,许多像所讨论的服务器一样需要它,并且也会在 HTTP/1.0 请求中接受它。
        猜你喜欢
        • 2021-03-05
        • 2017-11-27
        • 2013-06-30
        • 1970-01-01
        • 2013-04-07
        • 1970-01-01
        • 1970-01-01
        • 2018-07-08
        相关资源
        最近更新 更多