how to check the request is https in app engine python - google-app-engine

I would like to know if is there a way to validate that a request (say a POST or a GET) was made over https,
I need to check this in a webapp2.RequestHandler to invalidate every request that is not sent via https
best regards

Check the self.request.environ['HTTPS'] == 'on' # or 'off'.
If you only use https, consider using secure:always in your app.yaml as follows:
handlers:
- url: /.*
script: main.app
secure: always

The answer provided above to use the app.yaml config works well but in some case you need the granularity of checking this your python code itself, which is I believe what you asked for since you want to check in the RequestHandler.
Here is what you can do inside your RequestHandler:
if self.request.scheme.lower() != 'https':
self.abort(403)
else:
# handle your request here, you know it's secured!

If you are using GAE Flex (where the secure: directive doesn't work), the only way I've found to detect this (to redirect http->https myself) is to check if request.environ['HTTP_X_FORWARDED_PROTO'] == 'https'

Related

How do I force google app engine to use https ssl protocol?

I have a flask web app deployed to google app engine. However, it is not forcing my link to https. However, if I refresh it, it will go to the ssl https version. But the user can still remove the s and jump back into the http version. Is there any way to completely remove the http protocol on my site and have it redirect to the ssl version. Here is the app.yaml file I'm using currently. I also tried adding in redirect_http_response_code: 301 with no luck to remove the http protocol
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3.7
# This sample incurs costs to run on the App Engine flexible environment.
# The settings below are to reduce costs during testing and are not appropriate
# for production use. For more information, see:
# https://cloud.google.com/appengine/docs/flexible/python/configuring-your-app-with-app-yaml
manual_scaling:
instances: 1
resources:
cpu: 1
memory_gb: 0.5
disk_size_gb: 10
handlers:
- url: /.*
secure: always
script: auto
I prefer not to install additional software packages for relatively simple things, so I do it myself. For GAE flex there are a few things to handle. I've added comments below to help explain.
#app.before_request
def redirect_http():
# http -> https
if (
# Flask tells us when request is http. This might not be needed for you but
# I need it because I use this code for GAE standard as well.
not request.is_secure and
# Load balancers forward https requests as http but set headers to let you
# know that original request was https
not request.headers.get('X-Forwarded-Proto') == 'https' and
# GAE cron urls must be http
not request.path.startswith("/cron")
):
return redirect("https" + request.url[4:], code=301)
# naked domain -> www
if request.url.startswith("https://example.com"):
return redirect('https://www.' + request.url[8:], code=301)
The Flask packages recommended by #tzovourn do other important things as well so you may want to consider those (I personally do all those things myself since it isn't hard to do them).
I noticed that you are using App Engine Flexible. As per documentation, setting secure: always in app.yaml doesn't work for App Engine Flexible.
Documentation recommends to secure your HTTP requests by using the Flask Talisman library.
Another way to configure your Flask application to redirect all incoming requests to HTTPS is to use the Flask-SSLify extension

REST API call returns 404 error in Google App Engine with PHP Yii2 framework

My application contains Angular and Php Yii2 framework.
I hosted my application on Google App Engine.
Here is the contents of my app.yaml file:
threadsafe: true
runtime: php55
api_version: 2
handlers:
# The root URL (/) is handled by the Go application.
# No other URLs match this pattern.
- url: /(.+)
static_files: \1
upload: (.*)
- url: /web-service/*
script: web-service/yii
- url: /
static_files: index.html
upload: index.html
My Yii2 library is available in web-service directory, but when I call REST API from the postman, it then returns a '404 page not found' error.
Am I missing something in my app.yaml file?
Please help me solve this issue. My API call is something like this:
https://abcxyz.appspot.com/web-service/web/user-registration/login-user
Several problems:
api_version: 2 - there is no such version presently, set it to 1. From the api_version row in the Syntax table:
At this time, App Engine has one version of the php runtime
environment: 1
the order of the handlers in app.yaml matters, the first one with a matching pattern will be used. Your url: /(.+) pattern will match all of your /web-service/* requests as well, so static files uploads will be attempted instead of the script(s) you're expecting. Re-order your handlers with the most significant patterns preceeding the less significant ones.
your script: web-service/yii entry might not be OK if other php files need to be served from the web-service dir (the web-service/yii will always be the one served, regardless of the requested script). Instead I'd use the handler suggested in the Example (assuming the script names always end with .php):
# Serve php scripts.
- url: /(.+\.php)$
script: \1
Always check the request entries in the development server logs as a starting point to debug request failures.

Deployed Google Endpoints Quickstart app giving error message when i request url?

I am following the Quickstart for Cloud Endpoints Frameworks on App Engine in standard environment. I have deployed the sample API. When I open https://[my-project].appspot.com/ I get the error message:
Error: Not Found. The Requested URL / was not found on this server
The logs show the message:
No Handlers matched this url
The app.yaml handlers are the what came with the endpoints-frameworks-v2/echo sample:
handlers:
# The endpoints handler must be mapped to /_ah/api.
- url: /_ah/api/.*
script: main.api
I was having great difficulty generating the OpenAPI configuration file in a previous step of the quickstart. I got it to work by updating the system variable path for the SDK but I did get this error:
No handlers could be found for logger "endpoints.apiserving"
WARNING:root:Method echo.echo_path_parameter specifies path parameters buy you are
not using a ResourceContainer. This will fail in future releases; please
switch to using ResourceContainer as soon as possible.
I have no idea if this error is relavant to the current problem.
Any help would be much appreciated.
Regarding the "No handlers could be found for logger..." you need to do this:
http://excid3.com/blog/no-handlers-could-be-found-for-logger
The other issue is a known issue:
What are ResourceContainers and how to use them for Cloud Endpoints?
You need a url handler for / if that is a valid url:
handlers:
# The endpoints handler must be mapped to /_ah/api.
- url: /_ah/api/.*
script: main.api
- url: /.* # catchall for all other urls
script: main.api # or wherever you handle the request for `/` and others

Google App engine needs periodic restarting

I have a module that works fine when I push it to app engine. When it works it logs stuff nicely and the logs are accessible in the console logs viewer. But then after a while it just stops working and when I try to access any url give me 500 server errors with no info (it just says waiting 30 seconds might be a good idea). When this happens nothing gets logged for requests.
If I restart the module (by pushing my code to app engine) then it works for a little while again.
The module is running a Pyramid app and the configuration file looks a little something like:
application: my_app
module: my_module
version: dev
runtime: python27
api_version: 1
threadsafe: false
instance_class: B2
basic_scaling:
max_instances: 2
idle_timeout: 10m
handlers:
- url: /actions/.*
script: my_module.application
login: admin
- url: /.*
script: my_module.application
builtins:
- appstats: off
libraries:
- name: webob
version: latest
- name: setuptools
version: latest
includes:
- mapreduce/include.yaml
I think what is happening is that it's hitting the idle timeout and shutting down. I need requests to the module to turn it back on again. How do I do that?
Let me know if you need more info, I'm an app engine noob at this stage. Any help would be greatly appreciated.
When a module start, App Engine call the url /_ah/start. You mustn't handle this request.
In you my_module.application you need to add in the handler who match this request :
def get(self):
# Let module start
if "X-Appengine-Cron" in self.request.headers or "X-AppEngine-TaskName" in self.request.headers or "X-Appengine-Failfast" in self.request.headers:
return
Even if you hit the idle timeout, AppEngine will spin a new instance when new request is coming in.
Use Cloud Debugger to inspect the state of your application. The debugger makes it easier to view the application state and understand what happens after your app has been running for while.
Check the docs on startup state https://cloud.google.com/appengine/docs/python/modules/#Python_Instance_states
you current default handler /.* should be able deal with a /_ah/start if youe handler can gracefully deal with a 404.
Thats how I handle startups. Goes through the main handler which can deal with non existent url requests using the default pyramid not found.
I have a config.add_notfound_view(notfound) registered.

Google App Engine (Python) app.yaml urlhandler doesn't work

I'm trying google app engine with python27.
handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
- url: /hello
script: helloworld.app
- url: /.*
script: main.app
helloworld.py and main.app have the same code from the offical document with little difference (response string).
import webapp2
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.write('Hello world!!!')
app = webapp2.WSGIApplication([
('/', MainHandler)
], debug=True)
My result:
1. "~", the response comes from "main.app".
2. "~/favicon.ico", the response comes from "favicon.ico".
3. "~/hello", the response is "404".
4. "~/something", the response is "404".
Sorry, to post this question, "~" for "http://localhost:8080".
Why 3 and 4 cannot be handled? Is there something wrong?
Try changing ('/', MainHandler) to (r'/.*', MainHandler) (the r just indicates it is a raw string). The problem is that you don't currently have any handlers for anything other than your root /, so requests with other parameters (such as http://localhost:8080/hello) have no matching handler and therefore it is unknown how to handle it. Changing the handler to /.* means that all requests (regardless of what comes after the root) should be routed to your MainHandler.
As for the app.yaml handlers and the handlers in your *.py file, think of the app.yaml as the high-level director. It gets a request and simply determines where to send it (am I getting a request for a static Javascript file? CSS? Picture? Or is this a request that should serve a page, etc.?). In the case such as yours above, you want it to serve a particular page when hitting any URL that is not /favicon (so /.*), so what it does is takes any request to /.* and routes it to main.app, which is in your main.py file (I'm ignoring helloworld.app for now, mainly because in your situation you don't necessarily need it).
It is then that the more granular handling happens - main.app receives the original request, and then it looks for a specific handler to execute the code. When we change your handlers to r'/.*', it matches anything that comes in (so /, /hello, /helloworld, etc.), and it executes the corresponding class MainHandler, in this case).

Resources