allowing CORS request with Flask and React - python

I am trying to connect a client with a server via ajax requests.
My client, running on localhost:8080, has a button which invokes a function that does a simple ajax request to a locally running server, localhost:5000.
onClick function:
handleClick() {
console.log("check flights button was clicked!");
console.log(this.state);
const baseUrl = 'localhost:5000'
ajax.get(`${baseUrl}/flights/${this.state.origin}_${this.state.destination}`)
.end((error, response) => {
if (!error && response) {
console.log('got a valid response from the server')
} else {
console.log(`Error fetching data from the server: `, error)
}
});}
the (very) simple server, implemented with Flask, is as follows:
from flask import Flask, request
from flask_restful import Resource, Api
from json import dumps
app = Flask(__name__)
api = Api(app)
class Flights(Resource):
def get(self, origin, destination):
answer = 'we got some data ' + origin + ' ' + destination
print answer
api.add_resource(Flights, '/flights/<string:origin>_<string:destination>')
if __name__ == '__main__':
app.run()
I can access the server if i simply go to localhost:5000/flights/origin_destination, which prints a message saying it received the origin and destination.
However, when I try to do the ajax request, I get the following error:
XMLHttpRequest cannot load localhost:5000/flights/Porto_Lisboa. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https.
Any suggestions on how to correct this behaviour?
Thank you in advance.

As the error suggest, you're missing the protocol name in your request. Try to add it at the start of the string :
const baseUrl = 'http://localhost:5000'
instead of just localhost:5000

Related

Get data from an API with Flask

I have a simple flask app, which is intended to make a request to an api and return data. Unfortunately, I can't share the details, so you can reproduce the error. The app looks like that:
from flask import Flask
import requests
import json
from requests.auth import HTTPBasicAuth
app = Flask(__name__)
#app.route("/")
def getData():
# define variables
username = "<username>"
password = "<password>"
headers = {"Authorization": "Basic"}
reqHeaders = {"Content-Type": "application/json"}
payload = json.dumps(
{
"jobType": "<jobType>",
"jobName": "<jobName>",
"startPeriod": "<startPeriod>",
"endPeriod": "<endPeriod>",
"importMode": "<importMode>",
"exportMode": "<exportMode>"
}
)
jobId = 7044
req = requests.get("<url>", auth=HTTPBasicAuth(username, password), headers=reqHeaders, data=payload)
return req.content
if __name__ == "__main__":
app.run()
However, when executed this returns error 500: Internal Server Error
The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
The same script but outside a flask app (just the function as it is defined here) runs with no problems at all.
What am I doing wrong?
flask app return format json. If you return req.content, it will break function. You must parse response request to json before return it.
from flask import jsonify
return jsonify(req.json())
It's better with safe load response when the request fail
req = requests.get()
if req.status_code !=200:
return {}
else:
return jsonify(req.json())

Trying flask functions but get error that url is not valid

I wish to show my data in a webpage by using flask. (Trying to learn it)
from flask import Flask, jsonify, make_response
from flask_cors import CORS
api = Flask(__name__)
CORS(api)
api.config['JSON_AS_ASCII'] = False
api.config["JSON_SORT_KEYS"] = False
#api.route('/token',methods=["POST"])
def get_token(self):
data = {
"type": "testing",
}
response1 = make_response(jsonify(data))
return response1
if __name__ == "__main__":
api.run(port=11111)
current output when try http://127.0.0.1:11111/ on google chrome:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I also tried with /token:
Method Not Allowed
The method is not allowed for the requested URL.
you need to go to http://127.0.0.1:11111/token, if you want to go to http://127.0.0.1:11111/ you need to define a function with route #api.route('/',methods=["POST"])
Also a browser makes GET requests via URL unless explicitly defined, change it to get via #api.route('/',methods=["GET"])
Your route is /token, so you need to go to http://127.0.0.1:11111/token.
POST requests cannot be directly viewed in browser. Try some rest API client like Postman to test your POST request.
Alternatively, if you want to test if the API just works, change the POST method to GET. Then if you visit http://127.0.0.1:11111/token, you can see the response. Also you don't need 'self' argument to your method.
You restrict your app.route to only POST. If you want to enter your page from url you have to specify GET as well.
Read about http requests
from flask import Flask, jsonify, make_response
from flask_cors import CORS
api = Flask(__name__)
CORS(api)
api.config['JSON_AS_ASCII'] = False
api.config["JSON_SORT_KEYS"] = False
#api.route('/token',methods=["GET", "POST"])
def get_token(self):
data = {
"type": "testing",
}
response1 = make_response(jsonify(data))
return response1
if __name__ == "__main__":
api.run(port=11111)

