Skip to content

Instantly share code, notes, and snippets.

@jonobr1
Created August 15, 2022 17:29
Show Gist options
  • Save jonobr1/a971655d122109c1e6af0981feec3758 to your computer and use it in GitHub Desktop.
Save jonobr1/a971655d122109c1e6af0981feec3758 to your computer and use it in GitHub Desktop.
runtime: python37
service: default
handlers:
- url: /api/upload.*
script: auto
secure: always
# login: admin
- url: /(.*\.(gif|png|jpg|jpeg|ico|css|map|json|js|eot|svg|ttf|woff|woff2|ogg|mp3|wav|ogg|mp4|webm|xml|html|fbx|gltf))$
static_files: public/\1
upload: .*\.(gif|png|jpg|jpeg|ico|css|map|json|js|eot|svg|ttf|woff|woff2|ogg|mp3|wav|ogg|mp4|webm|xml|html|fbx|gltf)$
- url: /api/post.*
script: auto
secure: always
# login: admin
- url: /api/get.*
script: auto
secure: always
- url: /.*
static_files: index.html
upload: index.html
secure: always
from flask import Flask, request, redirect
from flask_cors import CORS
from google.cloud import datastore
from google.cloud import storage
CLOUD_STORAGE_BUCKET = 'YOUR-CLOUD-STORAGE-BUCKET-ID'
IMAGE_EXTENSIONS = { 'png', 'jpg', 'jpeg', 'gif' }
ds = datastore.Client()
cs = storage.Client()
bucket = cs.bucket(CLOUD_STORAGE_BUCKET)
def allowed(filename: str):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in IMAGE_EXTENSIONS
def upload(src: str, contents):
blob = bucket.blob(src)
blob.upload_from_string(contents)
return { 'src': 'https://storage.googleapis.com/{}/{}'.format(CLOUD_STORAGE_BUCKET, src) }
def save(id: str, model):
key = ds.key('model', id)
entity = datastore.Entity(key)
entity.update({ 'body': model })
ds.put(entity)
return { 'id': id }
def get(id: str):
key = ds.key('model', id)
entity = ds.get(key)
if entity is None:
return { 'error': 'API Error: no model found for key: {}'.format(id) }
else:
return entity.get('body', {})
#
app = Flask(__name__)
CORS(app)
#
@app.route('/api/get/<id>', methods=['GET'])
def on_get(id=None):
if not isinstance(id, str):
return { 'error': 'API Error: key does not exist.' }
else:
return get(id)
@app.route('/api/post/<id>', methods=['POST'])
def on_post(id=None):
if isinstance(id, str) and request.method == 'POST':
body = request.get_json()
if body is None:
return { 'error': 'API Error: body does not exist.' }
else:
return save(id, body)
else:
return { 'error': 'API Error: post not configured correctly.' }
@app.route('/api/upload/<src>', methods=['POST'])
def on_upload(src=None):
if isinstance(src, str) and request.method == 'POST':
if 'file' not in request.files:
return { 'error': 'API Error: file does not exist.' }
else:
file = request.files['file']
if file.filename == '':
return { 'error': 'API Error: no file selected.' }
if file and allowed(file.filename):
filename = 'assets/{}'.format(src)
contents = file.read()
return upload(filename, contents)
else:
return { 'error': 'API Error: filetype not permitted.' }
else:
return { 'error': 'API Error: upload not configured correctly.' }
if __name__ == '__main__':
# This is used when running locally only. When deploying to Google App
# Engine, a webserver process such as Gunicorn will serve the app. You
# can configure startup instructions by adding `entrypoint` to app.yaml.
app.run(host='127.0.0.1', port=3000, debug=True)
Flask==2.0.2
flask-cors==3.0.10
google-cloud-datastore
google-cloud-storage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment