Unable to decode "devanagari text" passed as URL param - python-3.x

My Python Flask App is unable to decode the devanagari text eg:"सिंगापूर" that I pass as urlparam from my postman. If I sen english text it handles it well.
My PostMan query :
GET http://localhost:5000/getSimilarWord/सिंगापूर
from flask import Flask
from flask_restful import Resource, Api
class DevnagriText(Resource):
def get(self, textInput):
print("parsed String is :",textInput)
return {'text': textInput}
api.add_resource(DevnagriText, '/getWord/<string:textInput>')
if __name__ == '__main__':
app.run(debug=True)
The output I get on console is
{
"text": "\u00818"
}
Instead of
{
"text": "सिंगापूर"
}

You need to prevent the response from forcing ASCII: app.config['JSON_AS_ASCII'] = False
So in your example:
from flask import jsonify, Flask
from flask_restful import Resource, Api
app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False
api = Api(app)
class DevnagriText(Resource):
def get(self, textInput):
print("parsed String is :",textInput)
return jsonify(text=textInput)
api.add_resource(DevnagriText, '/getWord/<string:textInput>')
if __name__ == '__main__':
app.run(debug=True)
But, this doesn't really matter, it will all get interpreted the same way if it gets read into Python or JavaScript.

Related

when i try to run the sample program of flask-restplus getting connection failed when we use curl command such as curl http://127.0.0.1:5000/hello

from flask import Flask, request
from flask_restplus import Resource, Api
app = Flask(name)
api = Api(app)
todos = {}
#api.route('/string:todo_id')
class TodoSimple(Resource):
def get(self, todo_id):
return {todo_id: todos[todo_id]}
def put(self, todo_id):
todos[todo_id] = request.form['data']
return {todo_id: todos[todo_id]}
if name == 'main':
app.run(debug=True)

flask_apispec library makes Flask app to crash when use_kwargs decorator is used

I am building a Restful API in Python 3.8 using flask_restful, flask_apispec, and marshmallow. When I enable use_kwargs decorator my app is crushing on a POST with TypeError: post() takes 1 positional argument but 2 were given
I'd appreciate any help in solving this bug.
# requirements.txt
aniso8601==9.0.1
apispec==5.1.1
certifi==2021.10.8
charset-normalizer==2.0.7
click==8.0.3
Flask==2.0.2
flask-apispec==0.11.0
Flask-RESTful==0.3.9
gunicorn==20.1.0
idna==3.3
itsdangerous==2.0.1
Jinja2==3.0.2
MarkupSafe==2.0.1
marshmallow==3.14.0
pytz==2021.3
requests==2.26.0
six==1.16.0
tableauserverclient==0.17.0
urllib3==1.26.7
webargs==8.0.1
Werkzeug==2.0.2
from apispec import APISpec
from flask import Flask, request
from flask_restful import Resource, Api
from apispec.ext.marshmallow import MarshmallowPlugin
from flask_apispec.extension import FlaskApiSpec
from marshmallow import Schema, fields, post_load, ValidationError
from flask_apispec.views import MethodResource
from flask_apispec import use_kwargs, marshal_with
app = Flask(__name__) # Flask app instance initiated
api = Api(app) # Flask restful wraps Flask app around it.
app.config.update({
'APISPEC_SPEC': APISpec(
title='Kube Controller',
version='v1',
plugins=[MarshmallowPlugin()],
openapi_version='2.0.0'
),
'APISPEC_SWAGGER_URL': '/swagger/', # URI to access API Doc JSON
'APISPEC_SWAGGER_UI_URL': '/swagger-ui/' # URI to access UI of API Doc
})
docs = FlaskApiSpec(app)
class AwesomeRequestSchema(Schema):
api_type = fields.String(required=True)
#post_load
def create(self, data, **kwargs):
return MyAPI(**data)
class MyAPI:
def __init__(self, api_type):
self.api_type = api_type
self.message = "hi"
class AwesomeAPI(MethodResource, Resource):
#use_kwargs(AwesomeRequestSchema)
#marshal_with(AwesomeRequestSchema, code=200, description='Something created')
def post(self):
"""
POST
"""
try:
schema = AwesomeRequestSchema()
data = schema.load(request.json)
print(data.api_type)
return request.json
except ValidationError as err:
return err.messages
api.add_resource(AwesomeAPI, '/')
docs.register(AwesomeAPI)
if __name__ == '__main__':
app.run(debug=True)
Thanks!
I had the same issue. The use_kwargs decorator will try to populate and inject the AwesomeRequestSchema object into the post() method: https://flask-apispec.readthedocs.io/en/latest/api_reference.html#flask_apispec.annotations.use_kwargs
To fix, replace
def post(self):
with
def post(self, populated_request_object):

How to return 401 in flask despite authorization

I am new to flask and I want to return 401 error, I am not using authentication, I am simply using a parameter api_key to check whether the user is authenticated.
I've tried abort(401) and return false, but it returns error 400 'Bad Request', is this the default way it returns a 401. Or is there a different way to do this?
My Code:
import flask
from flask import jsonify, request, Response
from flask_cors import CORS, cross_origin
from GoogleNews import GoogleNews
googlenews = GoogleNews()
googlenews.set_lang('en')
googlenews.set_period('1d')
googlenews.set_encode('utf-8')
app=flask.Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
#cross_origin()
#app.route('/', methods=["GET"])
def return_news():
API_KEY = request.args['api_key']
if API_KEY == "xyz":
googlenews.get_news('TECHNOLOGY')
return jsonify(googlenews.result(True)[0:4])
else:
return Response(response="Unauthorized", status=401)
Thankyou
instead, try flask.Response object.
from flask import Flask, Response
app = Flask(__name__)
#app.route("/abort")
def abort():
return Response(response="Unauthorized", status=401)
app.run()
without the actual code it is hard to tell, but I think it is not using the flask abort() but the python internal abort() function.
Check the code below:
import flask
app = flask.Flask("aborter")
#app.route("/abort")
def abort():
return flask.abort(401)
if __name__ == '__main__':
app.run()
Happy Coding