How can i build a proper restful response API by python flask for parameters

I'm studing about RESFful API with python.
I want to build a my restful api server,
but i have a problem,
i don't know how my api server returns proper data by reqeust each parameters
(request code sample)
the request code wants to get the information about 'item' : 'sword'
import requests
import json
url = "https://theURL"
querystring={"item":"sword"}
response = requests.request("GET", url, params=querystring)
print (response.json())
(API server response code sample, by flask python)
from flask import Flask, url_for
from flask_restful import Resource, Api, abort, reqparse
app = Flask(__name__)
api = Api(app)
TODOS = {
"version":"2.0",
"resultCode":"OK",
"output":{
{
"item" :"sword"
"price": 300,
"damage": 20,
},
{
"item" :"gun"
"price": 500,
"damage": 30,
},
},
}
class Todo(Resource):
def post(self):
return TODOS
api.add_resource(Todo, '/item.price')
if __name__ == "__main__":
app.run(debug=True, host ="192.168.0.8", port = 8080)
So i want to know how i use a code in response api server for returning 'item price' data by reqeusted parameters 'item : sword'
I just want to get the selected parameter's item price and damage information.
I thought it might be very easy, i'm tried to search the example but i couldn't find proper sample code.
I'm not a Flask-expert, but this helps setting up and running a minimalistic Flask-server. Then, this explains how to return json-formatted data from your server, and finally how to request and interpret the json-response can be found here. Summarized below:
Server returning a json-formatted data:
from flask import Flask
from flask import jsonify
app = Flask(__name__)
#app.route('/')
#app.route('/index')
def hello():
return "Hello, World!"
#app.route('/request_sword')
def grant_sword():
return jsonify({"sword": {"name":"Excalibur","price":"stack overflow"}})
Client requesting json-formatted data:
import json
import urllib.request
url = "http://127.0.0.1:5000/request_sword" ## My local host flask server
data = urllib.request.urlopen(url)
response = json.loads(data.read())
print(response)
That's all really. You may also just enter the url in your browser, which will correctly read the json-data:

Flask session not persisting between requests for Angular App

