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 模板。
应用程序可读
可选。默认情况下,在静态文件处理程序中声明的文件作为静态数据上传,并且仅提供给最终用户,应用程序无法读取它们。如果此字段设置为 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:如何使用相同的父目录创建静态和动态文件?例如dir / css&dir / python?