Can't get Flask-Session to send session cookie (Python+React) - python

So basically the issue is that my flask server is not saving the sessions I create in one route to access in a separate route. The sessions in my /login works, it returns the refresh and access token, however, the same cannot be said about the /auth path. I believe that there is something wrong with my CORS which is blocking my session cookies, but I'm not necessarily sure.
This is my flask app.py code:
from flask import Flask, jsonify, request, url_for,session
from flask_cors import CORS, cross_origin
from google_auth_oauthlib.flow import Flow
from google.oauth2 import id_token
from flask_session import Session
import os,pathlib,requests
app = Flask(__name__)
app.config['CORS_HEADERS'] = 'Content-Type'
SESSION_TYPE = 'filesystem'
app.config.from_object(__name__)
CORS(app,supports_credentials=True)
Session(app)
GOOGLE_CLIENT_ID = "----------------------------"
client_secrets_file = os.path.join(pathlib.Path(__file__).parent, "client_secret.json")
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
#app.route('/login', methods=['POST'])
#cross_origin()
def login():
flow = Flow.from_client_secrets_file(
'client_secret.json',
scopes=['https://www.googleapis.com/auth/drive.metadata.readonly'],
redirect_uri='http://localhost:3000',
)
flow.fetch_token(code=request.get_json()['code'])
credentials = flow.credentials
session['access_token'] = credentials.token
session['refresh_token'] = credentials.refresh_token
session.permanent = True
return jsonify({"access_token":session.get('access_token'),"refresh_token":session.get('refresh_token')})
#app.route('/auth', methods=['POST'])
#cross_origin()
def authenticate():
#This is just temp code to test if sessions work
return jsonify(session['access_token'])
#app.route('/refresh', methods=['POST'])
#cross_origin()
def refresh():
# check if refresh token is in session if not prompt user to login
# if user refresh token exists, contact google api to create new access token
# return either "403" relogin or "200" {new access token}
pass
if __name__ == '__main__':
app.run(debug=True)
This is my react code:
import axios from "axios";
import { useContext, useEffect, useState } from "react"
import { GlobalContext } from "../globalState/globalState";
import ErrorPage from "./errorPage";
const Authenticate = ({element}) => {
const [message, setMessage] = useState();
const {accessToken} = useContext(GlobalContext);
const checkValidToken = async() => {
//console.log(accessToken)
return await axios.post(
"http://localhost:5000/auth",{headers: {
'Content-Type': 'application/json'
},
withCredentials: true
}
).then((resp)=> {
console.log(resp)
})
}
useEffect(()=> {
// check if refresh token is a thing, if not post request localhost:5000/refresh
checkValidToken().then((resp)=> {
if(resp)
setMessage(element);
else
setMessage(<ErrorPage />)
})
},[])
return (<>{message}</>);
}
export default Authenticate;
This is the error I get when I make a /auth request.
Traceback (most recent call last):
File "C:\Program Files\Python39\Lib\site-packages\flask\app.py", line 2091, in call
return self.wsgi_app(environ, start_response)
File "C:\Program Files\Python39\Lib\site-packages\flask\app.py", line 2076, in wsgi_app
response = self.handle_exception(e)
File "C:\Program Files\Python39\Lib\site-packages\flask_cors\extension.py", line 165, in wrapped_function
return cors_after_request(app.make_response(f(args, **kwargs)))
File "C:\Program Files\Python39\Lib\site-packages\flask\app.py", line 2073, in wsgi_app
response = self.full_dispatch_request()
File "C:\Program Files\Python39\Lib\site-packages\flask\app.py", line 1518, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Program Files\Python39\Lib\site-packages\flask_cors\extension.py", line 165, in wrapped_function
return cors_after_request(app.make_response(f(args, kwargs)))
File "C:\Program Files\Python39\Lib\site-packages\flask\app.py", line 1516, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Program Files\Python39\Lib\site-packages\flask\app.py", line 1502, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(req.view_args)
File "C:\Program Files\Python39\Lib\site-packages\flask_cors\decorator.py", line 128, in wrapped_function
resp = make_response(f(*args, **kwargs))
File "C:\Users-------------------\Documents\GitHub\RememberMyProject\app\pythonxr\app.py", line 41, in authenticate
return jsonify(session['access_token'])
KeyError: 'access_token'

