Skip to content

Instantly share code, notes, and snippets.

@darktable
Created March 16, 2011 19:10
Show Gist options
  • Save darktable/873098 to your computer and use it in GitHub Desktop.
Save darktable/873098 to your computer and use it in GitHub Desktop.
GAE: App.yaml designed for serving a static site on Google App Engine (Python). Copy your static html and files into a folder called "static" next to app.yaml. Contains a bunch of mimetype declarations from html5boilerplate's .htaccess. May not be neces

App.yaml designed for serving a static site on Google App Engine (Python). Copy your static html and files into a folder called "static" next to app.yaml. Contains a bunch of mimetype declarations from html5boilerplate's .htaccess. May not be necessary for most situations.

my_site
  app.yaml
  static
    index.html
    ...

The static folder is invisible when serving (i.e. my_site/static/index.html is accessed as http://your-app-name-here.appspot.com/index.html.

Remember: No spaces in file or path names. Case sensitive.

application: you-app-name-here
version: 1
runtime: python
api_version: 1
default_expiration: "30d"
handlers:
- url: /(.*\.(appcache|manifest))
mime_type: text/cache-manifest
static_files: static/\1
upload: static/(.*\.(appcache|manifest))
expiration: "0m"
- url: /(.*\.atom)
mime_type: application/atom+xml
static_files: static/\1
upload: static/(.*\.atom)
expiration: "1h"
- url: /(.*\.crx)
mime_type: application/x-chrome-extension
static_files: static/\1
upload: static/(.*\.crx)
- url: /(.*\.css)
mime_type: text/css
static_files: static/\1
upload: static/(.*\.css)
- url: /(.*\.eot)
mime_type: application/vnd.ms-fontobject
static_files: static/\1
upload: static/(.*\.eot)
- url: /(.*\.htc)
mime_type: text/x-component
static_files: static/\1
upload: static/(.*\.htc)
- url: /(.*\.html)
mime_type: text/html
static_files: static/\1
upload: static/(.*\.html)
expiration: "1h"
- url: /(.*\.ico)
mime_type: image/x-icon
static_files: static/\1
upload: static/(.*\.ico)
expiration: "7d"
- url: /(.*\.js)
mime_type: text/javascript
static_files: static/\1
upload: static/(.*\.js)
- url: /(.*\.json)
mime_type: application/json
static_files: static/\1
upload: static/(.*\.json)
expiration: "1h"
- url: /(.*\.m4v)
mime_type: video/m4v
static_files: static/\1
upload: static/(.*\.m4v)
- url: /(.*\.mp4)
mime_type: video/mp4
static_files: static/\1
upload: static/(.*\.mp4)
- url: /(.*\.(ogg|oga))
mime_type: audio/ogg
static_files: static/\1
upload: static/(.*\.(ogg|oga))
- url: /(.*\.ogv)
mime_type: video/ogg
static_files: static/\1
upload: static/(.*\.ogv)
- url: /(.*\.otf)
mime_type: font/opentype
static_files: static/\1
upload: static/(.*\.otf)
- url: /(.*\.rss)
mime_type: application/rss+xml
static_files: static/\1
upload: static/(.*\.rss)
expiration: "1h"
- url: /(.*\.safariextz)
mime_type: application/octet-stream
static_files: static/\1
upload: static/(.*\.safariextz)
- url: /(.*\.(svg|svgz))
mime_type: images/svg+xml
static_files: static/\1
upload: static/(.*\.(svg|svgz))
- url: /(.*\.swf)
mime_type: application/x-shockwave-flash
static_files: static/\1
upload: static/(.*\.swf)
- url: /(.*\.ttf)
mime_type: font/truetype
static_files: static/\1
upload: static/(.*\.ttf)
- url: /(.*\.txt)
mime_type: text/plain
static_files: static/\1
upload: static/(.*\.txt)
- url: /(.*\.unity3d)
mime_type: application/vnd.unity
static_files: static/\1
upload: static/(.*\.unity3d)
- url: /(.*\.webm)
mime_type: video/webm
static_files: static/\1
upload: static/(.*\.webm)
- url: /(.*\.webp)
mime_type: image/webp
static_files: static/\1
upload: static/(.*\.webp)
- url: /(.*\.woff)
mime_type: application/x-font-woff
static_files: static/\1
upload: static/(.*\.woff)
- url: /(.*\.xml)
mime_type: application/xml
static_files: static/\1
upload: static/(.*\.xml)
expiration: "1h"
- url: /(.*\.xpi)
mime_type: application/x-xpinstall
static_files: static/\1
upload: static/(.*\.xpi)
# image files
- url: /(.*\.(bmp|gif|ico|jpeg|jpg|png))
static_files: static/\1
upload: static/(.*\.(bmp|gif|ico|jpeg|jpg|png))
# audio files
- url: /(.*\.(mid|midi|mp3|wav))
static_files: static/\1
upload: static/(.*\.(mid|midi|mp3|wav))
# windows files
- url: /(.*\.(doc|exe|ppt|rtf|xls))
static_files: static/\1
upload: static/(.*\.(doc|exe|ppt|rtf|xls))
# compressed files
- url: /(.*\.(bz2|gz|rar|tar|tgz|zip))
static_files: static/\1
upload: static/(.*\.(bz2|gz|rar|tar|tgz|zip))
# index files
- url: /(.+)/
static_files: static/\1/index.html
upload: static/(.+)/index.html
expiration: "15m"
- url: /(.+)
static_files: static/\1/index.html
upload: static/(.+)/index.html
expiration: "15m"
# site root
- url: /
static_files: static/index.html
upload: static/index.html
expiration: "15m"
@MaxLaumeister
Copy link

In the config, the svg directive has an incorrect mime_type. Here is the current version:

- url: /(.*\.(svg|svgz))
  mime_type: images/svg+xml
  static_files: static/\1
  upload: static/(.*\.(svg|svgz))

Here is what it needs to be:

- url: /(.*\.(svg|svgz))
  mime_type: image/svg+xml
  static_files: static/\1
  upload: static/(.*\.(svg|svgz))

Was running into an issue where SVGs weren't loading in my pages! Otherwise, thank you for this gist, it's been very helpful for hosting static files on app engine.

@pallavJha
Copy link

Hi, I have created a webapp using java and there are three app.yaml files in my target folder, so which one do I have to edit?
pkjustpj@tempinitial:~/ImgUploadImg/webapp/target$ tree
.
+-- appengine-staging
¦ +-- app.yaml
¦ +-- index.jsp
¦ +-- static
¦ ¦ +-- static-resources
¦ ¦ ...
¦ +-- static-resources
¦ ¦ ...
¦ +-- WEB-INF
¦ +-- appengine-generated
¦ ¦ +-- app.yaml
¦ +-- appengine-web.xml
¦ +-- classes
¦ ¦ +-- jetty-config.xml
¦ ¦ +-- logback.xml
¦ ¦ +-- spring-config
¦ ¦ +-- spring-context.xml
¦ +-- layouts
¦ ¦ +-- layout.xml
¦ +-- lib
¦ ¦ ...
¦ +-- web.xml
+-- classes
¦ +-- jetty-config.xml
¦ +-- logback.xml
¦ +-- pl
¦ ¦ ...
¦ +-- property-files
¦ ¦ +-- config-info.properties
¦ +-- spring-config
¦ +-- spring-context.xml
+-- generated-sources
¦ +-- annotations
+-- maven-archiver
¦ +-- pom.properties
+-- webapp
¦ +-- app.yaml
¦ +-- index.jsp
¦ +-- META-INF
¦ +-- static-resources
¦ ¦ ...
¦ +-- WEB-INF
¦ ...
+-- webapp.war

Also, my main problem is 404 on all other files(like .css .png. .js .ico) which are present in the static-resources which is a sibling of WEB-INF folder. I have also put on a question on stack-overflow. Kindly help me out. Thanks

http://stackoverflow.com/questions/35356212/404-for-all-the-files-residing-in-static-resources?noredirect=1#comment58501122_35356212

@Forfeit
Copy link

Forfeit commented Mar 25, 2016

I just deployed a website for testing on Google Appengine. Using google App Engine Launcher Its successfully done.

Now I tried to open the deployed website, please check here https://acuteservice-1260.appspot.com the internal pages are not opening.

Below is my APP YAML file its showing warning, I have all files are in php

application: acuteservice-1260
version: 1
runtime: python
api_version: 1

default_expiration: "30d"

handlers:

  • url: /(..(appcache|manifest))
    mime_type: text/cache-manifest
    static_files: static/\1
    upload: static/(.
    .(appcache|manifest))
    expiration: "0m"
  • url: /(..atom)
    mime_type: application/atom+xml
    static_files: static/\1
    upload: static/(.
    .atom)
    expiration: "1h"
  • url: /(..crx)
    mime_type: application/x-chrome-extension
    static_files: static/\1
    upload: static/(.
    .crx)
  • url: /(..css)
    mime_type: text/css
    static_files: static/\1
    upload: static/(.
    .css)
  • url: /(..eot)
    mime_type: application/vnd.ms-fontobject
    static_files: static/\1
    upload: static/(.
    .eot)
  • url: /(..htc)
    mime_type: text/x-component
    static_files: static/\1
    upload: static/(.
    .htc)
  • url: /(..php)
    mime_type: text/html
    static_files: static/\1
    upload: static/(.
    .php)
    expiration: "1h"
  • url: /(..ico)
    mime_type: image/x-icon
    static_files: static/\1
    upload: static/(.
    .ico)
    expiration: "7d"
  • url: /(..js)
    mime_type: text/javascript
    static_files: static/\1
    upload: static/(.
    .js)
  • url: /(..json)
    mime_type: application/json
    static_files: static/\1
    upload: static/(.
    .json)
    expiration: "1h"
  • url: /(..m4v)
    mime_type: video/m4v
    static_files: static/\1
    upload: static/(.
    .m4v)
  • url: /(..mp4)
    mime_type: video/mp4
    static_files: static/\1
    upload: static/(.
    .mp4)
  • url: /(..(ogg|oga))
    mime_type: audio/ogg
    static_files: static/\1
    upload: static/(.
    .(ogg|oga))
  • url: /(..ogv)
    mime_type: video/ogg
    static_files: static/\1
    upload: static/(.
    .ogv)
  • url: /(..otf)
    mime_type: font/opentype
    static_files: static/\1
    upload: static/(.
    .otf)
  • url: /(..rss)
    mime_type: application/rss+xml
    static_files: static/\1
    upload: static/(.
    .rss)
    expiration: "1h"
  • url: /(..safariextz)
    mime_type: application/octet-stream
    static_files: static/\1
    upload: static/(.
    .safariextz)
  • url: /(..(svg|svgz))
    mime_type: images/svg+xml
    static_files: static/\1
    upload: static/(.
    .(svg|svgz))
  • url: /(..swf)
    mime_type: application/x-shockwave-flash
    static_files: static/\1
    upload: static/(.
    .swf)
  • url: /(..ttf)
    mime_type: font/truetype
    static_files: static/\1
    upload: static/(.
    .ttf)
  • url: /(..txt)
    mime_type: text/plain
    static_files: static/\1
    upload: static/(.
    .txt)
  • url: /(..unity3d)
    mime_type: application/vnd.unity
    static_files: static/\1
    upload: static/(.
    .unity3d)
  • url: /(..webm)
    mime_type: video/webm
    static_files: static/\1
    upload: static/(.
    .webm)
  • url: /(..webp)
    mime_type: image/webp
    static_files: static/\1
    upload: static/(.
    .webp)
  • url: /(..woff)
    mime_type: application/x-font-woff
    static_files: static/\1
    upload: static/(.
    .woff)
  • url: /(..xml)
    mime_type: application/xml
    static_files: static/\1
    upload: static/(.
    .xml)
    expiration: "1h"
  • url: /(..xpi)
    mime_type: application/x-xpinstall
    static_files: static/\1
    upload: static/(.
    .xpi)

image files

  • url: /(..(bmp|gif|ico|jpeg|jpg|png))
    static_files: static/\1
    upload: static/(.
    .(bmp|gif|ico|jpeg|jpg|png))

audio files

  • url: /(..(mid|midi|mp3|wav))
    static_files: static/\1
    upload: static/(.
    .(mid|midi|mp3|wav))

windows files

  • url: /(..(doc|exe|ppt|rtf|xls))
    static_files: static/\1
    upload: static/(.
    .(doc|exe|ppt|rtf|xls))

compressed files

  • url: /(..(bz2|gz|rar|tar|tgz|zip))
    static_files: static/\1
    upload: static/(.
    .(bz2|gz|rar|tar|tgz|zip))

index files

  • url: /(.+)/
    static_files: static/\1/index.php
    upload: static/(.+)/index.php
    expiration: "15m"
  • url: /(.+)
    static_files: static/\1/index.php
    upload: static/(.+)/index.php
    expiration: "15m"

site root

  • url: /
    static_files: static/index.php
    upload: static/index.php
    expiration: "15m"
  • url: .*
    script: index.php

@SoulAuctioneer
Copy link

SoulAuctioneer commented Apr 13, 2017

So why would you do all of that rather than simply:

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

?

Copy link

ghost commented Jul 13, 2017

@SoulAuctioneer I found that adding each mime type allowed by backend api hosted in the same space to function You're blanket .* block would prevent my api from working.
I actually found this document very very helpful in getting my static files as well as my backend Google api working at the same time.

@hodoje
Copy link

hodoje commented Sep 2, 2017

Is this still valid? I'm creating a DjangoREST API as backend and Angular4 as frontend. I've put all my static files from 'dist' folder I've got in my Angular app to a folder named 'static' which is in my app folder, not in level with manage.py (because it doesn't work 100%).

