flask request from own site - python

#app.route('/bInfo', methods = ['POST', 'GET'])
def create():
result = []
....
return jsonify(result)
I would like to make a request from '/bInfo'
#app.route('/')
def index():
js = request.json('/bInfo') #this is not working
print(js)
return render_template('index.html')
How could I do that?

Anyways, you can do one of the following:
1. Refactor getting the contents of /bInfo outside of the route itself.
This is mostly self-explanatory. You're just moving the code that makes the contents outside, and calling it in both routes.
2. Request the page you need using requests.get() from requests and use that.
You'd need to request from localhost, and this will make one route rely on the other. Option 1 is much safer.

Related

How to trigger a function in a Python REST API

I have a local Flask REST API that runs some queries and return JSON responses. My idea is to send a POST request to the API and trigger a function capable of updating my database.
The inspiration behind this idea is the way we create resources in a public Cloud. Example: let's say we create a Virtual Cloud Network on any public cloud. The cloud architecture has several APIs for each module and the creation of a VCN trigger the creation of NAT Gateways, Route Tables, Security Lists, Subnets and so on through a GET or POST request to each resource type.
So inspired by this architecture, I want to do this in a simplified and local manner. My first guess is to use the multiprocessing library to spawn processes as soon as a request hits the endpoint, but I don't know if this the best way or a good practice. Can anyone give me an idea on how to do this or if I am in the right path.
i dont really understand... but i can try to help you,
the following code is a code that is the same API but you can get different responses, i dont know what are you going to do with so i added my own examples.
from flask import *
app = Flask(__name__)
#app.route('/api/route/1', methods=['POST'])
def api_1():
if request.method == 'POST':
# Some code here
#Eg:
# data = request.get_json()
# print(data)
#return data.thing
#OR
return "Hello from route 1"
#app.route('/api/route/2', methods=['POST'])
def api_2():
if request.method == 'POST':
# Some code here
#Eg:
# data = request.get_json()
# print(data)
#return data.thing
#OR
return "Hello from route 2"
#app.route('/api/route/3', methods=['POST'])
def api_3():
if request.method == 'POST':
# Some code here
#Eg:
# data = request.get_json()
# print(data)
#return data.thing
#OR
return "Hello from route 3"
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8000, debug=True)

Unable to redirect to method url through action prop in Gather method twilio

I have been trying to create a flow for sending back modified output to user on basis of the key press.
For this, I am using the twilio's Api.
Before I go ahead with my problem I will share the two pieces of code from Route.py and CallResponse.py
app = Flask(__name__)
logger = lh.log_initializer()
#app.route("/Aresponse", methods=['GET', 'POST'])
def ReceivedA():
"""Respond to incoming requests."""
logger.debug("Starting ReceivedA flow| name:" + __name__)
resp = tcr.RoutedReceivedA()
return str(resp)
if __name__ == "__main__":
# logger.debug("In routing main")
app.run(debug=True, host='0.0.0.0', port=80, threaded=True)
Below is the code of CallResponse.py
app = Flask(__name__)
logger = lh.log_initializer()
def RoutedReceivedA():
"""Respond to incoming requests."""
resp = VoiceResponse()
resp.say("Hello Monkey")
# Say a command, and listen for the caller to press a key. When they press
# a key, redirect them to /user-input-key.
logger.debug('Starting call receiving process|name:' + __name__)
A_num = Gather(numDigits=2, action="/user-A-input", method="POST")
A_num_entered = str(A_num) #there is surely something not right with this line, but I am hardly bothered about this right now
A_num.say("Please press a key to register your response")
logger.debug("After taking A number from user| A num:" + A_num_entered)
resp.append(A_num)
return str(resp)
#app.route("/user-A-input", methods=['GET', 'POST'])
def UserAInput():
"""Handle key press from a user."""
# Get the digit pressed by the user
#The below logs are not printed, so somehow this method isn't called
logger.debug('before considering user input in route')
route_num = request.values.get('Digits', None)
logger.debug('In side UserRouteInput| route_num:' + route_num)
return route_num
So when I start the app, I hit the url http://xyz.abc.io/AResponse, the request is first received in the Route.py to the ReceivedA() method, which internally calls the RoutedReceivedA(), which prints the log
Starting call receiving process|name:...
after which I am expecting it to redirect to the method UserAInput, as I am passing the method URL through the action property in Gather method of twilio library, but it isn't calling that method. To confirm that I have also written a debug log, which never prints itself.
The later pain would be to get the user inputted value and pass it to another method (as it would make an api call on basis of that input) which I am not bothered about right now.
I have tried understanding the flask working to verify if there is something I am doing wrong with that. I am missing something here but unknowingly I am not able to understand what.
Although I am trying to find a solution myself, I can surely use some help.
P.S: I tried replicating the issue using the sample gather code on twilio website, by creating a maincall.py which internally calls hello_monkey() method of the twilios sample code, which then calls handle-key. Even in this case it wasn't routing to the handle_key() method. However it was working when I was directly calling the hello_monkey() through the API call. I believe I am surely misunderstanding some concept of flask routing. Really frustrated.
I found the solution to the problem. I need to
#app.route("/user-A-input", methods=['GET', 'POST'])
method in Route.py instead of CallResponse.py
It's probably because it is using the instance of flask object which was created in the Route.py. I still need to look into detail, like how can I make it work by keeping the UserAInput method in CallResponse.py

