Flask - Pass back response of inner request - python

I looked at some of the similar suggested SO questions, but they weren't quite what I was looking for:
I have a Flask server with a POST route that calls another server. I want Flask to return the response from that request as-is.
import os
import requests
from flask import Flask, request, jsonify, make_response, Response
#app.route('/stuff', methods=['POST'])
def get_stuff():
resp = requests.post(...)
return resp
app.run(host='0.0.0.0', port=9999)
I've tried the following but each returns an error:
return jsonify(resp)
return ( resp.raw.read(), resp.status_code, resp.headers.items() )
return Response(json.dumps(resp), status=resp.status_code, mimetype='application/json')
I just want it to pass back what it got

Flask route functions should only return a string, you need a method to convert it and each of the attempts you made probably fell short in one way or another to do so.
Post the error messages, they may clue in how close you are to accomplishing the rerouting of the post response.

Related

Flask Session does not retain value between POST requests

So I'm using flask to create endpoints as receivers and data processors. I have two threads of http POST requests, the first one is sent to the first route, similarly for the second one. The thing is I want the 2nd processor to be triggered only when the 1st one is, so I created a session key, to validate for the execution of the 2nd processor.
But no matter what I did, session key is always wiped when I sent POST to the second processor. Here's my code, which has been simplified. Pardon my amateur ablity to express the problem, I'm extremely new to coding.
from flask import Flask, request, redirect, url_for, session
app = Flask(__name__)
app.secret_key = "abc"
#app.route('/first_processor', methods=['POST'])
def first_processor():
data = {
'message': 'json received',
'json': request.json
}
cond = data['json']
if cond['event'] == "message:received":
session["key"] = cond['key']
return redirect(url_for("second_processor"))
else:
return data
#app.route('/second_processor', methods=['POST'])
def second_processor():
if "key" in session:
print('OK')
else:
print("FAIL")
return data
if __name__ == "__main__":
app.run(debug=True)
Apparently I saw two minor problems. The first one is that
#app.route('/second_processor', methods=['POST']) `
only allows POST method, and
redirect(url_for("second_processor"))
is a GET request. And you cannot force a POST request. Even though, according to the documentation, there is a _method parameter in the url_for function.
Related question: Issue a POST request with url_for in Flask
The second problem is that you created the data variable inside the first_processor function, but you don't pass it to the second_processor.
if 'key' in session:
print('OK')
else:
print("FAIL")
--> return data
you could either:
pass the data inside the session,
make data global ( not sure if it is a good practice though)
store data in a file or db and read it inside second_processor.

Trying flask functions but get error that url is not valid

I wish to show my data in a webpage by using flask. (Trying to learn it)
from flask import Flask, jsonify, make_response
from flask_cors import CORS
api = Flask(__name__)
CORS(api)
api.config['JSON_AS_ASCII'] = False
api.config["JSON_SORT_KEYS"] = False
#api.route('/token',methods=["POST"])
def get_token(self):
data = {
"type": "testing",
}
response1 = make_response(jsonify(data))
return response1
if __name__ == "__main__":
api.run(port=11111)
current output when try http://127.0.0.1:11111/ on google chrome:
Not Found
The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I also tried with /token:
Method Not Allowed
The method is not allowed for the requested URL.
you need to go to http://127.0.0.1:11111/token, if you want to go to http://127.0.0.1:11111/ you need to define a function with route #api.route('/',methods=["POST"])
Also a browser makes GET requests via URL unless explicitly defined, change it to get via #api.route('/',methods=["GET"])
Your route is /token, so you need to go to http://127.0.0.1:11111/token.
POST requests cannot be directly viewed in browser. Try some rest API client like Postman to test your POST request.
Alternatively, if you want to test if the API just works, change the POST method to GET. Then if you visit http://127.0.0.1:11111/token, you can see the response. Also you don't need 'self' argument to your method.
You restrict your app.route to only POST. If you want to enter your page from url you have to specify GET as well.
Read about http requests
from flask import Flask, jsonify, make_response
from flask_cors import CORS
api = Flask(__name__)
CORS(api)
api.config['JSON_AS_ASCII'] = False
api.config["JSON_SORT_KEYS"] = False
#api.route('/token',methods=["GET", "POST"])
def get_token(self):
data = {
"type": "testing",
}
response1 = make_response(jsonify(data))
return response1
if __name__ == "__main__":
api.run(port=11111)

Flask - access the request in after_request or teardown_request

