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

0 投票
3 回答
1223 浏览
提问于 2025-04-17 21:35

我有一个单页面应用(SPA),它运行在Google App Engine(GAE)上。GAE主要做三件事:

  1. 提供index.html文件
  2. 提供静态文件(比如JS、CSS等)
  3. 提供动态文件(比如图片、文本等,通过REST接口)

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

handlers:
- url: /app
  static_dir: app

- url: /.*
  script: main.app

我的理解是,这个配置应该能匹配到所有请求到/app文件夹的内容,从而提供我的静态文件。所有的REST服务和主index页面应该会被/.*捕获,然后由main.py处理。

但是,我遇到了以下情况:

  1. 如果我去掉/app处理器,我可以成功提供index.html(通过Jinja模板)和REST服务(比如localhost/subjects/)。但是,我看不到静态文件(这也是预期的结果)。
  2. 如果我添加/app处理器,index.html文件无法提供,并且出现“内部服务器错误” IOError(errno.EACCES, '文件不可访问', 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及其他文件

  • app

    • 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的一个原因是:在index.html文件中添加(GAE生成的)登录/登出链接。除此之外,使用它没有其他理由。

3 个回答

0

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

通常我们会把这些模板放在一个叫做 /templates 的文件夹里。这个文件夹在 app.yaml 文件中并没有被提到,它只是用来在内部提供模板的。你可以在 GitHub 上找一些基础的应用程序(搜索 'gae boilerplate')。这个链接是一个很简单的例子,使用了 Jinja,可能对你来说是个不错的参考 https://github.com/SoulAuctioneer/notvanillae

1

好的,这可能解释了第二种情况,你是怎么访问index.html的呢?如果你在处理程序中加上/app,然后你的请求网址是/app/index.html,这样就会从静态文件夹中提供这个文件。

在你的情况中,似乎你的网址没有包含/app,因此它就会走到第二个处理规则,也就是main.app。

不过,因为你把html文件放在了/app里面,appengine会把它当作静态文件来处理。如果你想通过jinja模板来提供这个文件,就不应该把它放在静态文件夹里。

3

在默认情况下,Python无法访问在App Engine中标记为静态的文件或文件夹。你可以在你的处理程序映射中添加application_readable: true来解决这个问题,让Python可以访问这些文件。

另一种解决办法是把index.html文件移出静态文件夹,因为它实际上并不是一个静态文件,而是一个Python用的jinja模板。

application_readable

这是一个可选项。默认情况下,标记为静态文件的文件会被当作静态数据上传,只能提供给最终用户,应用程序无法读取这些文件。如果将这个选项设置为true,这些文件也会被当作代码数据上传,这样你的应用程序就可以读取它们。两种上传都会计入你的代码和静态数据存储资源配额。

撰写回答