Python REST API flask - python-3.x

I have a script which accepts arguments as JSON and gets executed. However I need to call the script through FLASK from a third party application POST method.
My Script is as below
import argparse
import os
import win32security, win32con
import ntsecuritycon as con
import pywintypes
import json
import sys, json
# Set up the argument parser
parser = argparse.ArgumentParser()
parser.add_argument('JSON', metavar='json',type=str, help='JSON to parse')
args = parser.parse_args()
# Get JSON data
json_str = args.JSON
# Parse JSON data
json_data = json.loads(json_str)
path = os.path.join(json_data["parentdir"], json_data["dirname"])
#print(json_data["parentdir"])
#print(json_data["dirname"])
os.mkdir(path)
The above scripts works when i run
python test.py "{\"parentdir\": \"D:\\Important\", \"dirname\": \"test\"}"
How I can call the same script as HTTP POST from a 3rd party API through flask. I have got idea on creating flask script but not sure how to pass the parameters to the script through flask route api
I tried below :
#app.route('/', methods=['POST'])
def hello_world():
#parentdir = request.values.get("parentdir")
#dirname = request.values.get("dirname")
#print(dirname)
#print(parentdir)
parentdir = request.get_json("parentdir")
dirname = request.get_json("dirname")
path = os.path.join(parentdir, dirname)
os.mkdir(path)
if __name__ == '__main__':
app.run(debug=True)
Error - Failed to decode JSON object: Expecting value: line 1 column 1
Please help.

You create a flask route witch receives parentdir and dirname as parameters.
The route can execute the part of your script that create the dir.
import locale
import os
from flask import Flask, request, jsonify
# Create Flask APP
app = Flask(__name__)
#app.route('/', methods=['POST'])
def hello_world():
parentdir = request.json.get("parentdir")
dirname = request.json.get("dirname")
path = os.path.join(parentdir, dirname)
# makedirs create directory recursively
os.makedirs(path)
return jsonify()
if __name__ == "__main__":
app.run(port=5000, host="0.0.0.0", use_reloader=True)
The postman request
curl --location --request POST 'http://0.0.0.0:5000/' \
--header 'Content-Type: application/json' \
--data-raw '{
"parentdir": "okn",
"dirname": "okn"
}'

Related

How do I solve page not found error in flask rest api

I have developed a flask application that returns some text from OPEN-AI by giving some inputs.
But unfortunately the rest API in my application returns 404 error.
Here is the code:
from crypt import methods
from warnings import catch_warnings
from flask import Flask,request
from flask_cors import CORS
import flask
import openai
from flask_restful import Api,Resource
import base64
import json
#Init
app = Flask(__name__)
CORS(app)
api = Api(app)
app.run(host='0.0.0.0',port=8080)
#OPENAI CREDENTIALS
openai.api_key = ""
#Functions
class advert(Resource):
def post(self):
try:
request_body=request.json
A=request_body["data"]
adprompt = "Write an advertisement for " + A
response = openai.Completion.create(
engine="text-davinci-002",
prompt=adprompt,
temperature=0.7,
max_tokens=70,
top_p=1.0,
n=1
)
json_advert = json.loads(str(response))
advert_output = json_advert['choices'][0]['text']
to_return= json_advert = json.loads(str(advert_output))
return to_return,200
except:
return ({"ERROR":"Error Occured"}),500
#Mapping
api.add_resource(advert,'/data',methods=['POST'])
if __name__=='__main__':
app.run(debug=True)
This is the response i get:
192.168.1.21 - - [24/Nov/2022 11:52:59] "POST /data HTTP/1.1" 404 -
I've tried changing the port and endpoints, nothing helped .
How to solve this.
Your problem is at this line,
app.run(host='0.0.0.0',port=8080)
take it out, then add the parameters into the last line,
if __name__=='__main__':
app.run(debug=True, host='0.0.0.0',port=8080)
A bit more explanation, when the code hits app.run, it actually starts the server and not running the line api.add_resource. Hence, no path was configured.

request an API based on sql query

It´s muy first time developing an API. It's very simple. here is my code:
from flask import Flask, Response
from flask import request
from flask import jsonify
import pyodbc
from sqlalchemy import create_engine,Integer
import pandas as pd
import urllib
app = Flask(__name__)
params = urllib.parse.quote_plus("DRIVER={SQL Server Native Client 11.0};"
"SERVER=xxx.xx.x.x;"
"DATABASE=xxxxx;"
"UID=xxxx;"
"PWD=xxxx")
engine = create_engine('mssql+pymssql://xxxx:xxxx#xxx.xx.x.x/xxxx')
sql_talle = "RSCV_TALLE_PARA_CADA_MARCA.sql"
fd1 = open(sql_talle, 'r')
sqlFile1 = fd1.read()
fd1.close()
DF1 = pd.read_sql_query(sqlFile1,engine)
DF1.insert(14, 'PROVEEDOR', DF1.pop('PROVEEDOR'))
periodo=DF1['YEARMONTH_DATE'].drop_duplicates()
NIKE=DF1.loc[DF1['MARCA'] == 'NIKE']
NIKE=NIKE.to_dict('records')
#app.route('/NIKE',methods = ['GET'])
def show_codigo_Agrupador():
if request.method == 'GET':
response = jsonify({'NIKE':NIKE})
response.status_code = 200
return response
if __name__ == "__main__":
app.run(debug=True)
it´s working fine!
when I run the .py on a terminal I get that it´s Running on http://127.0.0.1:5000
After that I try to do a request on another .py, simulating an external user:
import requests
import json
url = 'http://127.0.0.1:5000/NIKE'
r=requests.get(url)
response=r.text
j=response.json()
print(j)
but I get this error:
Traceback (most recent call last):
File "c:\Users\mvazquez\DABRA\FLASK_API\prueba_request_api.py", line 7, in <module>
j=response.json()
AttributeError: 'str' object has no attribute 'json'
I have these questions:
what am I doing wrong here?
my data is based on an sql query, I need to run the script every day to have refresehed data or it is refreshed when request is done? (sorry if it's stupid, I have no idea about API)
thanks in advance!

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)

Unable to decode "devanagari text" passed as URL param

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.

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)

Resources