Flask的内置服务器始终为404,设置了SERVER_NAME

时间:2017-10-29 16:35:45

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

这是一个最小的例子:

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错误,当我注释掉该行时,它会再次正常运行。

/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或任何生产Web服务器。我只是在处理Flask的内置开发服务器。

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

5 个答案:

答案 0 :(得分:2)

你也可以使用app.run内的端口号和主机,如:

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

删除:

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

答案 1 :(得分:2)

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

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

就像nginx vhost一样,使用Host头进行路由。

我认为SERVER_NAME主要用于路线图。

你应该手动设置主机和IP

  

app.run(主机=&#34; 0.0.0.0&#34;,端口= 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

最后,除非您知道它对路线图的影响,否则请勿使用SERVER_NAME设置主机,ip app.run()。

答案 2 :(得分:0)

来自Flask docs

  

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

  

有关SERVER_NAME的更多信息

     

SERVER_NAME键用于子域   支持。因为Flask无法猜测子域部分   了解实际的服务器名称,如果您愿意,这是必需的   使用子域名。这也用于会话cookie。

     

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

看起来没有必要将其设置为localhost。正如文档中所建议的那样,尝试myapp.dev:5000

之类的内容

答案 3 :(得分:0)

使用.runInput:focus { outline: 0 !important; } 为我工作:

debug=True

答案 4 :(得分:0)

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

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

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