【问题标题】:Create a HTTP object from a string in Python从 Python 中的字符串创建 HTTP 对象
【发布时间】:2016-12-30 16:19:00
【问题描述】:

我的设备正在向我的 RaspberryPi 发送以下 http 消息:

POST /sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData HTTP/1.1
Host: www.automation.siemens.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 349

xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd>

我无法更改设备上的任何内容。

在 RaspberryPi 上运行脚本以侦听和接收来自套接字的消息。 到目前为止,这有效,收到的消息是上面的消息。

现在,我想从这条消息中创建一个 HTTP 对象,然后轻松地提取标题、内容等。 类似于下面的例子:

r = requests.get('https://www.google.com')
r.status_code

但是,没有“获取”网址。我只想读取我已经拥有的字符串。

伪例子:

r = requests.read(hereComesTheString)
r.status_code

我希望问题变得可以理解。

很高兴得到一些提示。

感谢和最好的问候, 克里斯托夫

【问题讨论】:

  • 如果这都是本地/无服务器的,你为什么要关心标头或状态码是什么?你不会只关心字符串的内容吗?我正在试图弄清楚你真正的用例是什么。
  • 您的意思是,从您的 RPi 中,您想剖析 HTTP 请求并做出 HTTP 响应?您的套接字服务器是否已经实现了 HTTP?
  • @birryree:例如,我想更改路径并传递消息。我知道我可以通过一些解析和替换来做到这一点,但我认为可能有更优雅的方式..
  • 这听起来绝对像是您想要在您的 RPi 上设置服务器或代理,然后。我认为 Alistair McCormack 的回答可能正朝着您需要的正确方向发展。

标签: python sockets httprequest httpresponse


【解决方案1】:

您在示例中使用了 status_code 属性,但您收到的是请求而不是响应。但是,您仍然可以创建一个简单的对象来访问请求中的数据。

创建自己的自定义类可能是最简单的:

import mimetools
from StringIO import StringIO

request = """POST /sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData HTTP/1.1
Host: www.automation.siemens.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 349

xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd>"""

class Request:
    def __init__(self, request):
        stream = StringIO(request)
        request = stream.readline()

        words = request.split()
        [self.command, self.path, self.version] = words

        self.headers = mimetools.Message(stream, 0)
        self.content = stream.read()

    def __getitem__(self, key):
        return self.headers.get(key, '')

r = Request(request)
print(r.command)
print(r.path)
print(r.version)

for header in r.headers:
    print(header, r[header])

print(r.content)

这个输出:

POST
/sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData
HTTP/1.1
('host', 'www.automation.siemens.com')
('content-type', 'application/x-www-form-urlencoded')
('content-length', '349')
xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd>

【讨论】:

    【解决方案2】:

    如果您使用的是普通套接字服务器,那么您需要实现一个 HTTP 服务器,以便您可以根据协议拆分请求并响应。

    使用现有的 HTTP 服务器和应用服务器可能更容易。 Flask 非常适合:

    from flask import Flask
    from flask import request
    
    app = Flask(__name__)
    
    @app.route("/sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData", methods=['POST'])
    def dataCollector():
        data = request.form['xmlData']
        print(data)
        # parseData. Take a look at ElementTree
    
    if __name__ == "__main__":
        app.run(host=0.0.0.0, port=80)
    

    【讨论】:

    • 看起来很有趣,我明天会测试它,因为设备现在处于离线状态。
    【解决方案3】:

    谢谢奥尔登。在您的代码下方进行了一些更改,因此它可以与 Python3 一起使用。

    import email
    from io import StringIO
    
    request = """POST /sinvertwebmonitor/InverterService/InverterService.asmx/CollectInverterData HTTP/1.1
    Host: www.automation.siemens.com
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 349
    
    xmlData=<rd><m>xxxxx</m><s>yyyyyy</s><d t="1483019400" l="600"><p i="1">460380AE</p><p i="2">43655DE7</p><p i="3">4212C986</p><p i="4">424805BC</p><p i="5">4604E3D1</p><p i="6">441F616A</p><p i="7">4155E7F5</p><p i="8">E1</p><p i="9">112</p><p i="C">153</p><p i="D">4</p><p i="E">11ABAC</p><p i="F">22A48C</p><p i="10">0</p></d></rd>"""
    
    class Request:
        def __init__(self, request):
            stream = StringIO(request)
            request = stream.readline()
    
            words = request.split()
            [self.command, self.path, self.version] = words
    
            self.headers = email.message_from_string(request)
            self.content = stream.read()
    
        def __getitem__(self, key):
            return self.headers.get(key, '')
    
    r = Request(request)
    print(r.command)
    print(r.path)
    print(r.version)
    
    for header in r.headers:
        print(header, r[header])
    
    print(r.content)
    

    【讨论】:

      猜你喜欢
      • 2015-08-19
      • 2022-01-22
      • 1970-01-01
      • 2010-10-15
      • 2015-09-08
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多