【问题标题】:Google App Engine and 404 errorGoogle App Engine 和 404 错误
【发布时间】:2010-09-16 10:15:38
【问题描述】:

我使用在其他地方找到的提示在 GAE 上设置了一个静态网站,但不知道如何返回 404 错误。我的 app.yaml 文件看起来像

- url: (.*)/
  static_files: static\1/index.html
  upload: static/index.html

- url: /
  static_dir: static

所有静态 html/jpg 文件都存储在静态目录下。以上适用于存在的文件,但如果不存在则返回空长度文件。答案可能是编写一个 python 脚本来返回一个 404 错误,但是你如何设置东西来为存在的静态文件提供服务,但为不存在的文件运行脚本呢?

这是在开发应用服务器上获取一个不存在的文件 (nosuch.html) 的日志:

ERROR    2008-11-25 20:08:34,084 dev_appserver.py] Error encountered reading file "/usr/home/ctuffli/www/tufflinet/static/nosuch.html":
[Errno 2] No such file or directory: '/usr/home/ctuffli/www/tufflinet/static/nosuch.html'
INFO     2008-11-25 20:08:34,088 dev_appserver.py] "GET /nosuch.html HTTP/1.1" 404 -

【问题讨论】:

  • 我会标记这个'python'但我没有访问权限(还)......

标签: python google-app-engine http-status-code-404


【解决方案1】:

您需要注册一个包罗万象的脚本处理程序。将此附加到 app.yaml 的末尾:

- url: /.*
  script: main.py

您需要在 main.py 中输入以下代码:

from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app

class NotFoundPageHandler(webapp.RequestHandler):
    def get(self):
        self.error(404)
        self.response.out.write('<Your 404 error html page>')

