从espduino发布到Flask的时间超时

时间:2015-08-29 05:51:15

标签: python flask arduino

我正在使用esp8266向使用this library的Arduino提供WiFi。我已正确设置POST到Pushover以及requestbin,在调试输出和这些工具的界面之间,我可以验证请求数据是否正在正确发布,以及esp8266 / arduino unit的响应状态代码正确显示200。

我想测试设置的可靠性,所以我想我会转向Flask。我将来自espduino的100个请求发送到for循环到0.0.0.0:5000运行的Flask应用程序。 POST包含一个测试字符串(试图粗略地衡量简单的数据完整性,确保字符串未被破坏)以及正在发送的循环数(例如,第一个循环为0 ...最后一个为99) 。 Flask会跟踪这些请求并更新其输出,以显示哪些请求正确通过,哪些请求未通过。

设置工作正常,除了一件事:模块在每次请求后超时。每个POST似乎都有效,Flask会相应地更新输出,但espduino会为每个请求花费整整5秒(默认超时),并说它的响应代码为0

所以重申一下情况:我的espduino设置正确POST并从requestb.in和pushover.net获得200响应,但是我的本地Flask服务器POST然后超时。

WHYT

  • 确保all form data is read by Flask - >没有区别
  • 使用gunicorn代替内置的Flask服务器 - >没有区别
  • 将响应内容类型明确更改为" text / html" - >没有区别
  • 将响应内容类型更改为" application / json" - >没有区别
  • ; charset=utf-8添加到内容类型 - >没有区别
  • 将Flask api端点从索引/更改为/api - >没有区别
  • 更改端口 - >没有区别
  • 验证防火墙已关闭(OS X 10.10.5托管Flask应用) - >没有区别
  • nc -l 5000并检查模块中的传入帖子(看起来不错)
  • 从邮递员发帖并卷曲到Flask应用程序以检查响应(并与Requestb.in /工作站点的响应进行比较)
  • 从test_string
  • 中删除了特殊字符
  • WSGIRequestHandler.protocol_version更改为HTTP/1.1 - >没有区别

我花了几天时间研究这个和not made much progress。我今天取得的最大突破是,如果我将我的gunicorn / Flask设置置于nginx之后,我可以成功发布并获得200条响应,并且对espduino代码进行 no 更改,所以我确定在那里Flask正在做或不做的事情(我担心它可能是espduino对IP地址与域名的处理,但我认为这可以解决这个问题。)

我尝试过的设置摘要:

  • POST到requestb.in - > POST工作,200响应,无超时
  • POST to pushover.net - > POST工作,200响应,无超时
  • POST到本地Flask服务器 - > POST有效,无响应,超时
  • GET到本地Flask服务器 - > 没有回应,超时(尚未测试GET数据)
  • 发布到本地gunicorn服务Flask app - > POST有效,无响应,超时
  • 发布到本地nginx服务gunicorn / Flask - > POST工作,200响应,无超时
  • POST到本地gunicorn服务httpbin - > 没有回应,超时
  • POST到本地cherrypy服务器 - > 没有回应,超时

当前代码:

from flask import Flask, request, make_response
from datetime import datetime

app = Flask(__name__)

ESPDUINO_IP = 'XXX.XXX.XXX.XXX'
INCOMING_TEST_STRING = 'This is my espduino test string!'
incoming_requests = []

with open('results.txt', 'w') as f:
    f.write("Test run start: {}\n".format(datetime.now()))

@app.route('/api', methods=['GET', 'POST'])
def count_requests():
    if request.method == 'POST':
        form = request.form
        incoming_ip = request.remote_addr
        if incoming_ip == ESPDUINO_IP and form['test_string'] == INCOMING_TEST_STRING:
            test_num = int(form['test_num'])
            incoming_requests.append(test_num)
            msg = "All is peachy!"
            with open('results.txt', 'a') as f:
                f.write("{:02d}: {}\n".format(test_num, datetime.now()))
    else:
        msg = "Hey, you're not the espduino!<br>"
        msg += str(len(incoming_requests)) + " requests so far.<br>"
        missing = set(range(100)) - set(incoming_requests)
        msg += "Missing: {}<br>".format(', '.join(map(str, missing)) if missing else "None!")
        msg += '<br>'.join(map(str, incoming_requests))

    resp = make_response('{"this": "that"}')
    resp.headers['Content-Type'] = "application/json"
    return resp
    # return "<html><body>{}</body></html>".format(msg)

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

这里是来自espduino的POST的样子:

$ nc -l 5000
POST /api HTTP/1.1
Host: XXX.XXX.XXX.XXX
Content-Length: 55
Connection: close
Content-Type: application/x-www-form-urlencoded
User-Agent: ESPDRUINO@tuanpm

