12

For certain pages in a Flask app I'm creating, I have an HTTPS redirection system as follows.

def requires_https(f, code=302):
    """defaults to temp. redirect (301 is permanent)"""
    @wraps(f)
    def decorated(*args, **kwargs):
        passthrough_conditions = [
            request.is_secure,
            request.headers.get('X-Forwarded-Proto', 'http') == 'https',
            'localhost' in request.url
        ]

        if not any(passthrough_conditions):
            if request.url.startswith('http://'):
                url = request.url.replace('http://', 'https://')
                r = redirect(url, code=code)
                return r
    return decorated

If you're not requesting the HTTPS version of the page, it redirects you to it. I want to write unit tests for this service. I have written one that makes sure that you're redirected to the HTTPS version (check for a 301 or a 301, basically). I want to test that if you are requesting the https version of the page and are already on https, it does not redirect you (basically, for a 200). How do I get Flask to send an https request in the unit test?

jclancy
  • 49,598
  • 5
  • 30
  • 34
  • Did you ever figure this out? – nu everest Feb 26 '17 at 14:10
  • @nu_everest This was a long, long time ago, and I didn't try Belrog's answer because the project was already over. IIRC we ended up getting an HTTPS certificate for the testing environment and writing a quick manual test...not ideal. – jclancy Feb 26 '17 at 18:32

5 Answers5

6

You can force the Flask test's get() call to use HTTPS like this:

response = self.app.get('/login', base_url='https://localhost')
assert(response.status_code == 200)

The addition of the base_url is used by the underlying Werkzeug to set the url scheme (HTTP/HTTPS). For local test calls like these the host name is not used, and can be left out. You can see basic in code documentation for base_url here.

Belrog
  • 950
  • 1
  • 11
  • 19
  • 1
    While this works, answer https://stackoverflow.com/a/63708394/9415337 is much better. It allows less repetition (between different unit tests) and there's no need to hardcode the host address. – miquelvir Nov 21 '20 at 20:14
2

There's a even easier Flask way to do that, just use the PREFERRED_URL_SCHEME configuration parameter equals to 'https'.

You can find it's definition here. You can find the rules how it's used internally by Flask here. You can also find how its used here.

Filipe Bezerra de Sousa
  • 2,874
  • 1
  • 17
  • 17
1

Have you looked at unit testing for flask?

After your setup code, you'll have something like this

response = self.client.get(url)
self.assertEquals(response.status_code, 301)
self.assertEquals(resonse.text.find('https'), 0)

Update

It seems the best way forward is to create a werkzeug environment. Flask uses the werkzeug test client. You can have a look at the api here. The quickstart (which is useful) is over here.

You'll see that werkzeug has an EnvironBuilder with a base_url. Perhaps its possible to play around with that to mimic an https environment in your test suite.

Gevious
  • 3,214
  • 3
  • 21
  • 42
  • This isn't really what I was looking for; I clarified it just now. I want to simulate an https request in a unit test. – jclancy Jun 13 '13 at 20:21
  • I updated my answer. I'm really not sure if test suites cater for https testing. The above is my best shot at finding a solution. – Gevious Jun 14 '13 at 05:59
-1

I would use the python requests library: http://docs.python-requests.org/en/latest/

Quite easy to do http requests with it.

bwbrowning
  • 6,200
  • 7
  • 31
  • 36
-2

With the requests library, you can ignore SSL with the verify flag.

requests.get('https://example.com', verify=False)

This will ignore SSL warnings from using a self-signed certificate

Michael Davis
  • 2,350
  • 2
  • 21
  • 29
  • I tried this, but the issue is that I need to have an HTTPS server running (on port 483 or something). Does Flask provide facilities for this? – jclancy Jun 14 '13 at 02:57