簡體   English   中英

如何使用python從傳入的HTTP POST中提取數據

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

我有一個 Ubuntu LAMP 網絡服務器,數據通過 HTTP POST 方法不斷發送到網絡服務器。 我需要從 HTTP POST 中提取數據並將它們插入到數據庫中。 我不知道該怎么做。 有很多關於如何處理傳出的 HTTP POST 請求但傳入的 HTTP POST 請求的示例。 我想編寫一個 python3 腳本,它將從傳入的 HTTP POST 請求中提取數據並將它們保存為變量,我將用它來將數據插入數據庫並向客戶端返回響應。有人可以在這方面幫助我嗎?

UPDATE

根據您在下面發布的代碼,這是一個有效的答案。

#!/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()

用郵遞員打電話 在此處輸入圖片說明

命令行輸出是

 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 

我在這里結合從這些問題的答案:參考一個2第三 ,這也是非常重要的閱讀: https://docs.python.org/3/library/http.server.html

不建議將http.server用於生產。 它僅實現基本的安全檢查。

我相信可以進行一個較小的實現,並進行一些測試或概念驗證,但最終您需要更好地進行管理,也許我可以建議您花一些時間並使用Flask ,這實際上是Python的出色且非常輕便的框架API構建和原型制作。

-

先前的答案(已棄用並在上面更新)

-

根據對此的非常簡短的參考:

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>")

更新(不包含API):

假設您在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()

我假設您可以自由地重用變量。 也可以在這里查看此參考資料, 是布倫達的答案。

@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()

但是在使用此代碼時,我得到了正確的響應:

#!/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)

並在網絡瀏覽器上打印接收到的數據。 我將此腳本用作可通過Web瀏覽器訪問的apache Web服務器上的cgi腳本。 我沒有將此腳本作為服務或應用程序運行。

#!/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)-----

這段代碼解決了我的問題。 現在,我可以使用此python cgi腳本將HTTP POST數據存儲到變量中。

我的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

使用 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)

不要忘記插入 Content-Length 檢查以限制最大文件大小。 大概cgi.FieldStorage 在達到limit字節(如果指定)時停止讀取,並且通常也能更好地處理大文件。 這不是官方文檔的一部分。 我在源文件cgi.py閱讀了它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM