简体   繁体   English

如何使用python从传入的HTTP POST中提取数据

[英]How to extract data from incoming HTTP POST using python

I have a Ubuntu LAMP webserver and data is being sent to the webserver continuously through HTTP POST method.我有一个 Ubuntu LAMP 网络服务器,数据通过 HTTP POST 方法不断发送到网络服务器。 I need to extract the data from HTTP POST and insert them in a Database.我需要从 HTTP POST 中提取数据并将它们插入到数据库中。 I don't know how to do that.我不知道该怎么做。 There is a lot of example available on how to handle outgoing HTTP POST request but the incoming HTTP POST request.有很多关于如何处理传出的 HTTP POST 请求但传入的 HTTP POST 请求的示例。 I want to write a python3 script which will extract the data from incoming HTTP POST request and save them as varible which I will use to insert the data into the database and also return a response to the client.Can anybody help me in this regard?我想编写一个 python3 脚本,它将从传入的 HTTP POST 请求中提取数据并将它们保存为变量,我将用它来将数据插入数据库并向客户端返回响应。有人可以在这方面帮助我吗?

UPDATE UPDATE

According to the code you posted below, here is a working answer. 根据您在下面发布的代码,这是一个有效的答案。

#!/usr/bin/python3
import socketserver
from http.server import BaseHTTPRequestHandler
import time
import threading


def do_something(site_id, first, last, pass1):
    print(site_id)
    print(first)
    print(last)
    print(pass1)
    #just to illustrate the point and print the variables


class MyHandler(BaseHTTPRequestHandler):
    def do_POST(self):    # !important to use 'do_POST' with Capital POST
        global site_id, first, last, pass1  #those are still undefined at the module level ;) remember this for later
        if self.path == '/do_something':

            request_headers = self.headers

            site_id = request_headers["m_site_name"]
            first = request_headers["m_first_name"]
            last = request_headers["m_last_name"]
            pass1 = request_headers["m_device_name"]

            do_something(site_id, first, last, pass1)
        self.send_response(200)
        self.end_headers()             #as of P3.3 this is required

try:
    httpd = socketserver.TCPServer(("localhost", 9001), MyHandler)
    httpd.serve_forever()
finally:
    httpd = socketserver.TCPServer(("localhost", 9001), MyHandler)
    httpd.server_close()

Calling it with Postman 用邮递员打电话 在此处输入图片说明

and the command line output is 命令行输出是

 C:\\Development\\Python\\test\\venv\\Scripts\\python.exe C:/Development/Python/test/webserver_old.py 1001 jyoti0 127.0.0.1 - - [19/Nov/2018 21:53:45] "POST /do_something HTTP/1.1" 200 - jyoti1 101 

I combined answers from these here: Reference one , two and third And this is also very important to read: https://docs.python.org/3/library/http.server.html 我在这里结合从这些问题的答案:参考一个2第三 ,这也是非常重要的阅读: https://docs.python.org/3/library/http.server.html

http.server is not recommended for production. 不建议将http.server用于生产。 It only implements basic security checks. 它仅实现基本的安全检查。

I believe is ok for a small implementation and some testing around or proof of concept but eventually you'll need to manage this better, maybe I can suggest you to spend some time and use Flask , is actually an excellent & very light framework for Python API building and prototyping. 我相信可以进行一个较小的实现,并进行一些测试或概念验证,但最终您需要更好地进行管理,也许我可以建议您花一些时间并使用Flask ,这实际上是Python的出色且非常轻便的框架API构建和原型制作。

- -

Previous answer (deprecated & updated above) 先前的答案(已弃用并在上面更新)

- -

As per a very light and simple reference to this one: 根据对此的非常简短的参考:

def do_POST(self):
        # Doesn't do anything with posted data
        content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
        post_data = self.rfile.read(content_length) # <--- Gets the data itself
        self._set_headers()
        self.wfile.write("<html><body><h1>POST!</h1></body></html>")

Update (without and API): 更新(不包含API):

Assuming you are running on or machine at a custom port with a custom trailing part at the URL, then "pure" python would look like this: 假设您在URL上带有自定义尾部的自定义端口上运行或运行在计算机上,则“ pure” python如下所示:

import SocketServer
from BaseHTTPServer import BaseHTTPRequestHandler

def doSomething():
    print "i did"

class MyHandler(BaseHTTPRequestHandler):
    def do_POST(self):
        if self.path == '/doSomething':
            mail = self.request.POST.get('email')
            something = self.request.POST.get('something')

            doSomething()
        self.send_response(200)