Try initializing your CORS with CORS(app, supports_credentials=True).
Check here.

Related

Having issues using Flask-JWT-Extended with Flask-Restful

I'm building an API using Flask-Restful following the steps from the book "Python API Fundamentals". The problem I'm having is that I'm unable to get a token. My code which is an edited replica of that which is in the book is throwing the following error whenever I test it on Postman
127.0.0.1 - - [01/Aug/2022 13:26:49] "POST /token HTTP/1.1" 500 -
Traceback (most recent call last):
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 2091, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 2076, in wsgi_app
response = self.handle_exception(e)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 271, in error_router
return original_handler(e)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 2073, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 1519, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 271, in error_router
return original_handler(e)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 1517, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\app.py", line 1503, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 467, in wrapper
resp = resource(*args, **kwargs)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask\views.py", line 84, in view
return current_app.ensure_sync(self.dispatch_request)(*args, **kwargs)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_restful\__init__.py", line 582, in dispatch_request
resp = meth(*args, **kwargs)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\smilecook\resources\token.py", line 24, in post
access_token = create_access_token(identity=user.id)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\utils.py", line 157, in create_access_token
return jwt_manager._create_access_token(identity, fresh, expires_delta, user_claims)
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\jwt_manager.py", line 469, in _create_access_token
access_token = encode_access_token(
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\tokens.py", line 76, in encode_access_token
return _encode_jwt(token_data, expires_delta, secret, algorithm,
File "C:\Users\TARI\Documents\GitHub\understand_api_development_with_python\basic-api\venv\Lib\site-packages\flask_jwt_extended\tokens.py", line 31, in _encode_jwt
json_encoder=json_encoder).decode('utf-8')
AttributeError: 'str' object has no attribute 'decode'
Here's my requirements.txt
Flask==2.1.3
Flask-RESTful==0.3.9
httpie==3.2.1
Flask-SQLAlchemy==2.5.1
Flask-Migrate==3.1.0
psycopg2-binary==2.9.3
passlib==1.7.4
Flask-JWT-Extended==3.20.0
Werkzeug==2.0
and the codes that I think is causing the issue
from http import HTTPStatus
from flask import request
from flask_restful import Resource
from flask_jwt_extended import create_access_token
from utils import check_password
from models.user import User
class TokenResource(Resource):
def post(self):
json_data = request.get_json()
email = json_data.get('email')
password = json_data.get('password')
user = User.get_by_email(email=email)
if not user or not check_password(password, user.password):
return {'message': 'username or password is incorrect'}, HTTPStatus.UNAUTHORIZED
access_token = create_access_token(identity=user.id)
return {'access_token': access_token}, HTTPStatus.OK
from flask import request
from flask_restful import Resource
from flask_jwt_extended import jwt_optional, get_jwt_identity
from http import HTTPStatus
from utils import hash_password
from models.user import User
class UserListResource(Resource):
def post(self):
json_data = request.get_json()
username = json_data.get('username')
email = json_data.get('email')
non_hash_password = json_data.get('password')
if User.get_by_username(username):
return {'message': 'username already used'}, HTTPStatus.BAD_REQUEST
if User.get_by_email(email):
return {'message': 'email already used'}, HTTPStatus.BAD_REQUEST
password = hash_password(non_hash_password)
user = User(
username=username,
email=email,
password=password
)
user.save()
data = {
'id': user.id,
'username': user.username,
'email': user.email
}
return data, HTTPStatus.CREATED
class UserResource(Resource):
#jwt_optional
def get(self, username):
user = User.get_by_username(username=username)
if user is None:
return {'message': 'user not found'}, HTTPStatus.NOT_FOUND
current_user = get_jwt_identity()
if current_user == user.id:
data = {
'id': user.id,
'username': user.username,
'email': user.email,
}
else:
data = {
'id': user.id,
'username': user.username,
}
return data, HTTPStatus.OK
from flask import Flask
from flask_migrate import Migrate
from flask_restful import Api
from config import Config
from extensions import db, jwt
from resources.user import UserListResource, UserResource
from resources.token import TokenResource
from resources.recipe import RecipeListResource, RecipeResource, RecipePublishResource
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
register_extensions(app)
register_resources(app)
return app
def register_extensions(app):
db.init_app(app)
migrate = Migrate(app, db)
jwt.init_app(app)
def register_resources(app):
api = Api(app)
api.add_resource(UserListResource, '/users')
api.add_resource(UserResource, '/users/<string:username>')
api.add_resource(TokenResource, '/token')
api.add_resource(RecipeListResource, '/recipes')
api.add_resource(RecipeResource, '/recipes/<int:recipe_id>')
api.add_resource(RecipePublishResource, '/recipes/<int:recipe_id>/publish')
if __name__ == '__main__':
app = create_app()
app.run()
the results of pip freeze
alembic==1.8.1
aniso8601==9.0.1
certifi==2022.6.15
charset-normalizer==2.1.0
click==8.1.3
colorama==0.4.5
commonmark==0.9.1
defusedxml==0.7.1
Flask==2.1.3
Flask-JWT-Extended==3.20.0
Flask-Migrate==3.1.0
Flask-RESTful==0.3.9
Flask-SQLAlchemy==2.5.1
greenlet==1.1.2
httpie==3.2.1
idna==3.3
itsdangerous==2.1.2
Jinja2==3.1.2
Mako==1.2.1
MarkupSafe==2.1.1
multidict==6.0.2
passlib==1.7.4
psycopg2-binary==2.9.3
Pygments==2.12.0
PyJWT==2.4.0
PySocks==1.7.1
pytz==2022.1
requests==2.28.1
requests-toolbelt==0.9.1
rich==12.5.1
six==1.16.0
SQLAlchemy==1.4.39
urllib3==1.26.11
Werkzeug==2.0.0
This is happening because you have a newer version of PyJWT with an older version of flask jwt extended that are incompatible. Upgrading flask jwt extended to at least 3.25.0 should fix the issue. If you upgrade to the 4.x.x version of flask jwt extended, make sure to read over the breaking changes here: https://flask-jwt-extended.readthedocs.io/en/stable/v4_upgrade_guide/

Unit testing Flask app - mocking global variables in the app

I've got a Flask app module (app.py) which looks like this
# imports
...
from flask import Flask, request, Response
...
# module-level vars, including `logger` and `APP`
...
logger = None
APP = None
...
def init():
"""
Initialisation of app resources, including `logger`
"""
...
APP = Flask(__name__)
...
logger = logging.getLogger()
...
...
try:
init()
except Exception as e:
logger.error(str(e))
#APP.route('/healthcheck', methods=['GET'])
def healthcheck():
"""
Healthcheck endpoint - just returns OK if the app
initialised OK.
"""
return 'OK'
#APP.route('/get_keys', method=['POST'])
def get_keys():
"""
Main endpoint - accepts a POST request from a client
containing either a CSV or JSON payload defining a set
of geographic locations, and then returns some "keys"
for these.
"""
try:
logger.info('Extracting payload')
# extract payload
logger.info('Processing for keys')
# do some stuff
...
...
except Exception as e:
logger.error("Error: {}.".format(str(e)))
# return response
I've got unit tests for the Flask app defined in a module AppTests in the tests subpackage.
# general imports including `unittest` etc.
# import app module as `app`
class AppTests(unittest.TestCase):
"""
Flask app tests
"""
#classmethod
def setUpClass(self):
app.APP.config['TESTING'] = True
app.APP.config['DEBUG'] = False
self.app = app.APP.test_client()
# define other resources needed for `self.app`
def test_healthcheck(self):
res = self.app.get(path='/healthcheck')
self.assertEqual(res.status_code, 200)
def test_get_keys__csv(self):
# define sample csv data in `data` variable
headers = {
'Accept-Encoding': 'identity,deflate,gzip,compress',
'Content-Type': 'text/csv; charset=utf-8',
'Content-Length': len(data)
}
res = self.app.post(path='/get_keys', headers=headers.items(), data=data)
self.assertEqual(res.status_code, 200)
The test for the healthcheck endpoint passes but the test for the get_keys endpoint fails.
$ python -m unittest -v AppTests.AppTests.test_get_keys__csv
test_get_keys__csv (AppTests.AppTests) ...
ERROR
======================================================================
ERROR: test_get_keys__csv (AppTests.AppTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "AppTests.py", line 105, in test_get_keys__csv
res = self.app.post(path='/get_keys', headers=headers.items(), data=data)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 801, in post
return self.open(*args, **kw)
File "/path/to/venv/lib/python2.7/site-packages/flask/testing.py", line 127, in open
follow_redirects=follow_redirects)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 764, in open
response = self.run_wsgi_app(environ, buffered=buffered)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 677, in run_wsgi_app
rv = run_wsgi_app(self.application, environ, buffered=buffered)
File "/path/to/venv/lib/python2.7/site-packages/werkzeug/test.py", line 884, in run_wsgi_app
app_rv = app(environ, start_response)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1994, in __call__
return self.wsgi_app(environ, start_response)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1985, in wsgi_app
response = self.handle_exception(e)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1540, in handle_exception
reraise(exc_type, exc_value, tb)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1517, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1612, in full_dispatch_request
rv = self.dispatch_request()
File "/path/to/venv/lib/python2.7/site-packages/flask/app.py", line 1598, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/path/to/app.py", line 205, in get_keys
logger.error("Error: {}.".format(str(e)))
AttributeError: 'NoneType' object has no attribute 'error'
----------------------------------------------------------------------
Ran 1 test in 0.036s
FAILED (errors=1)
It looks like the reference to the logger object in the get_keys endpoint in the app is null when I make the call to self.app.post('/get_keys, headers=headers.items(), data=data). Every call to logger.info is generating an exception in the endpoint, which is caught and logged, and that's what I am seeing when I run the endpoint test.
Is there a way to mock this, or some how bypass the use of logger from the tests module itself? I would rather not modify the endpoint method itself.
You could potentially mock out the logging import when you run test_get_keys__csv().
from unittest.mock import patch
#patch('path.to.app.logging') # Mock the logging import
def test_get_keys__csv(self, mock_logging):
# define sample csv data in `data` variable
headers = {
'Accept-Encoding': 'identity,deflate,gzip,compress',
'Content-Type': 'text/csv; charset=utf-8',
'Content-Length': len(data)
}
res = self.app.post(path='/get_keys', headers=headers.items(), data=data)
self.assertEqual(res.status_code, 200)
If you're using Python 2, mock is a separate install.
pip install mock
and then import with
from mock import patch
More info on mock: https://docs.python.org/3/library/unittest.mock.html

'NoneType' object is not subscriptable [duplicate]

This question already has answers here:
How to get POSTed JSON in Flask?
(13 answers)
Closed 6 years ago.
I am creating an ios app that uses a server written in flask + python, and when I make a connection to the server to register a user I keep getting a 'NoneType' object is not subscriptable error in my server.py file. Basically my question is what is causing this error and how am I able to fix this. Also if anyone can point me in the right direction of different or easier ways to do this I would appreciate it thanks!
Here is the server.py file:
import bcrypt
from flask import Flask, request, make_response,jsonify
from flask_restful import Resource, Api
from pymongo import MongoClient
from json import JSONEncoder
from bson.objectid import ObjectId
from functools import wraps
app = Flask(__name__)
mongo = MongoClient('localhost', 27017)
app.db = mongo.eventure_db
app.bcrypt_rounds = 12
api = Api(app)
# Authentication code.
def check_auth(username, password):
# check_auth should access the database and check if the username + password are correct.
# create a collection to hold the users.
user_collection = app.db.users
user = user_collection.find_one({'username': username})
if user is None:
return False
else:
# check if hash generated matches stored hash
encodedPassword = password.encode('utf-8')
if bcrypt.hashpw(encodedPassword, user['password']) == user['password']:
return True
else:
return False
# User resource
class User(Resource):
def post(self):
if (request.json['username'] == None
or request.json['password'] == None):
return ({'error': 'Request requires username and password'},
400,
None)
user_collection = app.db.users
user = user_collection.find_one({'username': request.json['username']})
if user is not None:
return ({'error': 'Username already in use'}, 400, None)
else:
encodedPassword = request.json['password'].encode('utf-8')
hashed = bcrypt.hashpw(
encodedPassword, bcrypt.gensalt(app.bcrypt_rounds))
request.json['password'] = hashed
user_collection.insert_one(request.json)
#requires_auth
def get(self):
return (None, 200, None)
api.add_resource(User, '/eventure/api/v1.1/user/')
# Must define a custom JSON Serializer for flask_restful
# this is because ObjectId is not a string, and therefore,
# Flask's default serializer cannot serialize it.
#api.representation('application/json')
def output_json(data, code, headers=None):
resp = make_response(JSONEncoder().encode(data), code)
resp.headers.extend(headers or {})
return resp
if __name__ == '__main__':
app.config['TRAP_BAD_REQUEST_ERRORS'] = True
app.run(host='localhost', port=8789, debug=True)
And this is my register function in swift:
#IBAction func register(_ sender: AnyObject) {
let url = URL(string: "http://localhost:8789/eventure/api/v1.1/user/")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue(generateBasicAuthHeader(username: username.text!, password: password.text!), forHTTPHeaderField: "Authorization")
let session = URLSession.shared
let task = session.dataTask(with: request) { data, response, error in
if let response = response, let data = data {
print(String(data: data, encoding: String.Encoding.utf8))
}
}
task.resume()
self.username.text = ""
self.password.text = ""
}
traceback:
[28/Oct/2016 19:22:33] "POST /eventure/api/v1.1/user/ HTTP/1.1" 500 -
Traceback (most recent call last):
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1836, in __call__
return self.wsgi_app(environ, start_response)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1820, in wsgi_app
response = self.make_response(self.handle_exception(e))
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1403, in handle_exception
reraise(exc_type, exc_value, tb)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise
raise value.with_traceback(tb)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1817, in wsgi_app
response = self.full_dispatch_request()
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1477, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 270, in error_router
return original_handler(e)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1381, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/_compat.py", line 32, in reraise
raise value.with_traceback(tb)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1475, in full_dispatch_request
rv = self.dispatch_request()
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/app.py", line 1461, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 471, in wrapper
resp = resource(*args, **kwargs)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask/views.py", line 84, in view
return self.dispatch_request(*args, **kwargs)
File "/Users/Dynee/eventure-backend-api/development/lib/python3.5/site-packages/flask_restful/__init__.py", line 581, in dispatch_request
resp = meth(*args, **kwargs)
File "/Users/Dynee/eventure-backend-api/server.py", line 128, in post
if (request.json['username'] == None
TypeError: 'NoneType' object is not subscriptable
Also here is the generateBasicAuthHeader function:
func generateBasicAuthHeader(username: String, password: String) -> String {
let loginString = String(format: "%#:%#", username, password)
let loginData = loginString.data(using: String.Encoding.utf8)!
let base64LoginString = loginData.base64EncodedString()
let basicAuthHeader = "Basic \(base64LoginString)"
return basicAuthHeader
}
You need to explicitly set the content-type to application/json for request.json to work properly in flask. If the header isn't set, request.json would return None.
But the recommended to get json data in flask from a post request is to use request.get_json()
I'll also urge you to test your api with the nifty requests module before using your ios application.
>>> import requests
>>> requests.post(url, json={'name': 'hello world'})
It already sets the appropriate headers required to make a json request
If it works with the requests module, then you can be sure that it's going to work with your ios application. you just need to make sure you're setting the correct content-type.
You can forcefully tell flask to ignore the content-type header with
request.get_json(force=True)

error with flask session during youtube api v3 authentication [duplicate]

This question already has answers here:
demystify Flask app.secret_key
(2 answers)
Closed 7 years ago.
I'm developing an app in python that uses YT API. I decided to move it to the web and i'm using Flask. I took the auth example from Google guides. For testing purposes i'm trying to create a playlist after authentication. It looks like this:
#app.route('/')
def index():
if 'credentials' not in flask.session:
return flask.redirect(flask.url_for('oauth2callback'))
credentials = client.OAuth2Credentials.from_json(flask.session['credentials'])
if credentials.access_token_expired:
return flask.redirect(flask.url_for('oauth2callback'))
else:
http_auth = credentials.authorize(httplib2.Http())
yt_service = discovery.build('youtube', 'v3', http_auth)
playlists_insert_response = yt_service.playlists().insert(
part="snippet,status",
body=dict(
snippet=dict(
title="Test Playlist",
description="A private playlist created with the YouTube API v3"
),
status=dict(
privacyStatus="private"
)
)
).execute()
return playlists_insert_response["id"]
#app.route('/oauth2callback')
def oauth2callback():
flow = client.flow_from_clientsecrets('youtube/client_secret.json',scope='https://www.googleapis.com/auth/youtube',redirect_uri=flask.url_for('oauth2callback', _external=True))
if 'code' not in flask.request.args:
auth_uri = flow.step1_get_authorize_url()
return flask.redirect(auth_uri)
else:
auth_code = flask.request.args.get('code')
credentials = flow.step2_exchange(auth_code)
flask.session['credentials'] = credentials.to_json()
return flask.redirect(flask.url_for('index'))
So in browser I authenticate, accept app's permisions and then I see 500 internal error with ouath2callback URI and code parameter. In the error log I see this:
2015-09-07 10:23:08,319 :Successfully retrieved access token
2015-09-07 10:23:08,330 :Exception on /oauth2callback [GET]
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1687, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1360, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1358, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1344, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/Kraxi/youtube/playlist.py", line 63, in oauth2callback
flask.session['credentials'] = credentials.to_json()
File "/usr/local/lib/python2.7/dist-packages/werkzeug/local.py", line 339, in __setitem__
self._get_current_object()[key] = value
File "/usr/local/lib/python2.7/dist-packages/flask/sessions.py", line 57, in _fail
raise RuntimeError('the session is unavailable because no secret '
RuntimeError: the session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.
I tihnk it might be something wrong with Flask session - maybe seassion type?
Using Flask 0.10
Any ideas, please?
In order to use sessions you need to set a SECRET_KEY.
Extracted from the docs:
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

Bottle debug toolbar

Im trying to setup bottle debug toolbar but get the following error...
todo.py
import sqlite3
import bottle
from bottle_debugtoolbar import DebugToolbarPlugin
from bottle import route, run, debug, template, request, error, PasteServer
config = {'DEBUG_TB_ENABLED': True,
'DEBUG_TB_INTERCEPT_REDIRECTS':True
}
plugin = DebugToolbarPlugin(config)
bottle.install(plugin)
Error
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 862, in _handle
return route.call(**args)
File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 1727, in wrapper
rv = callback(*a, **ka)
File "/usr/local/lib/python2.7/dist-packages/bottle_debugtoolbar/__init__.py", line 75, in wrapper
return self.process_response(content)
File "/usr/local/lib/python2.7/dist-packages/bottle_debugtoolbar/__init__.py", line 135, in process_response
and bottle.response.headers['content-type'].startswith('text/html')
File "/usr/local/lib/python2.7/dist-packages/bottle.py", line 1930, in __getitem__
def __getitem__(self, key): return self.dict[_hkey(key)][-1]
KeyError: 'Content-Type'
bottle-debugtoolbar makes an assumption that Content-type response header is set.
Just set the response content-type using bottle.response:
from bottle import response
...
#bottle.route('/')
def index():
response.headers['Content-Type'] = 'text/html; charset=UTF-8'
...
UPD:
Here's a simple working example:
import bottle
from bottle_debugtoolbar import DebugToolbarPlugin
from bottle import response
config = {
'DEBUG_TB_ENABLED': True,
'DEBUG_TB_INTERCEPT_REDIRECTS': True,
}
plugin = DebugToolbarPlugin(config)
bottle.install(plugin)
#bottle.route('/')
def guestbook_index():
response.headers['Content-Type'] = 'text/html; charset=UTF-8'
return '<html><body>Hello, world</body></html>'
bottle.debug(True)
bottle.run(host='localhost', port=8082)
Hope that helps.

Categories