test_string=This is my espduino test string!&test_num=0

curl -X POST -d 'test_string=This is my espduino test string!&test_num=0' localhost:5000/api相比:

$ nc -l 5000
POST /api HTTP/1.1
Host: localhost:5000
User-Agent: curl/7.43.0
Accept: */*
Content-Length: 55
Content-Type: application/x-www-form-urlencoded

test_string=This is my espduino test string!&test_num=0

很想听听有关可能发生的事情的任何想法。我想知道这可能是一个WSGI问题吗?

2015年8月31日更新:

我仍然无法理解这一点,但这绝对不是Flask特有的问题。如上所述,我还使用CherryPy以及python3 -m http.server --bind 0.0.0.0 5000(并将espduino代码更改为GET /)以及ruby -run -e httpd复制了超时。 。我仍然不明白为什么nginx,requestbin等服务它没有任何问题。

为了回应@ Miguel关于HOST标头没有端口的评论,我正在努力分叉并构建固件来改变它,但同时我硬编码了客户端主机和将端口转换为一个没有运气的小HTTP服务器脚本。

from http.server import BaseHTTPRequestHandler, HTTPServer

class MyServer(BaseHTTPRequestHandler):
    # protocol_version = 'HTTP/1.1'
    # close_connection = True
    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()
        self.wfile.write(b"<html><body><h1>hi!</h1></body></html>")

    def do_HEAD(self):
        self._set_headers()

    def do_POST(self):
        self.client_address = ("192.168.0.4", 5000)
        self._set_headers()
        self.wfile.write(b"<html><body><h1>POST!</h1></body></html>")
        # import pdb; pdb.set_trace()

def run(server_class=HTTPServer, handler_class=MyServer, port=5000):
    server_address = ('0.0.0.0', port)
    httpd = server_class(server_address, handler_class)
    print('Starting httpd...')
    httpd.serve_forever()

if __name__ == "__main__":
    run()

查看tcpdump,看看我是否能找到工作(nginx)和非工作网络数据之间的任何区别。到目前为止,Haven找不到任何东西,但我也是该工具的新手。

2015年9月8日更新

仍然没有想到这一点,但看起来tcpdump在nginx和Python服务器之间存在显着差异。这是一个示例POST和响应 - 为了清楚起见,我已将ESPDUINO_IPOSX_IP替换为IP,并清理了周围的ACK调用等。我需要研究为什么Python响应会被那个奇怪的行中断 - 我检查了10个连续的POST / Response对,并且每个的Python响应被中断了(就在相同的地方)和nginx响应的 none ,所以我想知道这可能是问题。 (另外,正如您所看到的,在本轮测试中,我已将响应主体更改为文本而不是JSON - 结果没有变化。)

nginx(作品)
POST /api HTTP/1.1
Host: OSX_IP
Content-Length: 29
Connection: close
Content-Type: application/x-www-form-urlencoded; charset=utf-8
User-Agent: espduino@n8henrie

test_string=simple&test_num=0


09:16:04.079291 IP OSX_IP.commplex-main > ESPDUINO_IP.49146: Flags [P.], seq 1:183, ack 211, win 65535, length 182

HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Mon, 31 Aug 2015 15:16:04 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 26
Connection: close

<html><body></body></html>
烧瓶(超时)
POST /api HTTP/1.1
Host: OSX_IP
Content-Length: 29
Connection: close
Content-Type: application/x-www-form-urlencoded; charset=utf-8
User-Agent: espduino@n8henrie

test_string=simple&test_num=3

09:00:19.424086 IP OSX_IP.commplex-main > ESPDUINO_IP.48931: Flags [P.], seq 1:18, ack 211, win 65535, length 17

HTTP/1.0 200 OK

09:00:36.382125 IP OSX_IP.commplex-main > ESPDUINO_IP.48931: Flags [FP.], seq 18:181, ack 211, win 65535, length 163
E....F@.@..,...e.......#...k..S.P.......Content-Type: text/html; charset=utf-8
Content-Length: 26
Server: Werkzeug/0.10.4 Python/3.4.3
Date: Mon, 31 Aug 2015 15:00:36 GMT

<html><body></body></html>

在我看来,Python因某种原因将响应分成两部分,例如:与length 17的nginx单一回复相比,length 163的一部分和length 182的另一部分。

2015年9月10日更新

有趣的是,如果我通过mitmproxy运行它,一切都按预期工作 - 甚至直接到没有nginx或gunicorn的Flask应用程序。一旦我删除了mitmproxy,它就会恢复到上面的超时时间。

0 个答案:

没有答案