Calling Python file in an Ajax Call

So I have established a pretty decent understanding of the simple architecture of an angularjs app, calling $http and posting to a php page, and receiving data back.
What I'm wondering, is how to do the same type of function with python. Is it possible to have python act the same, with self contained script files that accept post data and echo json back?
$username = $_POST['username'];
type variable assignment at the beginning of the script, and:
echo json_encode(response);
type response.
I'm wanting to use Python for some Internal Tools for my company, as it offers better libraries for remotely running powershell scripts (as the tools are all linux hosted) and overall just has libraries that fit my needs. I'm just having a difficult time finding a concise answer to how this could be set up.
---EDIT------
So I set up a quick example using the information below.
the angular:
var app = angular.module("api");
app.controller("MainController", ["$scope","$http",MainController]);
function MainController($scope,$http){
$http.post('/api',{test: "hello"})
.then(function(response){
console.log(response.data);
})
}
The flask:
from flask import Flask, request
import json
app = Flask(__name__)
#app.route('/api', methods=['POST', 'GET'])
def api():
if request.method == 'POST':
request.data
return 'You made it' # Just so I originally could see that the flask page
if __name__ == "__main__":
app.run()
I'm getting a 404 for that URL. If I change the angular to look at 'localhost:5000/api' (where my flask app is running),it gives me the error of "Unsupported URL Type".
I am seeing when I do the first case, it tries to look at http://localhost/api , which is correct! except for the port. Which is why I tried to specify the port.
Any suggestions for a next step?
Use flask.
You could host your app on a flask "server" and return the content you'd like too with a python processing.
http://flask.pocoo.org/
Use the documentation to setup a route where you'll POST your data using jquery or whatever, then on the route you can do your python stuff and return a JSON to your angular app if you need to.
from flask import request
#app.route('/test', methods=['POST', 'GET'])
def test():
if request.method == 'POST':
print request.data['your_field']
return your_json_data

Flask redirect from outside API functions

I have a helper method in a Flask app that is used by several endpoints to get a resource. To avoid having multiple redirect_url calls everywhere, I want to be able to redirect from just this helper method. Throwing a RequestRedirect exception as shown here correctly returns a 301 response, but doesn't set the Content-Location error. To get around this, I added a after_this_request hook that sets the url for that response.
This seems to work correctly, but I was wondering if theres a more elegant way to go about it.
Anonymized helper method:
def get_resource(resource_id):
try:
# Some logic
except:
#after_this_request
def add_header(response):
response.headers['Content-Location'] = url
return response
raise RequestRedirect(new_url='/')
If it is outside of your api, typically you would redirect to a 404 page. Here's a sample:
#app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404