@chrisajedmonds
Copy link

This didn't work for me.

The sequence of my handlers seems to dictate a choice between the CSS/JS/Other working and the removal of .html from the URL. I can't have both, it seems.

@littlej247
Copy link

understanding the syntax I found made the biggest difference. You can see the descriptions
here

I don't touch my .yaml file often so I posted this at the top for when I do:

#  Note to self, syntax can be found here:
#  https://en.wikipedia.org/wiki/Regular_expression#Syntax

#  () defines a value to be saved in memory, \1 calles that value in order. ie: \1 \2
#  + will join strings but the values must match on either side
#  . Matches any single character
#  \ will 'excape' a charrictor. So the \. makes the period mean a period

@cosmith
Copy link

cosmith commented Dec 31, 2019

Simpler app.yaml

runtime: python37
service: static-website

handlers:
# index files
- url: /([^.]+)/?$  # urls with no dot in them
  static_files: public/\1/index.html
  upload: public/(.+)/index.html
  expiration: "15m"

# site root
- url: /
  static_files: public/index.html
  upload: public/index.html
  expiration: "15m"

# everything else
- url: /(.*)
  static_files: public/\1
  upload: public/(.*)

@bargar
Copy link

bargar commented Jan 4, 2020

Simpler app.yaml
...

Works great for my Gatsby site.

Thanks, @cosmith!

@jaunt
Copy link

jaunt commented Jun 11, 2020

@cosmith:

I'm no regex expert, but when I use your regex for "urls with no dot in them", it doesn't quite work for these:

/a/b/c

and

/a/b/c/

Here is the only solution that worked for me (escaped your final trailing slash, and made the group capture non-greedy).

  • url: /([^.]+?)/?$ # urls with no dot in them

@cosmith
Copy link

cosmith commented Jun 12, 2020

@jaunt you're right my url structure is only a single level deep

@Dipesh-Das97
Copy link

Dipesh-Das97 commented Aug 6, 2021

Hi, how would I reference a public file from the public/shared-json/blacklist.json in app.yaml?
The repo structure is:

  • public:
    - shared-json:
    - black-list.json
  • server :
    - app.yaml
    Below is how my app.yaml looks for handler section
    image

Is there a way to change the path in the static_dir option?

@JacobStenson1
Copy link

Thanks for this. Was just what I needed 👌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment