0

I have a single page app (SPA) that I am running off of Google App Engine (GAE). GAE does three things:

  1. Serve the index.html file
  2. Serve the static files (JS, CSS, etc.)
  3. Serve the dynamic files (images, text, etc. via REST)

I use the following app.yaml configuration.

handlers:
- url: /app
  static_dir: app

- url: /.*
  script: main.app

My understanding is that this should match any requests going to the /app folder, which would serve my static files. All the REST services and the main index page would then be caught by the /.* and processed by main.py

However, I see the following behavior:

  1. If I remove the /app handler, I can successfully serve the index.html (via Jinja templating) and the REST services (such as localhost/subjects/). However, I cannot see the static files (as expected).
  2. If I add the /app handler, the index.html file does not serve and gives an "Internal Server Error" IOError(errno.EACCES, 'file not accessible', filename). However, when I request a static file such as: "localhost/app/app.js", this succeeds.

Is there something that I am missing here? I do not understand why the two would conflict.

Thank you!

Notes: Google App Engine 1.8.9, Python 2.7, Developing locally

EDIT:

Here is the Python code I am using to serve the page

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))

My directory structure is as follows:

/

  • main.py

  • app.yaml & etc.

  • app

    • index.html

    • app.js

    • Module A

    • moduleA.tpl.html

    • moduleA.js

Edit 2:

I moved index.html to the root directory (/), and then used the following python code:

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

It (very interestingly) appears that the "double mapping" of the index.html to the Jinja template and to the static directory files caused a problem. I wonder what is the best practice way to do this. I use Jinja for one reason: adding the (GAE generated) login/logout link to the index.html file. Other than that, there is no reason for using it.

Diode Dan
  • 4,801
  • 6
  • 25
  • 34
  • 1
    Where do you put the index.html? Seems you put the index.html in the /app which cause the issue. – marcadian Mar 10 '14 at 08:48
  • @marcadian: Thanks for the pointer. I do put index.html in /app, but I don't think that's the problem. If you see my edited question, I have Jinja point to the /app folder, and then request that it serves index.html. I get the feeling that the issue is more with the static file configuration. – Diode Dan Mar 10 '14 at 13:09

3 Answers3

3

Python is by default unable to access files or directories marked as static in App Engine. You can add application_readable: true to your handler mapping to enable this.

Another solution would be to move the index.html away from the static folder since it in fact isn't a static file but instead is a jinja template for Python.

application_readable

Optional. By default, files declared in static file handlers are uploaded as static data and are only served to end users, they cannot be read by an application. If this field is set to true, the files are also uploaded as code data so your application can read them. Both uploads are charged against your code and static data storage resource quotas.

Community
  • 1
  • 1
Robin Andersson
  • 5,150
  • 3
  • 25
  • 44
  • In the end, the static vs. application data ended up being the problem. I decided to make a separate static folder. It is not as clean as I would like, but it does not eat up quota. – Diode Dan Apr 16 '14 at 05:23
1

Ok it might explains scenario #2, how do you access the index.html? If you add /app to the handler and your request url is something like /app/index.html it will serve from the static dir.

On your scenario seems your url does not contain /app, therefore it goes to the 2nd handler rule which is going to main.app.

However since you put the html inside the /app, appengine treats it as static file. If you want to serve the file from jinja template, you should not put it in static_dir

marcadian
  • 2,608
  • 13
  • 20
  • Please see the second edit. I tried this suggestion, and from a very brief test, it appears to alleviate the index.html situation. – Diode Dan Mar 11 '14 at 02:14
  • What do you mean by "double mapping"? What problems are you encounter after move the index.html? You haven't answered how do you access the index.html, what is the url handler mapped to MainHandler? – marcadian Mar 11 '14 at 05:17
0

Jinja templates (or Django, Mako etc) has no requirement to be sat in a publicly accessible folder. They are always called via a handler in the application and compiled in the application before serving to the user.

It is common practice to put these in a /templates directory. There is no reference to this directory in app.yaml, it is purely used internally to serve the templates. Check out some of the boilerplate apps in github (search 'gae boilerplate'). This one is minimal and uses Jinja so may be a good example for you https://github.com/SoulAuctioneer/notvanillae

Ron Chan
  • 3,315
  • 5
  • 27
  • 31