httpd = SocketServer.TCPServer(("", 8080), MyHandler)
httpd.serve_forever()

I assume this way you can reuse the variables freely. 我假设您可以自由地重用变量。 Check also this reference here , Brenda's answer. 也可以在这里查看此参考资料, 是布伦达的答案。

@oetoni, I am getting time out error while using: @oetoni,使用时出现超时错误:

#!/usr/bin/python3
import socketserver
from http.server import BaseHTTPRequestHandler
import time
import threading


def do_something(site_id, first, last, pass1):
    print(site_id)
    print(first)
    print(last)
    print(pass1)
    #just to illustrate the point and print the variables


class MyHandler(BaseHTTPRequestHandler):
    def do_POST(self):    # !important to use 'do_POST' with Capital POST
        global site_id, first, last, pass1  #those are still undefined at the module level ;) remember this for later
        if self.path == '/do_something':

            request_headers = self.headers

            site_id = request_headers["m_site_name"]
            first = request_headers["m_first_name"]
            last = request_headers["m_last_name"]
            pass1 = request_headers["m_device_name"]

            do_something(site_id, first, last, pass1)
        self.send_response(200)
        self.end_headers()             #as of P3.3 this is required

try:
    httpd = socketserver.TCPServer(("localhost", 9001), MyHandler)
    httpd.serve_forever()
finally:
    httpd = socketserver.TCPServer(("localhost", 9001), MyHandler)
    httpd.server_close()

But I am getting the correct response while using this code: 但是在使用此代码时,我得到了正确的响应:

#!/usr/bin/python3

# -*- coding: UTF-8 -*-

import cgi
import cgitb
cgitb.enable()

print('Content-Type: text/html')
print('')

arguments = cgi.FieldStorage()
for i in arguments.keys():
        print(arguments[i].value)

and it prints the received data on the web browser. 并在网络浏览器上打印接收到的数据。 I am using this script as a cgi script on the apache web server which can be accessed through a web browser. 我将此脚本用作可通过Web浏览器访问的apache Web服务器上的cgi脚本。 I am not running this script as a service or application. 我没有将此脚本作为服务或应用程序运行。

#!/usr/bin/python3

# -*- coding: UTF-8 -*-

import cgi
import cgitb
cgitb.enable()

print('Content-Type: text/html\n')
arguments = cgi.FieldStorage()
print(arguments["m_site_name"].value)
print("<br />\n")
print(arguments["m_first_name"].value)
print("<br />\n")
print(arguments["m_last_name"].value)
print("<br />\n")
print(arguments["m_device_name"].value)
print("<br />\n")
site = arguments["m_site_name"].value
first = arguments["m_first_name"].value
last = arguments["m_last_name"].value
device = arguments["m_device_name"].value
-----do_other_things_with_the_variables(site,first,last,device)-----

This code solved my problem. 这段代码解决了我的问题。 Now I can store HTTP POST data into variables with this python cgi script. 现在,我可以使用此python cgi脚本将HTTP POST数据存储到变量中。

my HTTP POST Request: http://your_server_url_or_IP/cgi-bin/python_script.py?m_site_name=MySite&m_first_name=anyname&m_last_name=anylastanme&m_device_name=anydeviceidorname 我的HTTP POST请求: http://your_server_url_or_IP/cgi-bin/python_script.py?m_site_name = MySite&m_first_name = anyname&m_last_name = anylastanme&m_device_name = anydeviceidorname

With python3, inside do_POST() of your handler class based on http.server.*Handler :使用 python3,在基于http.server.*Handler程序类的do_POST()中:

import cgi

enctype, attrs = cgi.parse_header(self.headers['Content-Type'])
if enctype == 'multipart/form-data':
    boundary = {'boundary':  attrs['boundary'].encode() }
    form_data = cgi.parse_multipart(self.rfile, boundary)
    file_content = form_data.get('myfile')
    fname = 'data/uploads/' + str(time.time()) + '.json'
    with open(fname, 'wb') as fp:
        for part in file_content:
            fp.write(part)

Don't forget to insert Content-Length check to limit the max file size.不要忘记插入 Content-Length 检查以限制最大文件大小。 Presumably cgi.FieldStorage stops reading when limit bytes reached (if specified) and also deals better with large files in general.大概cgi.FieldStorage 在达到limit字节(如果指定)时停止读取,并且通常也能更好地处理大文件。 This is not part of official doc .这不是官方文档的一部分。 I read it in the source file cgi.py .我在源文件cgi.py阅读了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM