从 Python 中的字符串创建 HTTP object

Create a HTTP object from a string in Python

我有一个设备正在向我的 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 object,然后轻松提取 header、内容等。 类似于下面的例子:

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

但是,没有 "getting" url。我只想读我已有的字符串。

Pseudo-example:

r = requests.read(hereComesTheString)
r.status_code

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

很高兴得到一些提示。

谢谢并致以最诚挚的问候, 克里斯托夫

如果您使用的是普通套接字服务器,那么您需要实现一个 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)

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

创建自己的自定义内容可能最简单 class:

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>

谢谢奥尔登。在您的代码下方进行一些更改,使其适用于 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)