Routing Flask application API GET requests through pythonanywhere proxy - flask

I've been stuck for a couple of days now trying to get a little football fixtures website hosted on pythonanywhere.com as a first personal project using FLASK
The issue I seem to have run into is that I need to route API calls through the pythonanywhere proxy (proxy.server:3128) but I've no idea how to configure this (I'm a beginner tbh)
Any help to point me in the right direction would be much appreciated
Some sample code below as an example of a request I'm trying to make (these work fine when hosted locally, but pythonanywhere requires the proxy routing for http requests)
from flask import Flask, request
import http.client
connection = http.client.HTTPConnection('api.football-data.org')
def getCompetitions():
print ("running getCompetitions")
connection.request('GET', '/v2/competitions/', None, headers )
response = json.loads(connection.getresponse().read().decode())
return response
competitions = getCompetitions()

Found it! Actually not too bad, just I'm a noob!
I needed to use the .set_tunnel function related to python's http.client function to do the routing through the proxy
Documentation here: https://docs.python.org/3/library/http.client.html
Usage for this example:
connection = http.client.HTTPSConnection("proxy.server", 3128)
connection.set_tunnel("api.football-data.org")
Hopefully this helps someone!

Related

Configuring a Flask application running on gunicorn to run behind a file path [duplicate]

This question already has answers here:
Python - Flask Default Route possible?
(4 answers)
Closed 7 months ago.
I am trying to configure a Flask application hosted with gunicorn to run behind a file path.
The current app is designed to run at www.example.com, but I would like to configure it to run at example.com/foo/bar
The difficulty I am having is that I can't seem to get the requests to be sent to the application. It currently works fine if you go to example.com, but going to example.com/foo/bar results in nothing. Everything is done through AWS. The networking has been setup to pass example.com/foo/bar requests to the server. The Flask init is as follows:
import os
from functools import wraps
import requests
from flask import Flask, render_template, make_response, redirect, Response, g
app = Flask(__name__)
app.config['VERSION'] = '3.7.2'
app.config['SERVER_ADDRESS'] = os.environ.get('SERVER_ADDRESS', 'https://example.com/')
app.config['APPLICATION_ROOT'] = '/foo/bar/'
#app.before_request
def set_server_address():
g.server_address = app.config['SERVER_ADDRESS']
#app.route('/')
def index(*args, **kwargs):
return redirect('/app/example')
When I check the logs after visiting example.com/foo/bar, there is no traffic. Any light which could be shed on this would be very much appreciated.
You can solve this problem by adding the /foo/bar to your flask route.
#app.route('/foo/bar')
def make_homepage():
return 'success'
But it's not best practice because each time the response will be as a redirect and with high traffic it's could be pretty resource intensive, so i will recommend to you to check this question:
Python - Flask Default Route possible?

Flask API, browser requests stopped working, no log the request was received

I have a very simple flask app that has been working for years, but last week requests from the built app return a 500, and from the Flask side, I can't even see the request. I am not seeing an OPTIONS request.
The below lines worked previously to keep CORS happy.
#app.after_request
def after_request(response):
response.headers.add('Access-Control-Allow-Origin', '*')
response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization,Auth-Token')
response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
return response
I have tried in a few browsers and all of them fail to successfully make any requests. Since the server doesn't even acknowledge the request has been made, I am not sure where to trouble shoot. I did confirm the app returns data as expected when I use Postman to make the request, as well as confirming that if I use the app locally (gulp serve on my computer) that the requests are successful. I have to believe its CORS, but what might I have to add / do to get the browser to be happy? Thanks.
The solution to my problem was that chrome started to "restrict the ability of websites to communicate with devices on the local network"
Communicating from Chrome 94+ with LAN devices that do not support HTTPS from a web app

How to allow CORS in google cloud run?