I want to be able to access the request object before I return the response of the HTTP call.
I want access to the request via "teardown_request" and "after_request":
from flask import Flask
...
app = Flask(__name__, instance_relative_config=True)
...
#app.before_request
def before_request():
# do something
#app.after_request
def after_request(response):
# get the request object somehow
do_something_based_on_the_request_endpoint(request)
#app.teardown_request
def teardown_request(response):
# get the request object somehow
do_something_based_on_the_request_endpoint(request)
I saw that I can add the request to g and do something like this:
g.curr_request = request
#app.after_request
def after_request(response):
# get the request object somehow
do_something_based_on_the_request_endpoint(g.curr_request)
But the above seems a bit strange. I'm sure that there's a better way to access the request.
Thanks
The solution is simple -
from flask import request
#app.after_request
def after_request(response):
do_something_based_on_the_request_endpoint(request)
return response
Also try teardown_request(exception). This executes "regardless of whether there was an exception or not". Check the documentation: http://flask.pocoo.org/docs/0.12/api/#flask.Flask.teardown_request

Is HTTP Post blocked by Cloud9?

I've been playing around with Python/Flask on Cloud9 ide. Pretty fun so far. But when I try to add a http post to my test project, Flask returns either a 403 or a 500. From what I can tell, when I attach data or send the POST method, the 'request' object is None. It doesn't make sense though. This is pretty straight forward and should work as far as I can tell. Here's the python:
from flask import Flask, jsonify, abort, request
#app.route('/test', methods = ['POST'])
def post():
print ('started')
print request
if request.method == 'POST':
something = request.get_json()
print something
Flask is running correctly. I can hit a GET url, returning data just fine. I get an error when I land on 'print request' because request is None.
Thanks,
You have two problems here:
You're getting a 500 error
"something" is always None
The first problem is because you're not returning anything from your route function.
127.0.0.1 - - [15/Dec/2014 15:08:59] "POST /test HTTP/1.1" 500 -
Traceback (most recent call last):
...snip...
ValueError: View function did not return a response
You can remedy this by adding a return statement at the end of the function. Don't forget it needs to be a string.
#app.route('/hi', methods = ['POST'])
def post():
return "Hello, World!"
The second problem isn't what it seems. I suspect that the object isn't None, but the function that returns the string representation returns None, so that's what gets printed. Try print type(request) to see this in action.
What I think you want access to is the form field. Here is a complete example:
from flask import Flask, request
app = Flask(__name__)
#app.route('/test', methods = ['POST'])
def post():
print type(request)
if request.method == 'POST':
print request.form
return str(request.form)
app.run(debug=True)

Is it possible to make POST request in Flask?

There is a need to make POST request from server side in Flask.
Let's imagine that we have:
#app.route("/test", methods=["POST"])
def test():
test = request.form["test"]
return "TEST: %s" % test
#app.route("/index")
def index():
# Is there something_like_this method in Flask to perform the POST request?
return something_like_this("/test", { "test" : "My Test Data" })
I haven't found anything specific in Flask documentation. Some say urllib2.urlopen is the issue but I failed to combine Flask and urlopen. Is it really possible?
For the record, here's general code to make a POST request from Python:
#make a POST request
import requests
dictToSend = {'question':'what is the answer?'}
res = requests.post('http://localhost:5000/tests/endpoint', json=dictToSend)
print 'response from server:',res.text
dictFromServer = res.json()
Notice that we are passing in a Python dict using the json= option. This conveniently tells the requests library to do two things:
serialize the dict to JSON
write the correct MIME type ('application/json') in the HTTP header
And here's a Flask application that will receive and respond to that POST request:
#handle a POST request
from flask import Flask, render_template, request, url_for, jsonify
app = Flask(__name__)
#app.route('/tests/endpoint', methods=['POST'])
def my_test_endpoint():
input_json = request.get_json(force=True)
# force=True, above, is necessary if another developer
# forgot to set the MIME type to 'application/json'
print 'data from client:', input_json
dictToReturn = {'answer':42}
return jsonify(dictToReturn)
if __name__ == '__main__':
app.run(debug=True)
Yes, to make a POST request you can use urllib, see the documentation.
I would however recommend to use the requests module instead.
EDIT:
I suggest you refactor your code to extract the common functionality:
#app.route("/test", methods=["POST"])
def test():
return _test(request.form["test"])
#app.route("/index")
def index():
return _test("My Test Data")
def _test(argument):
return "TEST: %s" % argument

Categories