【问题标题】:Flask's built-in server always 404 with SERVER_NAME setFlask 的内置服务器总是 404 并设置了 SERVER_NAME
【发布时间】:2018-04-10 16:29:15
【问题描述】:

这是一个最小的例子:

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)

如果我设置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.

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

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

【问题讨论】:

    标签: python flask pycharm http-status-code-404 werkzeug


    【解决方案1】:

    设置 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!
    

    如果你使用web explorer,你应该使用http://myapp.dev:5000/访问它并设置/etc/hosts文件。

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

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

    你应该手动设置主机和ip

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

    如果你没有设置host/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
    

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

    【讨论】:

    • 嗨,从 2019/08 (Flask 1.0) 开始,情况并非如此,默认主机和运行命令的端口是硬编码的。 github.com/pallets/flask/blob/…
    • 非常感谢你,我被这个问题打破了!投票赞成加号解释!谢谢!
    【解决方案2】:

    有时我发现 Flask 的文档令人困惑(请参阅上面 @dm295 的引号 - 围绕“SERVER_NAME”的含义的含义很难解析)。但是@Dancer Phd 的答案的替代设置(并受其启发)是在配置文件中指定“HOST”和“PORT”参数而不是“SERVER_NAME”。

    例如,假设您使用 Flask docs 中提出的配置策略,添加主机和端口号如下:

    class Config(object):
        DEBUG = False
        TESTING = False
        DATABASE_URI = 'sqlite://:memory:'
        HOST = 'http://localhost' #
        PORT = '5000'
    
    class ProductionConfig(Config):
        DATABASE_URI = 'mysql://user@localhost/foo'
    
    class DevelopmentConfig(Config):
        DEBUG = True
    
    class TestingConfig(Config):
        TESTING = True 
    

    【讨论】:

    • 这是在哪里记录的?你真的让它工作了吗?为什么 HOST 包含http://
    • 嗨@BigMcLargeHuge,请参阅链接文档上的此部分:flask.palletsprojects.com/en/0.12.x/config/…。我认为您不需要在本地主机中使用http://,它应该可以工作
    • 具体来说,我问的是 HOST 和 PORT 值。我找不到这些设置的任何文档。
    • 啊,我明白了。我认为 Flask 文档已经改变了。从对this answer above 的评论看来,'host' 和'port' 的默认值分别是127.0.0.15000。实际上,要在 CLI 上运行我的应用程序,我通常会这样做:flask run --host=localhost --port=PORT_NUMBER
    【解决方案3】:

    来自Flask docs

    服务器的名称和端口号。需要子域支持 (例如:'myapp.dev:5000')注意 localhost 不支持 子域,因此将其设置为“localhost”无济于事。设置一个 默认情况下,SERVER_NAME 也可以在没有请求的情况下生成 URL 上下文,但带有应用程序上下文。

    有关 SERVER_NAME 的更多信息

    SERVER_NAME 键用于子域 支持。因为 Flask 在没有 了解实际的服务器名称,如果您想这样做,这是必需的 使用子域。这也用于会话 cookie。

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

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

    【讨论】:

      【解决方案4】:

      您也可以在app.run 中仅使用端口号和主机,例如:

      app.run(debug=True, port=5000, host="localhost")
      

      删除:

      app.config['DEBUG'] = True
      app.config['SERVER_NAME'] = 'myapp.dev:5000'
      

      【讨论】:

        【解决方案5】:

        使用 debug=True 为我工作:

        from flask import Flask
        
        
        app = Flask(__name__)
        app.config['SERVER_NAME'] = 'localhost:5000'
        
        @app.route('/')
        def hello_world():
            return 'Hello World!'
        
        
        if __name__ == '__main__':
            app.run(debug=True)
        

        【讨论】:

          猜你喜欢
          • 2018-10-04
          • 2014-04-14
          • 1970-01-01
          • 2021-08-13
          • 1970-01-01
          • 2020-05-01
          • 2010-09-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多