JoeSchr
JoeSchr

Reputation: 1157

APP.YAML: Combine different URLs-same file, static file serving & source code access in app.yaml

I now there are a lot of questions about app.yaml, and I searched and searched, but this one I couldn't find.

TLDR: PLEASE read full answer first, this isn't your standard application_readable:true. I basically want to access the same file via different routes e.g. /static/img/pic.jpg AND /img/pic.jpg

USE CASE

I build a flask application (upon the work of fsouza ) and i try to build a thumbnail extension for flask which will work on gae (because it's a read-only FS, I forked flask-thumbnails and currently try to expand it.)

So I need:

What's not working:

It's working locally, won't work after deploying. I thinks app.yaml is not so strictly enforced by dev_appserver.py as it should.

I can either get one of this scenarios to work. This is how my app.yaml currently looks:

builtins:
- appstats: on
- admin_redirect: on
- deferred: on
- remote_api: on

- url: /css
  static_dir: application/static/css 

- url: /js
  static_dir: application/static/js 

- url: /img
  static_dir: application/static/img

- url: /static
  static_dir: application/static
  application_readable: true

- url: .*
  script: run.application.app

I also tried this instead:

- url: /css/(.*)
  static_files: css/\1
  upload: css/(.*) 

- url: /js/(.*)
  static_files: js/\1
  upload: js/(.*) 

- url: /img/(.*)
  static_files: img/\1
  upload: img/(.*) 

When I comment the specific js,css,img stuff out, the application can access the img in application/static/img and make a thumbnail out of it. But the urls with e.g. /img/dont.need.thumbnail.jpg won't be served.

When I comment this part:

- url: /static
  static_dir: application/static
  application_readable: true

img,css,js get served like they should.

Can anybody help me? What I'm doing wrong?

Are app.yaml urls recursive?

Current Workaround:

My current workaround is, that I simply add several url route through in python application. But that is not efficient and I suspect it costs me more CPU time and is slower. e.g.

app.add_url_rule('/img/<path>', 'static_img_files', view_func=views.static_img_files)
def static_img_files(path):
    return static_files("img/"+path)

Bonus hint:

If you just git push-to-deploy

application_readable: true

won't work, so the python application won't have access to the static images as soon as you test it on the gae servers and not locally anymore. you have to deploy it via the app engine launcher (this alone took me ages to find out)

Upvotes: 1

Views: 1483

Answers (2)

JoeSchr
JoeSchr

Reputation: 1157

The answer is oh so simple: make every access path application_readable, because negative permissions are stronger than positive ones.

- url: /img
  static_dir: application/static/img
  application_readable: true           # <---- !!!!!

- url: /static
  static_dir: application/static
  application_readable: true

So kind of eat my own words, it is a simple case of application_readable:true :)

Upvotes: 1

Dave W. Smith
Dave W. Smith

Reputation: 24966

The answer you're looking for is in the Static directory handlers section of the Configuring with app.yaml doc.

Look for application_readable. Setting that attribute to true gives you the best of both worlds, at the expense of quota (since static files marked this way need to be uploaded to two different places).

Updated with a working example

I've stripped this down to the essentials.

app.yaml

application: example
version: 1
runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /dir1
  static_dir: dir1
  mime_type: text/plain

- url: /dir2
  static_dir: dir2
  mime_type: text/plain
  application_readable: true

- url: .*
  script: main.app

main.py

import webapp2

class Test(webapp2.RequestHandler):
  def get(self):
    self.response.headers['Content-Type'] = 'text/plain'
    for path in ['dir1/file1.txt', 'dir2/file2.txt']:
      try:
        with open(path) as f:
          self.response.out.write(f.read())
      except IOError:
        pass

app = webapp2.WSGIApplication([(r'/', Test)])

dir1/file1.txt

Content1

dir2/file2.txt

Content2

You should be able to navigate to /dir1/file1.txt and dir2/file2.txt and see their contents, but navigating to / sees only the latter file. I went with text files instead of images for simplicity of example; that detail should't matter.

(I'm using GAE SDK 1.9.17 on Linux)

Upvotes: 0

Related Questions