python - Google App Engine: Correctly configuring a static site with advanced routing -


i've spent several shameful hours trying solve no avail...

problem:

i have static website developing 100% pre-processed via grunt & assemble (if familiar jekyll, same concept). has simple static blog component houses category directories of various names. such, need catch-all in app.yaml route them appropriately.

however, also have custom error page show in place of standard gae page status.

it seems cannot accomplish accounting both scenarios in app.yaml alone because can use catch-all target once.

here logic in current app.yaml

- url: (.*)/   static_files: dist\1/index.html   upload: dist/index.html   expiration: "15m"  - url: /(.*)   static_files: dist/\1/index.html   upload: dist/(.*)/index.html   expiration: "15m" 

this perfect use case because routes path index file if exists in current directory. however, because uses catch-all, cannot again use following

- url: /(.*)   static_files: custom_error.html 

or depend on

error_handlers:   - file: custom_error.html 

because renders paths no matching url pattern...

ideas:

my next thoughts may able accomplish advanced routing via external python script

- url: /.*   script: main.app 

but after trying myriad of various setups have yet stumble onto way accomplish this.

one example of trail of breadcrumbs on be

import os import webapp2 import jinja2  # vars jinja_environment = jinja2.environment(loader=jinja2.filesystemloader('jinja'), extensions=['jinja2.ext.autoescape'], autoescape=true)  class mainhandler(webapp2.requesthandler):     def get(self):         if (an-index-file-exists-in-this-directory)             # follow same static file logic app.yaml             # static_files: dist/\1/index.html             # upload: dist/(.*)/index.html         else:             template = jinja_environment.get_template('404/index.html')             context =  {                 'page_title': '404',             }             self.response.out.write(template.render(context))             self.error(404)  app = webapp2.wsgiapplication([     ('/.*', mainhandler) ], debug=false) 

i'm not sure if taking external python file solve issue or not, awkward stab @ it.

does have ideas on how can achieve custom error pages when catch-all pattern being used important purpose?

update: solved

ok have figured out, because stack overflow thinks i'm not cool enough answer own question (low point threshold?), i've posted solution here:

https://gist.github.com/dustintheweb/c5e6e4ee1a64d50d7f87

good luck!

as @anthuin's answer points out, can't write (nor modify) index.html files on disk (nor create new ones dynamically), makes little sense try read them disk -- "disk" available gae apps read-only (and split between part available static serving, , part readable app code itself).

rather, unless index.html files huge (unlikely, suspect), i'd keep them in gae datastore app. simple model:

from google.appengine.ext import ndb  class indx(ndb.model):     body = ndb.textproperty() 

assuming path no longer 500 characters , body megabyte. then, mainhandler becomes pretty simple:

class mainhandler(webapp2.requesthandler):      def get(self):         key = ndb.key('indx', self.request.path)         ent = key.get()         if ent:             self.response.write(ent.body)         else:             # existing 404-returning code goes here 

the app.yaml routing /.* script, , app = code, need no change.

now, thing remains is, how did expect write, or modify, these index.html files (now datastore entities)? have no idea because long were files app couldn't possibly have written nor modified them. in case, they're in data store, writing becomes simple:

def write_indx(path, body):     ent = indx(body=body, id=path)     ent.put() 

note there no real "modify" -- possibly "modify" index.html's "body", you'll read previous one, make new body string, , rewrite entity above write_indx.

potential problems include: bodies of more 1 mb; and, keys (paths) of more 500 characters. former can worked around using, @anhuin suggested, google cloud storage instead of gae datastore; latter may perhaps problem because gcs object names have limits (differently gcs object lengths) -- specifically, 1024 bytes once name converted utf-8. either of these issues problem you? if so, let know!


Comments

Popular posts from this blog

tcpdump - How to check if server received packet (acknowledged) -