I have a react microservice (via nginx) deployed onto google cloud run with its environment variable for the backend set to another google cloud run instance that's running gunicorn which is serving the backend.
My Flask app is set up following everything I could find about allowing CORS:
app = Flask(__name__)
app.config.from_object(config)
CORS(app, resources={r"/*": {"origins": "*"}})
app.config['CORS_HEADERS'] = 'Content-Type'
return app
# Different file, a blueprint's urls:
#blueprint.route('/resources')
#cross_origin()
def get_resources():
...
Yet I'm still getting the dreaded Access to XMLHttpRequest at 'https://backend/resources/' from origin 'https://frontend' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Does anyone have any insight into this/know where else to look in figuring this out? I wanted to set up GKE with my microservices but took the path of least resistance initially to get a POC up in the cloud. I have the backend speaking with my Cloud SQL instance, and I'm so close!!
Thank you
You've set up more than you need to. Unless you need to provide different CORS access for different endpoints, the simplest example just requires calling CORS(app):
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
#app.route("/resources")
def get_resources():
return "Hello, cross-origin-world!"
if __name__ == "__main__":
app.run('0.0.0.0', 8080, debug=True)
And you'll see that the header is present:
$ curl -I localhost:8080/resources
HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 26
Access-Control-Allow-Origin: *
Server: Werkzeug/1.0.1 Python/3.7.4
Date: Tue, 21 Apr 2020 17:19:25 GMT
Everything was self inflicted.
As Dustin Ingram mentioned, if you enable CORS for Flask, it will work. I still have NO idea why I was getting the CORS issues at all, I've had CORS enabled for my Flask app from the get go.
After I nuked everything and redeployed, the CORS issues disappeared. However, I still ended up getting either 404s, 405s, and 308s.
There were a couple of issues, all my shortcomings, that in combination gave me those issues. In create-react-app (webpack I think is doing it), environment variables passed into the docker runtime does not get respected, so the environment variable I set in Cloud Run wasn't working at all. Currently I opted for the process.env.VARIABLE || 'hardcoded-url' route. Once I got that figured out, I also remembered trailing slashes in flask URLs are bad.... Those gave me 308s, permanent redirects. Once I got that figured out, I realized during my manual deployments, I wasn't switching the cloud build image to the latest. Sigh. Once I started deploying the latest images, everything started working. Yay!
Thanks Dustin and Gabe for spending your time on my foolishness.
I just recently wrestled with this as well... My issue was trying to use some JS library to make my URL requests "easier" and instead was munging the headers on the request side (not the server side). Switched to just using straight XMLHttp and it started working fine. I also switched from application/json to application/x-www-form-urlencoded. I don't know if that made a difference or not, but including it for completeness.
You also shouldn't (I say shouldn't, but you know how that goes) need anything OTHER than:
CORS(app). All the #cross-region stuff, and the config pieces are all only there to make a narrower CORS access so it's not wide open, but you have it wide open anyway in your initial code (CORS(app, resources={r"/*": {"origins": "*"}}) is the same I believe as CORS(app)).
Long story, short, try looking at the request object, rather than the Flask side.
Edit: Adding the request code that worked for me after I couldn't get the "fetch" library working:
var xhttp = new XMLHttpRequest();
xhttp.open("POST", <url>, true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
xhttp.send(Data)
I had the same problem, it was solved by setting Allow unauthenticated invocations in Cloud Run. However, this should only be done with testing and for a production environment you'll have to configure Cloud IAM.

Flask Login and Flask Socket-IO working together

i have been following the Miguel Grinberg Tutorial of flask and i make my site work with flask-login.
Now im adding flask socket-io to my site but i encounter a problem. Miguel uses the route '/logout' to log out a user, flask socket-io documentation talks about sessions and the problem of cookies using flask socket-io, but using miguel route doesnt give me that problem. I think im confussing the term 'session' but also in his video tutorial about flask socket-io he talks about the problem of logging out of a cookie session from a socket without a server side session but... with the 'logout' route that doesnt happen. Also isn't it possible to make a cross site request forgery if i use a route like '/logout' ?

Status 500 for POST requests in django on IIS

Dear StackOverflow community, your help would be greatly appreciated.
I have zero experience with IIS. Unfortunately, a Windows Server 2012 with IIS 8.5 is all I can get for the current project. I followed this post by Matt Woodward to get my Django app running on IIS. I serve static files by means of an application that references the static folder. The app looks the way it is supposed to look and all GET requests are processed properly. However, the response to all POST requests (on localhost and remotely) is Status 500 Server Error. If I run my Django app with the runserver command, the POST requests are processed properly.
POST is NOT blocked in IIS Request Filtering -> HTTP Verbs. POST requests are sent to URLs like http:/site_title/update_plan/, not to html. The StackOverflow posts found here and here were not helpful.
I suspect the problem is in the IIS settings, but maybe some special Django settings are required and I am missing it. Any ideas on what can be done to fix the problem would be of great help. Thanks!