从 SimpleHTTPServer Post 数据中读取 JSON

Posted

技术标签:

【中文标题】从 SimpleHTTPServer Post 数据中读取 JSON【英文标题】:Reading JSON from SimpleHTTPServer Post data 【发布时间】:2015-09-30 23:55:54 【问题描述】:

我正在尝试使用 python SimpleHTTPServer 构建一个简单的 REST 服务器。我在从帖子消息中读取数据时遇到问题。如果我做得对,请告诉我。

from SimpleHTTPServer import SimpleHTTPRequestHandler
import SocketServer
import simplejson

class S(SimpleHTTPRequestHandler):
    def _set_headers(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        print "got get request %s" % (self.path)
        if self.path == '/':
          self.path = '/index.html'
          return SimpleHTTPRequestHandler.do_GET(self)

    def do_POST(self):
        print "got post!!"
        content_len = int(self.headers.getheader('content-length', 0))
        post_body = self.rfile.read(content_len)
        test_data = simplejson.loads(post_body)
        print "post_body(%s)" % (test_data)
        return SimpleHTTPRequestHandler.do_POST(self)

def run(handler_class=S, port=80):
    httpd = SocketServer.TCPServer(("", port), handler_class)
    print 'Starting httpd...'
    httpd.serve_forever()

index.html 文件

<html>
<title>JSON TEST PAGE</title>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">

JSONTest = function() 

var resultDiv = $("#resultDivContainer");

$.ajax(
    url: "http://128.107.138.51:8080",
    type: "POST",
    data: txt1: $("#json_text").val(),
    dataType: "json",
    success: function (result) 
        switch (result) 
            case true:
                processResponse(result);
                break;
            default:
                resultDiv.html(result);
        
    ,
    error: function (xhr, ajaxOptions, thrownError) 
    alert(xhr.status);
    alert(thrownError);
    
);
;

</script>
</head>
<body>

<h1>My Web Page</h1>
<div id="resultDivContainer"></div>
<form>
<textarea name="json_text" id="json_text" rows="50" cols="80">
["resources": "dut": "any_ts", "endpoint1": "endpoint", "endpoint2": "endpoint",
"action": "create_conference", "serverName": "dut", "confName": "GURU_TEST"]
</textarea>
<button type="button" onclick="JSONTest()">Generate Test</button>
</form>
</body>
</html>

SimpleJson 无法从 POST 消息中加载 json。我不熟悉网络编码,我什至不确定我所做的是否适合创建一个简单的 REST API 服务器。 我感谢您的帮助。

【问题讨论】:

另外,如果这不是可行的方法,如果只有 django 是唯一可行的方法,请告诉我。 getheadersself.headers 上的 Python 3 中没有实现。请改用self.headers['Content-Length']。如果 header 不存在,它将返回None 【参考方案1】:

感谢 matthewatabet 提出 klein 的想法。我想出了一种使用 BaseHTTPHandler 来实现它的方法。下面的代码。

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import SocketServer
import simplejson
import random

class S(BaseHTTPRequestHandler):
    def _set_headers(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html')
        self.end_headers()

    def do_GET(self):
        self._set_headers()
        f = open("index.html", "r")
        self.wfile.write(f.read())

    def do_HEAD(self):
        self._set_headers()

    def do_POST(self):
        self._set_headers()
        print "in post method"
        self.data_string = self.rfile.read(int(self.headers['Content-Length']))

        self.send_response(200)
        self.end_headers()

        data = simplejson.loads(self.data_string)
        with open("test123456.json", "w") as outfile:
            simplejson.dump(data, outfile)
        print "".format(data)
        f = open("for_presen.py")
        self.wfile.write(f.read())
        return


def run(server_class=HTTPServer, handler_class=S, port=80):
    server_address = ('', port)
    httpd = server_class(server_address, handler_class)
    print 'Starting httpd...'
    httpd.serve_forever()

if __name__ == "__main__":
    from sys import argv

if len(argv) == 2:
    run(port=int(argv[1]))
else:
    run()

以及对应的html页面

<form action="/profile/index/sendmessage" method="post" enctype="application/x-www-form-urlencoded">
<div class="upload_form">
    <dt id="message-label"><label class="optional" for="message">Enter Message</label></dt>
    <dd id="message-element">
    <textarea cols="80" rows="50" id="message" name="message">
["resources": "dut": "any_ts", "endpoint1": "multistream_endpoint", "endpoint2": "multistream_endpoint",

"action": "create_conference", "serverName": "dut", "conferenceName": "GURU_SLAVE_TS",

"action": "dial_out_ep", "serverName": "dut", "confName": "GURU_SLAVE_TS", "epName": "endpoint1"
]
        </textarea></dd>
    <dt id="id-label">&nbsp;</dt>
    <dd id="id-element">
    <input type="hidden" id="id" value="145198" name="id"></dd>
    <dt id="send_message-label">&nbsp;</dt>
    <dd id="send_message-element">
    <input type="submit" class="sendamessage" value="Send" id="send_message" name="send_message"></dd>
</div>
</form>

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script type="text/javascript">
$("input.sendamessage").click(function(event) 
event.preventDefault();

var message = $('textarea#message').val();
var id      = $('input#id').val();
url = "http://128.107.138.51:8080"

var posting = $.post(url, message)

posting.done(function( data ) 
  alert(message);
);
);


</script>

【讨论】:

在 do_POST() 函数中,您发送了两次响应和 end_headers()。【参考方案2】:

SimpleHTTPRequestHandler 不支持 POST。确实很简单。看看克莱恩,他的服务器功能更全。

这里有一个 json PUT(非常接近 POST)的示例: https://pypi.python.org/pypi/klein/0.2.3

import json

from klein import Klein


class ItemStore(object):
    app = Klein()

    def __init__(self):
        self._items = 

    @app.route('/')
    def items(self, request):
        request.setHeader('Content-Type', 'application/json')
        return json.dumps(self._items)

    @app.route('/<string:name>', methods=['PUT'])
    def save_item(self, request, name):
        request.setHeader('Content-Type', 'application/json')
        body = json.loads(request.content.read())
        self._items[name] = body
        return json.dumps('success': True)

    @app.route('/<string:name>', methods=['GET'])
    def get_item(self, request, name):
        request.setHeader('Content-Type', 'application/json')
        return json.dumps(self._items.get(name))


if __name__ == '__main__':
    store = ItemStore()
    store.app.run('localhost', 8080)

【讨论】:

感谢您的链接。我还认为可以使用 BaseHTTPHandler 来完成。

以上是关于从 SimpleHTTPServer Post 数据中读取 JSON的主要内容,如果未能解决你的问题,请参考以下文章

通过SimpleHTTPServer实现树莓派与主机传输文件

BaseHTTPServer 和 SimpleHTTPServer 有啥区别?何时何地使用它们?

使用 SimpleHTTPServer 禁用索引文件

使用 SimpleHTTPServer 进行单元测试

python SimpleHTTPServer源码学习

Python SimpleHTTPServer