Calling flask restful API resource methods

I'm creating an API with Flask that is being used for a mobile platform, but I also want the application itself to digest the API in order to render web content. I'm wondering what the best way is to access API resource methods inside of Flask? For instance if I have the following class added as a resource:
class FooAPI(Resource):
def __init__(self):
# Do some things
super(FooAPI, self).__init__()
def post(self, id):
#return something
def get(self):
#return something
api = Api(app)
api.add_resource(FooAPI, '/api/foo', endpoint = 'foo')
Then in a controller I want:
#app.route("/bar")
def bar():
#Get return value from post() in FooAPI
How do I get the return value of post() from FooAPI? Can I do it somehow through the api variable? Or do I have to create an instance of FooAPI in the controller? It seems like there has to be an easy way to do this that I'm just not understanding...
The obvious way for your application to consume the API is to invoke it like any other client. The fact that the application would be acting as a server and a client at the same time does not matter, the client portion can place requests into localhost and the server part will get them in the same way it gets external requests. To generate HTTP requests you can use requests, or urllib2 from the standard library.
But while the above method will work just fine it seems overkill to me. In my opinion a better approach is to expose the common functionality of your application in a way that both the regular application and the API can invoke. For example, you could have a package called FooLib that implements all the shared logic, then FooAPI becomes a thin wrapper around FooLib, and both FooAPI and FooApp call FooLib to get things done.
Another approach is to have both the app and API in the same Flask(-RESTful) instance. Then, you can have the app call the API methods/functions internally (without HTTP). Let's consider a simple app that manages files on a server:
# API. Returns filename/filesize-pairs of all files in 'path'
#app.route('/api/files/',methods=['GET'])
def get_files():
files=[{'name':x,'size':sys.getsizeof(os.path.join(path,x))} for x in os.listdir(path)]
return jsonify(files)
# app. Gets all files from the API, uses the API data to render a template for the user
#app.route('/app/files/',methods=['GET'])
def app_get_files():
response=get_files() # you may verify the status code here before continuing
return render_template('files.html',files=response.get_json())
You can push all your requests around (from the API to the app and back) without including them in your function calls since Flask's request object is global. For example, for an app resource that handles a file upload, you can simply call:
#app.route('/app/files/post',methods=['POST'])
def app_post_file():
response=post_file()
flash('Your file was uploaded succesfully') # if status_code==200
return render_template('home.html')
The associated API resource being:
#app.route('/api/files/',methods=['POST'])
def post_file():
file=request.files['file']
....
....
return jsonify({'some info about the file upload'})
For large volumes of application data, though, the overhead of wrapping/unwrapping JSON makes Miguel's second solution preferrable.
In your case, you would want to call this in your contoller:
response=FooAPI().post(id)
I managed to achieve this, sometimes API's get ugly, in my case, I need to recursively call the function as the application has a extremely recursive nature (a tree). Recursive functions itself are quite expensive, recursive HTTP requests would be a world of memory and cpu waste.
So here's the snippet, check the third for loop:
class IntentAPI(Resource):
def get(self, id):
patterns = [pattern.dict() for pattern in Pattern.query.filter(Pattern.intent_id == id)]
responses = [response.dict() for response in Response.query.filter(Response.intent_id == id)]
return jsonify ( { 'patterns' : patterns, 'responses' : responses } )
def delete(self, id):
for pattern in Pattern.query.filter(Pattern.intent_id == id):
db.session.delete(pattern)
for response in Response.query.filter(Response.intent_id == id):
db.session.delete(response)
for intent in Intent.query.filter(Intent.context == Intent.query.get(id).set_context):
self.delete(intent.id) #or IntentAPI.delete(self, intent.id)
db.session.delete(Intent.query.get(id))
db.session.commit()
return jsonify( { 'result': True } )

Categories