Skip to content

Instantly share code, notes, and snippets.

@dskecse
Forked from akiray03/.gcloudignore
Created January 14, 2026 10:08
Show Gist options
  • Select an option

  • Save dskecse/56db659bfefaa27820f9a2fb88bfe9bb to your computer and use it in GitHub Desktop.

Select an option

Save dskecse/56db659bfefaa27820f9a2fb88bfe9bb to your computer and use it in GitHub Desktop.
# This file specifies files that are *not* uploaded to Google Cloud Platform
# using gcloud. It follows the same syntax as .gitignore, with the addition of
# "#!include" directives (which insert the entries of the given .gitignore-style
# file at that point).
#
# For more information, run:
# $ gcloud topic gcloudignore
#
.gcloudignore
# If you would like to upload your .git directory, .gitignore file or files
# from your .gitignore file, remove the corresponding line
# below:
.git
.gitignore
# Python pycache:
__pycache__/
# Ignored by the build system
/setup.cfg
.venv
runtime: python37
service: default
import flask
import logging
import sys
import datetime
import base64
import google.auth.transport.requests
from google.auth import compute_engine
from google.auth.iam import Signer
from gumo.core import configure as core_configure
from gumo.core import get_google_oauth_credential
from gumo.storage.infrastructure import build_signed_url
from gumo.storage.infrastructure import SignedURLFactory
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logger = logging.getLogger(__name__)
app = flask.Flask(__name__)
core_configure(
google_cloud_project='levii-playground-signed-url',
google_cloud_location='us-central1',
)
class AppEngineCredentials:
_credentials = None
@classmethod
def fetch(cls):
if cls._credentials is None:
cls._credentials = compute_engine.Credentials()
if not cls._credentials.valid or cls._credentials.service_account_email is None:
request = google.auth.transport.requests.Request()
cls._credentials.refresh(request=request)
logger.debug(f'credential refreshed.')
return cls._credentials
@app.route('/')
def hello():
return 'Hello'
def storage_signed_url(bucket_name: str, blob_path: str):
credentials = AppEngineCredentials.fetch()
request = google.auth.transport.requests.Request()
signer = Signer(
request=request,
credentials=credentials,
service_account_email=credentials.service_account_email
)
signer_email = credentials.service_account_email
http_verb = 'GET'
md5_digest = ''
content_type = ''
expiration = int((datetime.datetime.utcnow() + datetime.timedelta(days=1)).timestamp())
blob_path = blob_path if blob_path.startswith('/') else f'/{blob_path}'
sign_info = [
http_verb,
md5_digest,
content_type,
str(expiration),
f'/{bucket_name}{blob_path}'
]
string_to_sign = '\n'.join(sign_info)
signature = signer.sign(string_to_sign.encode('ascii'))
encoded_signature = base64.b64encode(signature).decode('ascii')
escaped_signature = encoded_signature.replace('+', '%2B').replace('/', '%2F')
base_url = f'https://storage.googleapis.com/{bucket_name}{blob_path}'
params = '&'.join([
f'GoogleAccessId={signer_email}',
f'Expires={expiration}',
f'Signature={escaped_signature}',
])
return f'{base_url}?{params}'
class ModifiedSignedURLFactory(SignedURLFactory):
@classmethod
def get_credential(cls):
if cls._credential is None:
cls._credential = get_google_oauth_credential()
if not cls._credential.valid or cls._credential.service_account_email is None:
request = google.auth.transport.requests.Request()
cls._credential.refresh(request=request)
return cls._credential
def modified_build_signed_url(
bucket_name: str,
blob_path: str,
http_verb: str = 'GET',
md5_digest: str = '',
content_type: str = '',
expiration_seconds: int = 3600,
):
return ModifiedSignedURLFactory(
bucket_name=bucket_name,
blob_path=blob_path,
http_verb=http_verb,
md5_digest=md5_digest,
content_type=content_type,
expiration_seconds=expiration_seconds,
).build()
@app.route('/storage-signed-url')
def signed_url():
mode = flask.request.args.get('mode', 'google')
if mode == 'google':
signed_url = storage_signed_url(
bucket_name='levii-playground-signed-url',
blob_path='testfile.txt'
)
elif mode == 'gumo':
signed_url = build_signed_url(
bucket_name='levii-playground-signed-url',
blob_path='testfile.txt'
)
elif mode == 'gumo-modified':
signed_url = modified_build_signed_url(
bucket_name='levii-playground-signed-url',
blob_path='testfile.txt'
)
else:
raise RuntimeError(f'Invalid parameters (mode={mode})')
if 'bench' in flask.request.args:
return 'ok'
else:
return signed_url
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080, debug=True)
.PHONY: help
help:
@echo "[Usage] available sub commands:"
@echo " * make deploy ... deploy to google app engine"
.PHONY: deploy
deploy:
gcloud app deploy app.yaml --project=levii-playground-signed-url --quiet
google-cloud-storage
flask
requests
gumo-storage
#
# This file is autogenerated by pip-compile
# To update, run:
#
# pip-compile --output-file=requirements.txt requirements.in
#
cachetools==3.1.1 # via google-auth
certifi==2019.3.9 # via requests
chardet==3.0.4 # via requests
click==7.0 # via flask
flask==1.0.3
google-api-core==1.11.1 # via google-cloud-core
google-api-python-client==1.7.9 # via gumo-core
google-auth-httplib2==0.0.3 # via google-api-python-client
google-auth==1.6.3 # via google-api-core, google-api-python-client, google-auth-httplib2, google-cloud-storage
google-cloud-core==1.0.1 # via google-cloud-storage
google-cloud-storage==1.16.1
google-resumable-media==0.3.2 # via google-cloud-storage
googleapis-common-protos==1.6.0 # via google-api-core
gumo-core==0.0.30 # via gumo-storage
gumo-storage==0.0.5
httplib2==0.13.0 # via google-api-python-client, google-auth-httplib2
idna==2.8 # via requests
injector==0.16.2 # via gumo-core
itsdangerous==1.1.0 # via flask
jinja2==2.10.1 # via flask
markupsafe==1.1.1 # via jinja2
protobuf==3.8.0 # via google-api-core, googleapis-common-protos
pyasn1-modules==0.2.5 # via google-auth
pyasn1==0.4.5 # via pyasn1-modules, rsa
pytz==2019.1 # via google-api-core
pyyaml==5.1.1 # via gumo-core
requests==2.22.0
rsa==4.0 # via google-auth
six==1.12.0 # via google-api-core, google-api-python-client, google-auth, google-resumable-media, protobuf
uritemplate==3.0.0 # via google-api-python-client
urllib3==1.25.3 # via requests
werkzeug==0.15.4 # via flask
@dskecse
Copy link
Author

dskecse commented Jan 14, 2026

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