Pass filepath as parameter to a URL in FLASK(Python)

I want to build an api which accepts a parameter from the user which is a filepath and then process the file given in that path. The file to be processed is already in the server where the api will be running.
As of now, I have written an api where I have hardcoded the filepath in my code which runs the api. Now, I want to configure my api in such a way that accepts a filepath from the user. My api should accept the path as a parameter and process the file that has been given in the path.
The api code is as follows:
The convert function returns the category of the file.
import ectd
from ectd import convert
from flask import Flask, request
from flask_restful import Resource, Api
#from flask.views import MethodView
app = Flask(__name__)
api = Api(app)
#convert(r'D:\files\67cecf40-71cf-4fc4-82e1-696ca41a9fba.pdf')
class ectdtext(Resource):
def get(self, result):
return {'data': ectd.convert(result)}
#api.add_resource(ectdtext, '/ectd/<result>')
categories=convert(r'D:\files\6628cb99-a400-4821-8b13-aa4744bd1286.pdf')
#app.route('/')
def returnResult():
return categories
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000)
So, I want to make changes to this code to accept a parameter from the user which will be a filepath and the convert function will process that filepath. I want to know how to make my api accept a filepath parameter from the user.
Trial with requests.args.get:
import ectd
from ectd import convert
from flask import Flask, request
from flask_restful import Resource, Api
#from flask.views import MethodView
app = Flask(__name__)
api = Api(app)
#convert(r'D:\files\67cecf40-71cf-4fc4-82e1-696ca41a9fba.pdf')
class ectdtext(Resource):
def get(self, result):
return {'data': ectd.convert(result)}
#api.add_resource(ectdtext, '/ectd/<result>')
#app.route('/')
def returnResult():
categories=convert(r'D:\files\'.format(request.args.get('categories')))
return categories
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000)
results in error :
"RuntimeError: Working outside of request context.
This typically means that you attempted to use functionality that needed
an active HTTP request. Consult the documentation on testing for
information about how to avoid this problem."
PRESENT SCENARIO:
I am able to post a filepath to the url. My question is now how do I use this posted url with filepath in my code to trigger my function that takes in the filepath and processes the file. Code to post the filepath:
import ectd
from ectd import convert
from flask import Flask, request
from flask_restful import Resource, Api
#from flask.views import MethodView
app = Flask(__name__)
api = Api(app)
class ectdtext(Resource):
def get(self, result):
return {'data': ectd.convert(result)}
#api.add_resource(ectdtext, '/ectd/<result>')
categories=convert('/home/brian/ajay/files/5ca21af9-5b67-45f8-969c-ae571431c665.pdf')
#app.route('/')
def returnResult():
return categories
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def get_dir(path):
return path
##app.route('/get_dir/<path>')
#def get_dir(path):
# return path
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000)

Flask-RESTful API does not return a dictionary as a json format

I am using flask-restful api. When I change debug=True to debug=False I don't receive data as a json format. This is the example code:
from flask import Flask, jsonify, Response
from flask_restful import Resource, Api
import json
app = Flask(__name__)
# Create the API
api = Api(app)
#app.route('/')
def index():
return "HELLO WORLD"
class tests(Resource):
def get(self):
#return json.dumps({"A":1, "B":2}, sort_keys=False, indent=4)
return jsonify({"A":1, "B":2})
api.add_resource(tests, '/<string:identifier>')
if __name__ == '__main__':
app.run(debug=False)
with json.dumps(dictionary) it returns:
"{\n \"A\": 1,\n \"B\": 2\n}"
but I expect:
{
"A": 1,
"B": 2
}
The defined resource is the cause of your issue since it requires that you pass "self" to the functions inside. Defining the class as an object instead of a resource will circumvent this while still allowing you to pass arguments to the function, such as id, as seen in get_tests_id().
from flask import Flask, json
from flask_restful import Api
app = Flask(__name__)
# Create the API
api = Api(app)
#app.route('/')
def index():
return "HELLO WORLD"
class Tests(object):
# function to get all tests
#app.route('/tests', methods=["GET"])
def get_tests():
data = {"A": 1, "B": 2}
return json.dumps(data, sort_keys=False, indent=4), 200
# function to get tests for the specified id("A" or "B" in this case)
#app.route('/tests/<id>', methods=["GET"])
def get_tests_id(id):
data = {"A": 1, "B": 2}
return json.dumps({id: data.get(id)}, sort_keys=False, indent=4), 200
if __name__ == '__main__':
app.run(debug=False)
Assuming you are running the API on port 5000 and testing it from the host, the following URLs can be used to access your data from a web browser:
'localhost:5000/tests' - URL to get all tests
'localhost:5000/tests/A' - URL to get tests with id="A"
'localhost:5000/tests/B' - URL to get tests with id="B"

Resources