Google App Engine 静态文件服务与应用程序冲突

Posted

技术标签:

【中文标题】Google App Engine 静态文件服务与应用程序冲突【英文标题】:Google App Engine static file serving conflicts with application 【发布时间】:2014-03-10 04:00:22 【问题描述】:

我有一个使用 Google App Engine (GAE) 运行的单页应用 (SPA)。 GAE 做了三件事:

    提供 index.html 文件 提供静态文件(JS、CSS 等) 通过 REST 提供动态文件(图像、文本等)

我使用下面的 app.yaml 配置。

handlers:
- url: /app
  static_dir: app

- url: /.*
  script: main.app

我的理解是,这应该与进入 /app 文件夹的任何请求相匹配,该文件夹将为我的静态文件提供服务。然后所有的 REST 服务和主索引页面将被 /.* 捕获并由 main.py 处理

但是,我看到以下行为:

    如果我删除 /app 处理程序,我可以成功地提供 index.html(通过 Jinja 模板)和 REST 服务(例如 localhost/subjects/)。 但是,我看不到静态文件(如预期的那样)。 如果我添加 /app 处理程序,则 index.html 文件不会提供服务并给出“内部服务器错误”IOError(errno.EACCES, 'file not access', filename)。 不过,当我请求静态文件如:“localhost/app/app.js”时,就成功了。

这里有什么我遗漏的吗?我不明白为什么两者会冲突。

谢谢!

注意事项: Google App Engine 1.8.9,Python 2.7,本地开发

编辑:

这是我用来提供页面的 Python 代码

path = os.path.join(os.path.dirname(__file__), 'app')
jinja_environment = jinja2.Environment(loader=jinja2.FileSystemLoader(path))

class MainHandler(webapp2.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/html'
    template_values = 
    template = jinja_environment.get_template('index.html')
    self.response.out.write(template.render(template_values))

我的目录结构如下:

/

main.py

app.yaml 等

应用程序

index.html

app.js

模块 A

moduleA.tpl.html

moduleA.js

编辑 2:

我将 index.html 移到根目录(/),然后使用以下 python 代码:

path = os.path.dirname(__file__)
jinja_environment = jinja2.Environment(loader=jinja2.FileSystemLoader(path))

看起来(非常有趣)index.html 到 Jinja 模板和静态目录文件的“双重映射”导致了一个问题。我想知道这样做的最佳实践方法是什么。我使用 Jinja 的原因之一:将(GAE 生成的)登录/注销链接添加到 index.html 文件。除此之外,没有理由使用它。

【问题讨论】:

你把 index.html 放在哪里了?似乎您将 index.html 放在导致问题的 /app 中。 @marcadian:感谢您的指点。我确实将 index.html 放在 /app 中,但我认为这不是问题所在。如果您看到我编辑的问题,我让 Jinja 指向 /app 文件夹,然后请求它为 index.html 提供服务。我觉得问题更多在于静态文件配置。 【参考方案1】:

默认情况下,Python 无法访问在 App Engine 中标记为静态的文件或目录。您可以将application_readable: true 添加到您的处理程序映射以启用此功能。

另一种解决方案是将index.html 从静态文件夹中移开,因为它实际上不是静态文件,而是 Python 的 jinja 模板。

相关问题:Read a file on App Engine with Python? Documentation for application_readable

应用程序可读

可选。默认情况下,在静态文件处理程序中声明的文件作为静态数据上传,并且仅提供给最终用户,应用程序无法读取它们。如果此字段设置为 true,则文件也会作为代码数据上传,以便您的应用程序可以读取它们。两次上传都根据您的代码和静态数据存储资源配额收费。

【讨论】:

最后,静态数据与应用程序数据最终成为问题。我决定制作一个单独的静态文件夹。它不像我想要的那样干净,但它不会耗尽配额。【参考方案2】:

好的,它可能解释了场景 #2,您如何访问 index.html?如果您将 /app 添加到处理程序并且您的请求 url 类似于 /app/index.html 它将从静态目录提供服务。

在您的场景中,您的 url 似乎不包含 /app,因此它转到第二个处理程序规则,该规则将转到 main.app。

但是,由于您将 html 放在 /app 中,appengine 将其视为静态文件。如果你想从 jinja 模板提供文件,你不应该把它放在 static_dir 中

【讨论】:

请参阅第二次编辑。我尝试了这个建议,通过一个非常简短的测试,它似乎可以缓解 index.html 的情况。 “双重映射”是什么意思?移动 index.html 后遇到什么问题?你还没回答怎么访问index.html,映射到MainHandler的url handler是什么?【参考方案3】:

Jinja 模板(或 Django、Mako 等)不需要放在可公开访问的文件夹中。它们总是通过应用程序中的处理程序调用,并在提供给用户之前在应用程序中编译。

通常的做法是将它们放在 /templates 目录中。 app.yaml 中没有对该目录的引用,它纯粹在内部用于为模板提供服务。查看 github 中的一些样板应用程序(搜索“gae 样板”)。这个是最小的,使用 Jinja,所以可能是你的一个很好的例子https://github.com/SoulAuctioneer/notvanillae

【讨论】:

以上是关于Google App Engine 静态文件服务与应用程序冲突的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Google App Engine 上托管静态 HTML 文件?

要在 Google App Engine 上托管静态 (HTML) 网站,app.yaml 文件中应该包含啥内容?

在Google App Engine Standard中配置嵌套的静态文件夹 - PHP环境

Google App Engine 上的静态 mp4 视频

GWT与Google App Engine-上传文件

Google App Engine:如何使用相同的父目录创建静态和动态文件?例如dir / css&dir / python?