application = webapp.WSGIApplication([('/.*', NotFoundPageHandler)],
                                     debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

用有意义的东西替换&lt;Your 404 error html page&gt;。或者更好地使用模板,您可以阅读如何做到这一点here

如果您在设置时遇到问题,请告诉我。

【讨论】:

  • 看起来我的原始 app.yaml 中的最后一行在您建议添加的那一行之前匹配
  • 这行得通,但我更喜欢 Zachary 的建议,即为 404 页面使用静态处理程序(请参阅下面的答案)。
  • 我正在尝试这样做,但是如果我设置了 404 错误,无论我是否使用模板,都不会显示 html。
  • 不适用于您拥有不同网址的情况,例如 domain.com/admin/.* 、 domain.com/.* 等
  • 这似乎不适用于 static_dir 子句。似乎 static_dir 中任何丢失的文件都会返回它自己的(空的)404 页面,而不是直接传递给其他处理程序。
【解决方案2】:

谷歌应用引擎现在有Custom Error Responses

因此您现在可以将 error_handlers 部分添加到您的 app.yaml 中,如下例所示:

error_handlers:

- file: default_error.html

- error_code: over_quota
    file: over_quota.html

【讨论】:

  • 这里需要把HTML文件放在哪里?
  • 您可以将 HTML 放在任何地方,例如error_handlers: - 文件:youappname/templates/default_error.html
  • 注意:因此回答不回答问题
【解决方案3】:

在不需要任何 CPU 周期的情况下执行此操作的一种非常简单的方法是将此处理程序放在 app.yaml 的底部

- url: /.*
    static_files: views/404.html
    upload: views/404.html

这允许您将静态 404.html 文件放置在您的视图目录中。不需要 python 处理程序。您的 app.yaml 中未处理的任何内容都会受到影响。

【讨论】:

  • 这种方式无法返回 404 HTTP 响应代码,是吗?
  • 是的,您所要做的就是将标题添加到您的 HTML 文件中。
  • 也许它很棒..但如果你有 nadlers/controllers 即 domain.com/admin/ 和不同的 domain.com/ 并且你想处理域,它就不起作用。 com/admin/notexistent 和 domain.com/nonexistent 404 错误
  • 这是错误的。您不能让静态内容返回 200 以外的状态码。
  • 添加到@NickJohnson - 这不是限制,而是定义:如果您提供静态内容,它被发现
【解决方案4】:

您可以创建一个函数来处理任何状态代码的错误。你的情况是 404,定义一个这样的函数:

def Handle404(request, response, exception):
     response.out.write("Your error message") 
     response.set_status(404)`

您可以在 response.out.write 函数中传递任何内容 - HTML / 纯文本 / 模板。现在,在您的 app 声明之后添加以下声明。

app.error_handlers[404] = Handle404

这对我有用。

【讨论】:

    【解决方案5】:

    webapp2 提供了error_handlers 字典,您可以使用它来提供自定义错误页面。 示例如下:

    def handle_404(request, response, exception):
        logging.warn(str(exception))
        response.set_status(404)
        h = YourAppBaseHandler(request, response)
        h.render_template('notfound')
    
    def handle_500(request, response, exception):
        logging.error(str(exception))
        response.set_status(500)
        h = YourAppBaseHandler(request, response)
        h.render_template('servererror')
    
    app = webapp2.WSGIApplication([
        webapp2.Route('/', MainHandler, name='home')
        ], debug=True)
    app.error_handlers[404] = handle_404
    app.error_handlers[500] = handle_500
    

    更多详细信息请参见webapp2 的文档页面:http://webapp-improved.appspot.com/guide/app.html#error-handlers

    【讨论】:

    • 这非常有用,因为现有 webapp2 路由(页面和通配符)的性质会导致其他解决方案无法正常工作。谢谢。
    【解决方案6】:

    dev_appserver 已经为任何不匹配映射或匹配映射但不存在的任何内容返回 404 响应。 404 响应本身没有正文,但它仍然是 404:

    $ wget -O - http://127.0.0.1:8080/foo
    --2010-10-28 10:54:51--  http://127.0.0.1:8080/foo
    Connecting to 127.0.0.1:8080... connected.
    HTTP request sent, awaiting response... 404 
    2010-10-28 10:54:51 ERROR 404: (no description).
    
    $ wget -O - http://127.0.0.1:8080/foo/
    --2010-10-28 10:54:54--  http://127.0.0.1:8080/foo/
    Connecting to 127.0.0.1:8080... connected.
    HTTP request sent, awaiting response... 404 
    2010-10-28 10:54:54 ERROR 404: (no description).
    

    如果您想返回更加用户友好的错误页面,请遵循 jonmiddleton 的建议并指定自定义 404 页面。

    【讨论】:

    • 这样不行,我认为error_code可以是^(default|over_quota|dos_api_denial|timeout)$,默认不处理404错误
    • @rafek 然后指定一个包罗万象的处理程序,正如 Alexander 建议的那样。无论哪种方式,默认处理程序已经返回了正确的响应代码,只是没有向用户提供解释性消息。
    • @Nick:如果我有 /admin/.* 处理程序和(全部)/.* 处理程序并按照 Alexander 的建议行事.. 那么 domain.com/admin/stuff-that-doesnt -exist 未处理.. 因为 app.yaml 中的 /admin/.* 处理程序处理了它.. 然后我应该为每个脚本捕获所有处理程序 - 这是严重的代码重复。
    • 然后将您的处理程序限制为一个,或者有一个包含 404 处理程序的模块,您在每个处理程序中导入该处理程序,并将其设置为包罗万象。
    • 一个处理程序 script - 任意数量的处理程序。大多数人每个“应用”使用一个。
    【解决方案7】:

    我已经查看了以上所有给出的答案,并在最后使用以下作为最通用的 404 解决方案:

    app.yaml末尾添加此链接

    - url: /(.*) 
      script: 404.app
    

    并使用以下内容创建404.py

    import webapp2
    from google.appengine.ext.webapp import template
    
    class NotFound(webapp2.RequestHandler):
      def get(self):
        self.error(404)
        self.response.out.write(template.render('404.html', {}))
    
    app = webapp2.WSGIApplication([
        ('/.*', NotFound)
    ], debug=True)
    

    这将显示带有 404 错误代码的 404.html 文件的内容。

    此解决方案的优点是简单、行为的正确性和灵活性,因为它允许使用静态 404.html 文件作为错误页面内容。

    我还想对上面建议的一些解决方案提出警告。

    • Custom Error Responses 不能使用 404 错误
    • 也不要使用静态文件,因为它们会返回 200 而不是 404 错误。这可能会给您带来很多麻烦。

    【讨论】:

      【解决方案8】:

      我无法评论 jonmiddleton 的回答,但从外观上看,自定义错误响应是针对 App 引擎特定错误的。 我看不到指定自定义 404 页面的方法。

      Django 让你specify 一个。

      【讨论】:

        【解决方案9】:

        我的方法是在我放在最后一个处理程序中的全部处理程序中处理 404 和永久重定向。当我重新设计和应用程序并重命名/替换 url 时,这很有用:

        app = webapp2.WSGIApplication([
            ...
            ...
            ('/.*', ErrorsHandler)
        ], debug=True)
        
        
        class ErrorsHandler(webapp2.RequestHandler):
            def get(self):
                p = self.request.path_qs
                if p in ['/index.html', 'resources-that-I-removed']:  
                    return self.redirect('/and-substituted-with-this', permanent=True)
                else: 
                    self.error(404)
                    template = jinja_environment.get_template('404.html')
                    context =  {
                        'page_title': '404',
                    }
                    self.response.out.write(template.render(context))
        

        【讨论】:

          猜你喜欢
          • 2021-11-02
          • 1970-01-01
          • 1970-01-01
          • 2015-09-21
          • 2017-10-04
          • 2013-07-15
          • 1970-01-01
          • 2012-01-25
          • 1970-01-01
          相关资源
          最近更新 更多