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"
@lipis
Copy link

lipis commented Dec 31, 2013

For ttf I think it's better to use the application/x-font-ttf instead of font/truetype

https://github.com/h5bp/html5-boilerplate/blob/master/.htaccess#L148

@andlord
Copy link

andlord commented Feb 19, 2014

Thanks a lot !!!!!!! very helpful !!!!!

Copy link

ghost commented Jun 12, 2014

Very helpful ! .. but , images didnt work without mime types

instead of

  • url: /(..(bmp|gif|ico|jpeg|jpg|png))

    static_files: static/\1

    upload: static/(.
    .(bmp|gif|ico|jpeg|jpg|png))

i replaced with this .. It worked only after i added separate mime types like

  • url: /(..png)

    mime_type: image/png

    static_files: static/\1

    upload: static/(.
    .png)

can you let me know it didnt work regularly for me alone .. am using python 2.7

@noahwc
Copy link

noahwc commented Jun 29, 2014

Why are certain file types handled on their own (.txt) with mime types and others are handled together ((bmp|gif|ico|jpeg|jpg|png))

@louischan
Copy link

Mime type for svg should be image/svg+xml instead of images/svg+xml

@aweiand
Copy link

aweiand commented Jul 30, 2014

What I do for sending email with GAE?
Thanks.

@thekondrashov
Copy link

Here are the official MIME types for Web Fonts:

.eot -> application/vnd.ms-fontobject (as from December 2005) (gzip disabled)
.otf -> application/font-sfnt (as from March 2013) (gzip disabled)
.svg -> image/svg+xml (as from August 2011) (gzip enabled)
.ttf -> application/font-sfnt (as from March 2013) (gzip disabled, but GAE support ttf-fonts gzip with mime type "font/ttf")
.woff -> application/font-woff (as from January 2013) (already gzip compressed)

http://stackoverflow.com/questions/2871655/proper-mime-type-for-fonts#20723357

MIME types from MaxCDN (for example FontAwesome):
.eot -> application/vnd.ms-fontobject
.otf -> application/octet-stream
.svg -> image/svg+xml
.ttf -> font/ttf
.woff -> application/font-woff

/ sorry for my English /

@kumarjatin
Copy link

The order of url specifications is crucial! Make sure any other url handler rule doesn't interfere with your static handler rule and comes before that.

Like this works

- url: /static
  static_dir : static
- url: .*
  script: main.py
  secure: always

but this doesn't

- url: .*
  script: main.py
  secure: always
- url: /static
  static_dir : static

@jasonwbarnett
Copy link

Thank you very much... I can't tell you how awful their (Google App Engine) documentation is and this cleared things up.

@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