Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use WSGI to reroute a user from http to https

Original Question


App Engine SDK 1.6.5
Python 2.7
webapp2

I have implemented webapp2 schemes to secure pages to https. The issue is that when a user goes to say http:// site/login instead of https:// site/login they get a 404 error due to the schemes not recognising the route.

example main.py

#  Libraries
import webapp2

#  Local Controllers
from controllers.HomeHandler import HomeHandler
from controllers.LoginHandler import LoginHandler

app = webapp2.WSGIApplication([
    webapp2.Route(r'/', HomeHandler),
    webapp2.Route(r'/login', LoginHandler, schemes=['https'], name='login')
], debug=True)

I have added another route / controller below the https route to catch http requests:
webapp2.Route(r'/login', RouteLogin)

RouteLogin.py

#  Libraries
import webapp2

class RouteLogin(webapp2.RequestHandler):
    def get(self):
        self.redirect('https://site.appspot.com/login')

This works, but it seems there should be a better way to do this. Like using htaccess on Apache web server. This is too much like a hack for my liking. I really don't like hard coded URLs in my code. Not to mention that it is 2 requests which for login isn't a big deal, but there could be other examples where it ends up costing too much.

NOTE 1: If you are looking at this solution be aware that using the HTTPS schemes also means that you will be unable to use the dev console without deleting the SCHEME or configuring a variable that you set for dev.

NOTE 2: I was able to get a programatic way to serve HTTPS instead of HTTP. I was on the right track with the comment below but it needs an argument.

webapp2.uri_for('login', _scheme='https')
This will give you the correct https://someapp.appspot.com/login url. It unfortunately doesn't take care of my main problem of how to handle people typing the url into the address bar without https and receiving an error unless I use the hack above. So I am still looking for the WSGI way to route income requests to HTPPS.

Edits: Added Note 1 and clarified the title, I thought it was apparent that I was using WSGI from the source and not CGI.

like image 434
Mark Finch Avatar asked May 29 '12 18:05

Mark Finch


People also ask

How to redirect HTTP requests to HTTPS using IIs URL Rewrite?

Redirect HTTP requests to HTTPS by using IIS URL Rewrite 1 In server, site or application level, go to URL Rewrite feature 2 Click “ Add Rule (s) ” in the “ Actions ” pane 3 Select “ Blank rule “. Click “ OK “

Why does my url rewrite rule not work with https?

If this is the case in your environment, you may need to change the server variable you use in the condition of your URL Rewrite rule. In the instructions above, we used {HTTPS} header to check the usage of HTTPS protocol. The load balancer in your network may remove this header from requests.

How to redirect from http to https?

How to Redirect from HTTP to HTTPS 1 Choose a certificate for your site#N#To make everything official, you’ll need to get your hands on a Secure Sockets... 2 Tell Google about your new protocol#N#Google considers the HTTP and HTTPS versions of one site to be two different... 3 Update your internal links More ...

How to always redirect to secure HTTPS url in WordPress?

Append query string must be checked and set the Redirect type select Permanent (301). Then click the Apply button in the right sidebar. All done, You have successfully configured your site to always redirect to secure https url. To verify open your URL in a browser without https and it should auto-redirect to https.


2 Answers

Set the URLs in app.yaml, rather than in code. See https://developers.google.com/appengine/docs/python/config/appconfig#Secure_URLs

For example:

handlers:

- url: /foo/.*
  script: accounts.py
  secure: always

This will redirect HTTP to HTTPS.

like image 75
Wilfred Hughes Avatar answered Sep 21 '22 06:09

Wilfred Hughes


This is the working code I used in testing for this question.

Note: The development Web Server (as of this writing v1.6.5) doesn't support https so your WSGI routes will need the schemes removed to work in the development environment. You can add them back before deployment or create an variable to set the scheme that checks the environment as I did below.

You can get App Engine Python to reroute the request by defining app.yaml as:
app.yaml

application: cgi-vs-wsgi
version: 1
runtime: python27
api_version: 1
threadsafe: yes

libraries:
- name: webapp2
  version: latest

handlers:

- url: /profile
  script: main.app
  secure: always

- url: /login
  script: main.app
  secure: always

- url: /.*
  script: main.app

Then in main.py you can declare your WSGI Handlers as normal like:

main.py

import webapp2
import os

# Models
from models.Shout import Shout

# Controllers
from controllers.HomeHandler import HomeHandler
from controllers.LoginHandler import LoginHandler
from controllers.ProfileHandler import ProfileHandler

if os.environ['SERVER_SOFTWARE'].startswith('Development'):
    app_scheme = 'http'
else:
    app_scheme = 'https'

app = webapp.WSGIApplication([
    webapp2.Route(r'/login', LoginHandler, name='login', schemes=[app_scheme]),
    webapp2.Route(r'/profile', ProfileHandler, name='profile', schemes=[app_scheme]),
    webapp2.Route(r'/', HomeHandler)
], debug=True)

I have uploaded the code for this app to my AE-BaseApp GitHub please feel free to download and use this in your applications. The code is licensed Apache License 2.0.

like image 28
Mark Finch Avatar answered Sep 21 '22 06:09

Mark Finch