Open cloud-rocket opened 6 years ago
Now, I do see that default handlers are registered (in _set_error_handler_callbacks). But for some reason they never executed in my configuration
I think it is related to the fact that I am using Restplus Api object with Flask Blueprint, so errorhandler should be used with api
object and not with app
as it is done in _set_error_handler_callbacks
Eventually, I recreated all the error handlers manually to solve it:
@api.errorhandler(jwt_extended_exception.NoAuthorizationError)
def handle_auth_error(e):
return {'message': str(e)}, 401
@api.errorhandler(jwt_extended_exception.CSRFError)
def handle_auth_error(e):
return {'message': str(e)}, 401
@api.errorhandler(jwt_exception.ExpiredSignatureError)
def handle_expired_error(e):
return {'message': 'Token has expired'}, 401
@api.errorhandler(jwt_extended_exception.InvalidHeaderError)
def handle_invalid_header_error(e):
return {'message': str(e)}, 422
@api.errorhandler(jwt_exception.InvalidTokenError)
def handle_invalid_token_error(e):
return {'message': str(e)}, 422
@api.errorhandler(jwt_extended_exception.JWTDecodeError)
def handle_jwt_decode_error(e):
return {'message': str(e)}, 422
@api.errorhandler(jwt_extended_exception.WrongTokenError)
def handle_wrong_token_error(e):
return {'message': str(e)}, 422
@api.errorhandler(jwt_extended_exception.RevokedTokenError)
def handle_revoked_token_error(e):
return {'message': 'Token has been revoked'}, 401
@api.errorhandler(jwt_extended_exception.FreshTokenRequired)
def handle_fresh_token_required(e):
return {'message': 'Fresh token required'}, 401
@api.errorhandler(jwt_extended_exception.UserLoadError)
def handler_user_load_error(e):
# The identity is already saved before this exception was raised,
# otherwise a different exception would be raised, which is why we
# can safely call get_jwt_identity() here
identity = get_jwt_identity()
return {'message': "Error loading the user {}".format(identity)}, 401
@api.errorhandler(jwt_extended_exception.UserClaimsVerificationError)
def handle_failed_user_claims_verification(e):
return {'message': 'User claims verification failed'}, 400
But I think this case should be handled internally somehow
It is an error with rest plus breaking native flask error handlers. Look at #83 for the details.
I've thought of a better way to solve this. It is very much a hack, and I still think flask-restplus should fix their extension so that it does not break native flask features, but it should get you up and going safer then how you have it handled above.
It looks like the errorhandler method for restplus uses the same signature that flask error handler does, so you could take advantage of duck typing and access this internal method to set the errors on the restplus level: https://github.com/vimalloc/flask-jwt-extended/blob/master/flask_jwt_extended/jwt_manager.py#L81
from flask import Flask
from flask_jwt_extended import JWTManager
from flask_restplus import Api
app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'super-secret' # Change this!
jwt = JWTManager(app)
api = Api()
# This is where the duck typing magic comes in
jwt._set_error_handler_callbacks(api)
This would obviously be prone to break if I changed how the underlying part of this extension worked, as you are accessing a private method that doesn't have any guarantees on it, but I do not see any reason why that method would change in the foreseeable future, and this would insure that any new or changed error handles in this extension would get properly set on the flask-restplus extension.
Hope this helps :)
I tried it - its not working
On Oct 10, 2017 6:22 PM, "Landon" notifications@github.com wrote:
I've thought of a better way to solve this. It is very much a hack, and I still think flask-restplus should fix their extension so that it does not break native flask features, but it should get you up and going safer then how you have it handled above.
It looks like the errorhandler method for restplus uses the same signature that flask error handler does, so you could take advantage of duck typing and access this internal method to set the errors on the restplus level: https://github.com/vimalloc/flask-jwt-extended/blob/ master/flask_jwt_extended/jwt_manager.py#L81
from flask import Flaskfrom flask_jwt_extended import JWTManagerfrom flask_restplus import Api
app = Flask(name) app.config['JWT_SECRET_KEY'] = 'super-secret' # Change this! jwt = JWTManager(app) api = Api()
This is where the duck typing magic comes in
jwt._set_error_handler_callbacks(api)
This would obviously be prone to break if I changed how the underlying part of this extension worked, as you are accessing a private method that doesn't have any guarantees on it, but I do not see any reason why that method would change in the foreseeable future, and this would insure that any new or changed error handles in this extension would get properly set on the flask-restplus extension.
Hope this helps :)
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/vimalloc/flask-jwt-extended/issues/86#issuecomment-335509456, or mute the thread https://github.com/notifications/unsubscribe-auth/ACU-vDf7fm8v8FHICqwVt4bpRisEbjIrks5sq4uzgaJpZM4PyP7J .
It works for me if I try the following. Are you doing something different?:
from flask import Flask, jsonify, request
from flask_jwt_extended import (
JWTManager, jwt_required, create_access_token,
get_jwt_identity
)
from flask_restplus import Resource, Api
app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'super-secret' # Change this!
jwt = JWTManager(app)
api = Api(app)
jwt._set_error_handler_callbacks(api)
@api.route('/hello')
class HelloWorld(Resource):
@jwt_required
def get(self):
return {'hello': 'world'}
@api.route('/login')
class Login(Resource):
def post(self):
username = request.json.get('username', None)
password = request.json.get('password', None)
if username != 'test' or password != 'test':
return jsonify({"msg": "Bad username or password"}), 401
access_token = create_access_token(identity=username)
return {'access_token': access_token}
if __name__ == '__main__':
app.run(debug=True)
And using it:
$ http GET :5000/hello
HTTP/1.0 401 UNAUTHORIZED
Content-Length: 44
Content-Type: application/json
Date: Tue, 10 Oct 2017 16:06:28 GMT
Server: Werkzeug/0.12.2 Python/3.6.2
{
"msg": "Missing Authorization Header"
}
$ http POST :5000/login username=test password=test
HTTP/1.0 200 OK
Content-Length: 302
Content-Type: application/json
Date: Tue, 10 Oct 2017 16:06:30 GMT
Server: Werkzeug/0.12.2 Python/3.6.2
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDc2NTI0OTAsImlhdCI6MTUwNzY1MTU5MCwibmJmIjoxNTA3NjUxNTkwLCJqdGkiOiI4YWRjYzQyOS02MmE0LTRlNTAtYjhhZS05MmU0MTA4YTUyZDMiLCJpZGVudGl0eSI6InRlc3QiLCJmcmVzaCI6ZmFsc2UsInR5cGUiOiJhY2Nlc3MifQ.ixGtDywN2SVyBHMeSLXZq8g0fs0VwgbIARUXP8CaITQ"
}
$ http GET :5000/hello Authorization:"Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDc2NTI0OTAsImlhdCI6MTUwNzY1MTU5MCwibmJmIjoxNTA3NjUxNTkwLCJqdGkiOiI4YWRjYzQyOS02MmE0LTRlNTAtYjhhZS05MmU0MTA4YTUyZDMiLCJpZGVudGl0eSI6InRlc3QiLCJmcmVzaCI6ZmFsc2UsInR5cGUiOiJhY2Nlc3MifQ.ixGtDywN2SVyBHMeSLXZq8g0fs0VwgbIARUXP8CaITQ"
HTTP/1.0 200 OK
Content-Length: 25
Content-Type: application/json
Date: Tue, 10 Oct 2017 16:06:49 GMT
Server: Werkzeug/0.12.2 Python/3.6.2
{
"hello": "world"
}
@vimalloc Just wanted to let you know that I ran into this as well. I also tried the solution you posted and didn't have any luck. I am guessing one of two things is going on:
I did some digging to figure out where this was going awry in Restplus and you can see the link above where I submitted it upstream. The upstream issue links to a gist, in case you'd like a small test-case to play with.
Thanks for your work on this! Hopefully this will lead to changes in flask-restplus where native flask error handlers will just work. In the mean time, I tried to duplicate the example in your gist to check the error handler work around. I wasn't able to get the gist working by itself, it couldn't find the route for the restfplust api for some reason. Instead of spending time debugging that, I created a new example using (afaict) the same type of setup that you have in the gist.
from flask import Flask, Blueprint
from flask_jwt_extended import jwt_required, JWTManager, create_access_token
from flask_restplus import Api, Namespace, Resource
app = Flask(__name__)
app.config['SECRET_KEY'] = "test"
jwt = JWTManager(app)
api_v1 = Blueprint('api', __name__)
api = Api(api_v1, version='1.0', title='Todo API', description='A simple TODO API')
# This is the hack I added to get the error handlers to work with restplus
jwt._set_error_handler_callbacks(api)
ns = api.namespace('todo', description='TODO operations')
@ns.route('/access')
class ProductAccess(Resource):
@jwt_required
def post(self):
return "", 200
def get(self):
return "", 200
@app.route("/token")
def token():
return create_access_token(identity="test")
if __name__ == '__main__':
app.register_blueprint(api_v1)
print(app.url_map)
app.run(debug=True)
Doing some testing on this, it looks like your guess about python2 and python3 was correct. This works correctly under python3 but not under python2:
http POST :5000/todos/access
HTTP/1.0 401 UNAUTHORIZED
Content-Length: 44
Content-Type: application/json
Date: Wed, 18 Oct 2017 18:16:04 GMT
Server: Werkzeug/0.12.2 Python/3.6.2
{
"msg": "Missing Authorization Header"
}
http POST :5000/todos/access
HTTP/1.0 500 INTERNAL SERVER ERROR
Content-Length: 43
Content-Type: application/json
Date: Wed, 18 Oct 2017 18:24:06 GMT
Server: Werkzeug/0.12.2 Python/2.7.14
{
"message": "Internal Server Error"
}
I'm not sure why it is working in python3 and not python2 yet. Hopefully I can find some time to dig into this later this week. That said, I think the ideal situation would still be to see flask-restplus update their extension so it passes back errors to the flask error handlers.
Cheers!
EDIT: Here is the stacktrace for python2
Traceback (most recent call last):
File "/tmp/foo/venv/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/tmp/foo/venv/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/tmp/foo/venv/lib/python2.7/site-packages/flask_restplus/api.py", line 557, in error_router
return original_handler(e)
File "/tmp/foo/venv/lib/python2.7/site-packages/flask/app.py", line 1504, in handle_user_exception
assert exc_value is e
AssertionError
The problem that I am seeing in python2 with my hack applied stems from here: https://github.com/noirbizarre/flask-restplus/blob/master/flask_restplus/api.py#L583
My error handlers return a flask response, not a python dictionary, which ends up in default_data
and triggers a AttributeError: 'Response' object has no attribute 'get'
here:
https://github.com/noirbizarre/flask-restplus/blob/master/flask_restplus/api.py#L599
This in turn causes the original app error handler to be run here https://github.com/noirbizarre/flask-restplus/blob/master/flask_restplus/api.py#L567 and leads to the following stacktrace:
Traceback (most recent call last):
File "/tmp/foo/venv/lib/python2.7/site-packages/flask/app.py", line 1982, in wsgi_app
response = self.full_dispatch_request()
File "/tmp/foo/venv/lib/python2.7/site-packages/flask/app.py", line 1614, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/tmp/foo/venv/lib/python2.7/site-packages/flask_restplus/api.py", line 557, in error_router
return original_handler(e)
File "/tmp/foo/venv/lib/python2.7/site-packages/flask/app.py", line 1504, in handle_user_exception
assert exc_value is e
AssertionError
Funny enough, in python3 the exact same sequence happens. By registering our error handlers on the flask-restplus api object, we aren't actually having flask-restplus serve our error handlers. We are just setting up a situation where an exception is raised in the flask-restplus error handling, and that triggers flask-restplus to kick the error back up to the native flask error. I'm guessing the reason why this works with python3 and not python2 boils down to the subtle differences in how exceptions work between them.
Regardless, what I would really like to see is flask-restplus kicking the exception back up to the native flask error handlers, so that no magic needs to be done to use these extensions together.
Flask-restplus and python2.7 is also used in my project. Is there a solution to this problem now?
I am not aware of any changes that have not been outlined in this ticket. If flask-restful is still bypassing the built in flask error handlers (make sure you have app.config['PROPOGATE_EXCEPTIONS'] = true
), you may need to hack something onto flask-restful, or manually register the flask-jwt-extended error handlers to the flask-restful error system.
I am not entirely sure what exactly the issue is but, i came across the very same issue on Python 3.6.7, today while testing a simple CRUD app that has Flask-Restful + SQLAlchemy + Flask-JWT-extended.
If i keep DEBUG
as True, everything goes fine, but as soon I put the config mode to Production where my secret key, expiry and the DEBUG
changes from Dev.
For eg.
class Development:
DEBUG = True
SECRET_KEY = "changeme"
JWT_ACCESS_TOKEN_EXPIRES = False
SQLALCHEMY_DATABASE_URI = 'postgresql://postgres:postgres'\
'@localhost/examples'
# Suppress SQLALCHEMY_TRACK_MODIFICATIONS overhead warning
SQLALCHEMY_TRACK_MODIFICATIONS = False
class Production(Development):
DEBUG = False
SECRET_KEY = "sup3rs3cr3tk3yf0rPr0duct10N"
SQLALCHEMY_DATABASE_URI = os.getenv(
'SQLALCHEMY_DATABASE_URI',
'postgresql://localhost/examples'
)
JWT_ACCESS_TOKEN_EXPIRES = timedelta(7)
class Testing(Development):
DEBUG = True
TESTING = True
SECRET_KEY = "testsecret"
JWT_ACCESS_TOKEN_EXPIRES = False
SQLALCHEMY_DATABASE_URI = 'postgresql://postgres:postgres'\
'@localhost/examples_test'
# Suppress SQLALCHEMY_TRACK_MODIFICATIONS overhead warning
SQLALCHEMY_TRACK_MODIFICATIONS = False
As you can see, I kept DEBUG
as True for dev and test config, due to which I got no unit test breaks (I feel betrayed :frowning_face: ).
However, as the DEBUG
is False
in Production, it just returns 500 : Internal Server Error
for flask_jwt_extended.exceptions.NoAuthorizationError: Missing Authorization Header
Completely out of curiosity, I changed the Production.DEBUG
to True
and 500
is gone and as expected, there is a valid 401 : Missing Authorization Header
.
Any idea why this happens, and where would the culprit to this cause be? :thinking:
Here is a traceback of the 500:
Traceback (most recent call last):
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask/app.py", line 1813, in full_dispatch_request
rv = self.dispatch_request()
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask/app.py", line 1799, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask_restful/__init__.py", line 480, in wrapper
resp = resource(*args, **kwargs)
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask/views.py", line 88, in view
return self.dispatch_request(*args, **kwargs)
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask_restful/__init__.py", line 595, in dispatch_request
resp = meth(*args, **kwargs)
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 102, in wrapper
verify_jwt_in_request()
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 31, in verify_jwt_in_request
jwt_data = _decode_jwt_from_request(request_type='access')
File "/home/madboy/.virtualenvs/examples-rest/lib/python3.6/site-packages/flask_jwt_extended/view_decorators.py", line 284, in _decode_jwt_from_request
raise NoAuthorizationError(errors[0])
flask_jwt_extended.exceptions.NoAuthorizationError: Missing Authorization Header
Yeah, for whatever reason when you are using flask-restful you will need to set app.config['PROPAGATE_EXCEPTIONS'] = True
in order for the error handlers to properly work. I would expect that to fix your issue.
Wow, super duper quick reply :clap:
Interesting nonetheless :smile:
set app.config['PROPAGATE_EXCEPTIONS'] = True
=> Works :+1:
It works for me in python 3.6 with Blueprints
Yeah, for whatever reason when you are using flask-restful you will need to set
app.config['PROPAGATE_EXCEPTIONS'] = True
in order for the error handlers to properly work. I would expect that to fix your issue.
I had similar issue, and after a little bit of digging through code I raised issue in Flask-RESTful about this: https://github.com/flask-restful/flask-restful/issues/796
I am not sure that enabling PROPAGATE_EXCEPTIONS in production environment is the right way to go, since that way we would leave any actual exceptions without registered handlers completely unhandled.
I'm not getting any luck with the app.config['PROPAGATE_EXCEPTIONS'] = True
What am I missing?
from flask_restplus import Resource, Api
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_jwt_extended import JWTManager
import base64
import os
app = Flask(__name__)
POSTGRES = {
'user': os.environ.get('DATABASE_USER'),
'pw': os.environ.get('DATABASE_PW'),
'db': os.environ.get('DATABASE_NAME'),
'host': os.environ.get('DATABASE_HOST'),
'port': os.environ.get('DATABASE_PORT'),
}
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://%(user)s:%(pw)s@%(host)s:%(port)s/%(db)s' % POSTGRES
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = base64.b64decode(os.environ.get('TB_JWT_SECRET_KEY'))
app.config['JWT_ALGORITHM'] = 'HS512'
app.config['JWT_IDENTITY_CLAIM'] = 'sub'
app.config['PROPAGATE_EXCEPTIONS'] = True
app.url_map.strict_slashes = False
db = SQLAlchemy(app)
jwt = JWTManager(app)
from .main.v1 import blueprint as v1, url_prefix
migrate = Migrate(app, db)
@app.route('/')
def redirect_to_latest_api_version():
"""Redirects to /v1"""
return redirect(url_prefix, code=302)
api = Api(app)
jwt._set_error_handler_callbacks(api)
app.register_blueprint(v1)```
@Jonyorker Flask restplus has a different issue that causes problems with native flask errorhandlers: https://github.com/noirbizarre/flask-restplus/issues/340. You can work around that for the time being with the details here: https://github.com/vimalloc/flask-jwt-extended/issues/86#issuecomment-335509456
RIght, but I've added in the jwt._set_error_handler_callbacks(api) and the progapge_exceptions and I'm still getting the error 500 instead of whatever 40* it should be.
Are you using python3? That work around doesn't work for python2 for whatever reason.
3.7
Hrm, I'm not sure right off hand then. I'll try to take a closer when I have some downtime :+1:
I appreciate it. Up for whatever you need me to provide you to debug it.
Thanks!
Yeah, for whatever reason when you are using flask-restful you will need to set
app.config['PROPAGATE_EXCEPTIONS'] = True
in order for the error handlers to properly work. I would expect that to fix your issue.I had similar issue, and after a little bit of digging through code I raised issue in Flask-RESTful about this: flask-restful/flask-restful#796
I am not sure that enabling PROPAGATE_EXCEPTIONS in production environment is the right way to go, since that way we would leave any actual exceptions without registered handlers completely unhandled.
I agree that this is not the best solution although it works. Are there any plans to fix this or is PROPAGATE_EXCEPTIONS the official solution now?
@matusbielik As the PROPAGATE_EXCEPTIONS
issues is part of flask-restful, there isn't anything I can do about it in this extension. I would suggest following up with that ticket in flask-restful to see if they are planning to resolve that.
Setting app.config['PROPAGATE_EXCEPTIONS'] = True
Didn't work for me :(
Have you gone over the other solutions outlined in this ticket, for example if you are using flask-restplus? If none of them are working for you, please open a new ticket with all the details you can. Specifically, what version of flask and flask-jwt-extension you are using, what other flask extensions you are running, and a minimum example which demonstrates this behavior.
I'm using flask-restplus
and I have gone with all the suggested workarounds and neither of them worked for me
This is my main file
import os, sys
import config
import logging
import ast
import time
import datetime
from prometheus_client import (
Summary, Histogram, generate_latest, CollectorRegistry)
from flask_jwt_simple import JWTManager
from flask_mongoengine import MongoEngine
from flask_restplus import Api
import logging.config
from flask_compress import Compress
db = MongoEngine()
jwt = JWTManager()
compress = Compress()
# application factory
def create_app(config):
# create application instance
app = Flask(__name__)
#TODO: Check the problem with config
app.config.from_object(config)
app.config['DEBUG'] = True
###### MongoDB ########
app.config['MONGODB_SETTINGS'] = {
'db': 'wallet',
'host': 'mongodb://mongoadmin:mongopass@localhost:27017/wallet?authSource=admin'
}
db.init_app(app)
# Setup the Flask-JWT-Extended extension
#TODO: Move it to Config File
app.config['JWT_ALGORITHM'] = 'RS256'
app.config['JWT_PUBLIC_KEY'] = open("./keys/public.key", "r").read()
app.config['JWT_DECODE_AUDIENCE'] = 'ledger'
app.config['JWT_IDENTITY_CLAIM'] = 'sub'
app.config['PROPAGATE_EXCEPTIONS'] = True
jwt.init_app(app)
compress.init_app(app)
from .apis import blueprint as api
app.register_blueprint(api, url_prefix='/api/v1')
api = Api(app=app, doc='/api/v1')
# This is the hack I added to get the error handlers to work with restplus
jwt._set_error_handler_callbacks(api)
# Pass Flask logger to Gunicorn logger
# gunicorn_logger = logging.getLogger('gunicorn.error')
# app.logger.handlers = gunicorn_logger.handlers
# app.logger.setLevel(gunicorn_logger.level)
# app.logger.addHandler(logging.StreamHandler(sys.stdout))
# app.logger.setLevel(logging.DEBUG)
logging.config.fileConfig('./conf/logging.conf')
logger = logging.getLogger(__name__)
register_jwt_callbacks()
return app
def register_jwt_callbacks():
"""Set up custom behavior for JWT based authentication.
Return
------
None
"""
# @jwt.user_loader_callback_loader
# def user_loader_callback(identity):
# """This function is going to be called everytime a user tries
# to access a protected endpoint.
# Args
# ----
# identity (User.username): This is the exact identity passed
# to `create_access_token` in auth.py
# Return
# ------
# User instance
# """
# return User.find_by_identity(identity)
# TODO: should this method be taking in `self` as arg?
@jwt.unauthorized_loader
def jwt_unauthorized_callback(self):
"""We are just overriding `@jwt.unauthorized_loader`
to return a custom error message
"""
response = {
'error': {
'message': 'Your auth token or CSRF token are missing'
}
}
# HTTP STATUS CODE 401 stands for Unauthorized Access
return jsonify(response), 401
@jwt.expired_token_loader
def jwt_expired_token_callback():
"""We are just overriding `@jwt.expired_token_loader`
to return a custom error message
"""
response = {
'error': {
'message': 'Your auth token has expired'
}
}
return jsonify(response), 401
return None
Are you using python3? The work around linked above with jwt._set_error_handler_callbacks
does not work with python2. If that is not the issue please create a new issue that has a minimal example that I can run to troubleshoot further.
Yes, I'm using python 3.7
I'm going to lock this issue for now, as adding more comments on here only makes it harder to find the helpful solutions linked in this ticket.
As a summary, this issue is not caused by flask-jwt-extended, but rather by other flask extensions not working correctly with flask errorhandlers, a native feature in flask. Because of this, there is not a lot I can do on my end to fix their issues, I can only help try to find workarounds.
If you are running into this error, I would start by looking at these comments:
https://github.com/vimalloc/flask-jwt-extended/issues/86#issuecomment-444983119 : Flask-RESTful
https://github.com/vimalloc/flask-jwt-extended/issues/141#issuecomment-937963926: Flask-RESTful
https://github.com/vimalloc/flask-jwt-extended/issues/86#issuecomment-335509456 : Flask-RESTPlus
If you are still having issues, please open a new issue with a minimal complete and verifiable example to help me dig into this further. I will make sure to link any updates back here so the information is easily available.
Thanks! :+1:
It looks to me that this part is not yet implemented:
The upper code raises many different exceptions, but I don't see any code returning the errors (my own default error handling of restplus triggers 500 error every time).
The documentation states that:
Default callbacks are all provided, but never returned.
Am I wrong?
Thanks, Meir Tseitlin