I have an Angular app that needs to call a Flask server that use sessions to store information between requests.
I also have an older JS app that called the same server using XMLHttpRequest, that I am replacing with the new Angular app.
The trouble is that when the old app was making a request, session cookies were working as expected but now with the angular app it does not.
All interactions are done over localhost. The Flask server is accessible from localhost:5000, and the Angular app from localhost:4200.
The old app was doing request like this:
var xhttp = new XMLHttpRequest();
xhttp.open("GET", "http://localhost:5000/api/getAll", true);
xhttp.withCredentials = true;
xhttp.send();
The Angular app is doing like so:
import { Injectable } from '#angular/core';
import { HttpClient, HttpHeaders, } from '#angular/common/http';
import { Observable } from 'rxjs';
const httpOptions = {
withCredentials: true,
headers: new HttpHeaders({
'Content-Type': 'application/json',
'charset': 'UTF-8',
})
};
#Injectable()
export class ServerService {
url = "http://localhost:5000/api/"
constructor(private http:HttpClient) { }
getAll(): Observable<string>{
return this.http.get<string>(this.url + 'getAll', httpOptions);
}
login (username: string): Observable<string> {
return this.http.post<string>(this.url + 'login', JSON.stringify({"username": username}), httpOptions)
}
}
And the Flask server:
from flask import Flask, session, request, jsonify
from flask_cors import CORS
import os
import Person
import multiprocessing as mp
import json
import Insurance
import datetime
import Functions
import missingVal
app = Flask(__name__)
CORS(app, supports_credentials=True)
# set the secret key. keep this really secret:
# The value come from calling os.urandom(24)
# See https://stackoverflow.com/a/18709356/3729797 for more information
# app.secret_key = b'fL\xabV\x85\x11\x90\x81\x84\xe0\xa7\xf1\xc7\xd5\xf6\xec\x8f\xd1\xc0\xa4\xee)z\xf0'
app.config['SECRET_KEY'] = b'fL\xabV\x85\x11\x90\x81\x84\xe0\xa7\xf1\xc7\xd5\xf6\xec\x8f\xd1\xc0\xa4\xee)z\xf0'
#app.route('/api/getAll')
def getAll():
response = jsonify()
if 'username' in session:
user = users[session['username']]
# some more logic here
response = jsonify({'username': session['username']})
return response
# login and account creation
#app.route('/api/login', methods=['POST'])
def login():
response = jsonify()
if users.get(request.json.get('username')) is not None:
session['username'] = request.json.get('username')
# some more logic here
response = jsonify({'username': session['username']})
response.headers.add('Access-Control-Allow-Methods',
'GET, POST, OPTIONS, PUT, PATCH, DELETE')
response.headers.add('Access-Control-Allow-Headers',
"Origin, X-Requested-With, Content-Type, Accept, x-auth")
return response
if __name__ == '__main__':
# some more logic here
app.run(host='localhost', threaded=True
The problem is that when I log in, it push information into the session, and when I do another request, I check if that information is in the session but it does not.
I found a lot of other related question on StackOverflow:
this one has to do with setting the secret_key multiple times, which is not my problem.
this one talk about static versus dynamic configuration in init but I don't think it has anything to do with my problem? Tell me if I'm wrong.
this one and this other one had trouble because their payload inside the cookie was too big, only 4096bytes or less are allowed it seems. But I only put a username that is a few letters into my cookie so I don't believe it is my problem.
this one I thought was related to my problem because it deals with localhost, but it turns out that it was because OP was mixing requests on 127.0.0.1 and localhost and cookies are processed separately by flask apparently. I do all my request on localhost so not related I believe.
I'm a bit lost right now, there is probably something very obvious I am missing but can't figure it out, any suggestion appreciated
I got it working by adding
response.headers.add('Access-Control-Allow-Headers',
"Origin, X-Requested-With, Content-Type, Accept, x-auth")
in the Flask server before sending back all requests.
For example
#app.route('/api/doSomething', methods=['POST'])
def doSomething():
response = jsonify()
if 'username' in session:
# some logic here
response = jsonify(someData)
# here is the line I added
response.headers.add('Access-Control-Allow-Headers',
"Origin, X-Requested-With, Content-Type, Accept, x-auth")
return response
Apparently it is needed when doing CORS, some good informations on MDN

Making an Angular2 POST with JSON

I have a simple Flask backend for the API, and want to make a POST.
I'm not sure the error is-I get the error message, but am unsure if its an Angular or Flask issue. I tried request.get_json() in my Flask, and got
{BadRequest}400 BadRequest: The browser (or proxy) sent a request that
this server could not understand
Angular2 call in my service.ts:
import { Injectable } from '#angular/core';
import { Http, Response } from '#angular/http';
import { Observable} from 'rxjs/Rx';
import { Headers } from '#angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';
#Injectable()
export class NicksService {
private headers = new Headers({'Content-Type': 'application/json'});
nickUrl: string = "http://localhost:5000/nick";
constructor(private http: Http) { }
// Send the nick to the server to see if it is valid
checkNickValidity(nickName: string): Observable<string>{
return this.http.post(this.nickUrl, JSON.stringify({nick: nickName}), {headers: this.headers})
.map(this.extractData)
.catch(this.handleError)
}
Flask backend:
from flask_cors import CORS
from flask.ext.api import FlaskAPI
from flask import request
app = FlaskAPI(__name__)
CORS(app)
#app.route('/')
#app.route('/nick', methods=['POST'])
def check_nick():
try:
nick = request.json
if nick =='AmandaPanda':
return 'Good'
else:
return 'No nick found'
except:
return 'error'
if __name__ == '__main__':
app.run()
I think you have problems on both sides of your application.
Client side:
Angular's Http's post method receives any object in for the body parameter, meaning you don't need to stringify it.
E.g.:
this.http.post(this.nickUrl, {nick: nickName}, {headers: this.headers})
Server side:
Once the client's request arrived properly to the server, you are not getting the data properly.
What you need to do is something like this:
from flask import jsonify
(... your code ...)
data = request.json
nick = data.get('nick')
if nick == 'AmandaPanda':
return jsonify({'message': 'good'}), 200
else:
return jsonify({'message': 'no nick found'}), 400
Here, the json data is stored as a dictionary in the variable data. Later, the nick is obtained from the nick key of said dictionary.
Finally, it is a better practice to return to the client in json form. That's what Flask's jsonify method is for. Notice the 200 and 400 status codes appended to the response, to indicate to the client if the request was properly accepted (200) or if it was a bad request (400).

Categories