Flask 的内置服务器总是 404 设置 SERVER_NAME

nal*_*zok 12 python werkzeug pycharm flask http-status-code-404

这是一个最小的例子:

from flask import Flask

app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SERVER_NAME'] = 'myapp.dev:5000'


@app.route('/')
def hello_world():
    return 'Hello World!'

@app.errorhandler(404)
def not_found(error):
    print(str(error))
    return '404', 404


if __name__ == '__main__':
    app.run(debug=True)
Run Code Online (Sandbox Code Playgroud)

如果我设置了SERVER_NAME,Flask 会以 404 错误响应每个URL,当我注释掉该行时,它会再次正常运行。

/Users/sunqingyao/Envs/flask/bin/python3.6 /Users/sunqingyao/Projects/play-ground/python-playground/foo/foo.py
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 422-505-438
127.0.0.1 - - [30/Oct/2017 07:19:55] "GET / HTTP/1.1" 404 -
404 Not Found: The requested URL was not found on the server.  If you entered the URL manually please check your spelling and try again.
Run Code Online (Sandbox Code Playgroud)

请注意,当使用 SERVER_NAME 时,这不是Flask 404的副本,因为我没有使用 Apache 或任何生产网络服务器。我只是在处理 Flask 的内置开发服务器。

如果相关,我在 macOS High Sierra 上使用 Python 3.6.2、Flask 0.12.2、Werkzeug 0.12.2、PyCharm 2017.2.3。

tin*_*are 6

设置 SERVER_NAME 时,您应该使 HTTP 请求标头 'Host' 与其相同:

# curl http://127.0.0.1:5000/ -sv -H 'Host: myapp.dev:5000'
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 5000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Accept: */*
> Host: myapp.dev:5000
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Content-Length: 13
< Server: Werkzeug/0.14.1 Python/3.6.5
< Date: Thu, 14 Jun 2018 09:34:31 GMT
<
* Closing connection 0
Hello, World!
Run Code Online (Sandbox Code Playgroud)

如果您使用网络浏览器?您应该使用http://myapp.dev:5000/访问它并设置 /etc/hosts 文件。

就像nginx vhost,使用Host header做路由。

我认为 SERVER_NAME 主要用于路由映射。

你应该手动设置主机和IP

app.run(host="0.0.0.0",port=5000)

如果您没有设置主机/IP 而是设置了 SERVER_NAME 并发现它似乎可以工作,因为 app.run() 具有以下逻辑:

    def run(self, host=None, port=None, debug=None,
        load_dotenv=True, **options):

        ...

        _host = '127.0.0.1'
        _port = 5000
        server_name = self.config.get('SERVER_NAME')
        sn_host, sn_port = None, None

        if server_name:
            sn_host, _, sn_port = server_name.partition(':')

        host = host or sn_host or _host
        port = int(port or sn_port or _port)

        ...

        try:
            run_simple(host, port, self, **options)
        finally:
            self._got_first_request = False
Run Code Online (Sandbox Code Playgroud)

最后,不要使用SERVER_NAME来设置host,ip app.run() 使用,除非你知道它对路由图的影响。


Duš*_*ďar 1

来自Flask 文档

\n\n
\n

服务器的名称和端口号。需要子域支持\n(例如:\'myapp.dev:5000\')请注意,localhost 不支持\n 子域,因此将其设置为\xe2\x80\x9clocalhost\xe2\x80\x9d 没有帮助。默认情况下,设置 SERVER_NAME 还可以在不使用请求上下文但使用应用程序上下文的情况下启用 URL 生成。

\n
\n\n

\n\n
\n

有关 SERVER_NAME 的更多信息

\n\n

SERVER_NAME 键用于子域支持。由于 Flask 在不知道实际服务器名称的情况下无法猜测子域部分,因此如果您想要使用子域,这是必需的。这也用于会话 cookie。

\n\n

请记住,不仅 Flask 存在不知道子域是什么的问题,您的 Web 浏览器也存在这样的问题。大多数现代 Web 浏览器不允许在名称中不带点的服务器上设置跨子域 Cookie。因此,如果您的服务器名称是“localhost”,您将无法为“localhost”及其每个子域设置 cookie。在这种情况下,请选择不同的服务器名称,例如 \n \'myapplication.local\' 并将此名称 + 您想要\n 使用的子域添加到主机配置中或设置本地绑定。

\n
\n\n

看起来没有必要将其设置为localhost。按照文档中的建议,尝试类似myapp.dev:5000.

\n