flask_dance + Google Search Console API searchAnalytics - python

I'm currently testing Google Search Console API and Flask Dance to do the oauth stuff.
It works great for getting the /sites, but i get an
ValueError: View function did not return a response
if i try to query searchAnalytics with /search
According to https://developers.google.com/webmaster-tools/search-console-api-original/v3/searchanalytics/query#try-it it must be POST + additonal data. e.g.:
json={'startDate':'2017-11-01','endDate':'2017-12-01'}
In https://developers.google.com/oauthplayground/ it works like this but with flask dance sadly not. any ideas?
import os
from werkzeug.contrib.fixers import ProxyFix
from flask import Flask, redirect, url_for
from flask_dance.contrib.google import make_google_blueprint, google
from raven.contrib.flask import Sentry
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)
sentry = Sentry(app)
app.secret_key = os.environ.get("FLASK_SECRET_KEY", "supersekrit")
app.config["GOOGLE_OAUTH_CLIENT_ID"] = os.environ.get("GOOGLE_OAUTH_CLIENT_ID")
app.config["GOOGLE_OAUTH_CLIENT_SECRET"] = os.environ.get("GOOGLE_OAUTH_CLIENT_SECRET")
google_bp = make_google_blueprint(scope=["profile", "email", "https://www.googleapis.com/auth/webmasters"])
app.register_blueprint(google_bp, url_prefix="/login")
#app.route("/")
def index():
return "BlA BLA"
#app.route("/sites")
def sites():
if not google.authorized:
return redirect(url_for("google.login"))
resp = google.get("/webmasters/v3/sites")
siteEntry = resp.json()["siteEntry"]
result = ""
for site in siteEntry:
result = result + site["siteUrl"] + "</br>"
return result
#app.route("/search")
def search():
if not google.authorized:
return redirect(url_for("google.login"))
resp = google.post("/webmasters/v3/sites/https%3A%2F%2Fzrce.eu/searchAnalytics/query", json={'startDate':'2017-11-01','endDate':'2017-12-01'})
print(resp)
if __name__ == "__main__":
app.run()

All API routes should always return something even if its an empty response.
Simply return a response, it can be "" or resp.

Related

Python Flask extracting results from endpoint

In the Flask script below, I want to use the results of the endpoint '/three' in my endpoint '/five'.
The endpoint for '/three' works fine, however when I try the endpoint '/five', I get the error: TypeError: 'Response' object is not subscriptable.
How do I correctly use the output of '/three' to compute '/five'?
from flask import Flask, url_for, redirect
app = Flask(__name__)
#app.route('/three')
def three():
return {'message':3}
#app.route('/five')
def five():
old_message = redirect(url_for('three'))['message'] # expect to return 3
new_message = {'message':old_message + 2 } # 3+2 = 5
return new_message # expecting {'message':5}
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=8080)
if you want to trigger the three method via http request, you could use requests package, then JSON-parse it, manipulate and return to the client:
from flask import jsonify
import requests
import json
...
...
...
#app.route('/three')
def three():
return {'message':3}
#app.route('/five')
def five():
http_req = requests.get('http://localhost:8000/three')
my_three_json = json.loads(http_req.text)
my_three_json["message"] += 2
return jsonify(my_three_json)

'message': 'The method is not allowed for the requested URL.'

I am getting this error when I run my python script to make a call to my API:
{'message': 'The method is not allowed for the requested URL.'}
I cannot figure out why I am getting this error as I am using the exact code as the tutorial I am following.
Here is the call to my API:
import requests
BASE = "http://127.0.0.1:5000/"
response = requests.put(BASE + "video/1", {"likes": 10})
print(response.json())
And here is my API:
from flask import Flask
from flask_restful import Api, Resource, reqparse
app = Flask(__name__)
api = Api(app)
video_put_args = reqparse.RequestParser()
video_put_args.add_argument("name",type=str, help="t")
video_put_args.add_argument("views",type=int, help="t")
video_put_args.add_argument("likes",type=int, help="t")
videos = {}
class Video(Resource):
def get(self, video_id):
return videos[video_id]
def put(self, video_id):
args=video.args.parse_args()
return {videoid:args}
api.add_resource(Video, "/video/<int:video_id>")
if __name__ == "__main__":
app.run(debug=True)
Any help would be appreciated, thanks

Unable to connect 2 Apps in FLASK

I have created 2 apps in FLASK, one app will issue a GET request and pull the data, 2nd app will take that data from app 1 and issue a POST request to push data into other system.
APP1.py
from flask import Flask, jsonify, request, render_template
app = Flask(__name__)
#app.route('/pushdata', methods=['GET', 'POST'])
def testfn():
# POST request
if request.method == 'POST':
print(request.get_json()) # parse as JSON
req = request.get_json()
print(type(req))
print(req)
return 'Success!! Reached Flask', 200
# main driver function
if __name__ == '__main__':
app.run(debug=True)
APP2.py
from flask import Flask,jsonify,request,make_response,url_for,redirect
import requests, json
app = Flask(__name__)
url = 'http://xx.xx.xx.xxx:<PORT>/lemte/7/rest/tenten/'
json_data = **<JSON DATA received from APP1....................>**
headers = {'content-type': 'application/json'}
res = requests.post(url, headers=headers, auth=('XXXXX', 'YYYYY'), data=json.dumps(json_data))
print ('response from server:',res.text)
dictFromServer = res.json()
if __name__ == '__main__':
app.run(host='localhost',debug=False, use_reloader=True)
How can I achieve this? searched a lot, but unable to find any hints/suggestions.
Perhaps you could try through a POST request from APP1 to APP2 or through sockets where APP1 would be the server and APP2 the client.
Edit:
This might help:
communication-between-two-python-scripts and
communication-between-two-python-scripts
They both have the same title but different answers
this solves your problem in order to let 2 flask app talk to each other :
In APP1.py:
from flask import Flask, jsonify, request, render_template
app = Flask(__name__)
#app.route('/lemte/7/rest/tenten', methods=['GET', 'POST'])
def testfn():
if request.method == 'POST':
print(request.get_json()) # parse as JSON
req = request.get_json()
print(type(req))
print(req)
return jsonify({"message":"success!! readched flask"}),200
# return 'Success!! Reached Flask', 200
if __name__ == '__main__':
app.run(debug=True,port=5201)
In APP2.py:
from flask import Flask,jsonify,request,make_response,url_for,redirect
import requests, json
app = Flask(__name__)
url = 'http://localhost:5201/lemte/7/rest/tenten'
json_data = {"test":"hello"}
headers = {'content-type': 'application/json'}
res = requests.post(url, headers=headers, auth=('XXXXX', 'YYYYY'),
data=json.dumps(json_data))
print ('response from server:',res.text)
dictFromServer = res.json()
if __name__ == '__main__':
app.run(host='localhost',debug=False, use_reloader=True,port=5200)
You did not not specified any error here
I assume the error is that you tried to run both in same port which is not possible
You can run each in different ports by specifying port in app.run
example:
app1
from flask import Flask
app = Flask(__name__)
if __name__ == "__main__":
app.run(host="localhost", port=5000)
app2
from flask import Flask
app = Flask(__name__)
if __name__ == "__main__":
app.run(host="localhost", port=5001)
You can use python app1.py and python app2.py in two different terminals to run the servers

How can I return API objects in application using flask

from flask import Flask, request, jsonify
import requests
app = Flask(__name__)
#app.route('/address_search', methods=['GET'])
def sample():
zipcode = request.args.get('zipcode', None)
url = f'https://zipcloud.ibsnet.co.jp/api/search?zipcode={zipcode}'
response = requests.get(url)
# results = response.json()
# results = jsonify(response) ?????
return response
if __name__ == '__main__':
app.run(debug=True)
I'm trying to create an Application which return the Address.
I succeeded to return url but about response, I can't and Internal Server Error appears
So I thought in flask, requests.get(url) cannot be used but I didn't came up an another way.
I heard that jsonify() is used but I don't known how.
I searched it in Google for two days but I still cannot find it's answer.
Someone please give me advice.
So, you want to return the response of that API in your web application, i guess this is what you're looking for?
#app.route('/address_search', methods=['GET'])
def sample():
zipcode = request.args.get('zipcode', None)
url = f'https://zipcloud.ibsnet.co.jp/api/search?zipcode={zipcode}'
response = requests.get(url)
response_json = response.json()
return jsonify(response_json)
EDIT, response to your comment:
You can't do jsonify(response_json)['results'][0] because jsonify turns the JSON data to Flask Response object, instead try this:
#app.route('/address_search', methods=['GET'])
def sample():
zipcode = request.args.get('zipcode', None)
url = f'https://zipcloud.ibsnet.co.jp/api/search?zipcode={zipcode}'
response = requests.get(url)
response_json = response.json()
results = response_json['results'][0]
return jsonify(results)

Python requsts.post returning 405 error: The method is not allowed for the requested URL

Howdie do,
I'm just running a simple flask API call.
The flask API will take a XML request in and then parse the XML and print it to the terminal screen.
However, everytime I do this, I'm receiving
The method is not allowed for the requested URL
The Flask script is:
__author__ = 'Jeremy'
from flask import Flask
from flask import request
import xmltodict
app = Flask(__name__)
#app.route('/', methods=['POST'])
def parsexml():
xmlrequest = xmltodict.parse(request.data)
print xmlrequest
if __name__ == '__main__':
app.run()
The script that sends the XML is:
__author__ = 'Jeremy'
import requests
xml = """
<dtc:GetShipmentUpdates>
<dtc:GetShipmentUpdatesRequest>
<dtc:SearchStartTime>2015-07-12T12:00:00</dtc:SearchStartTime>
<dtc:SearchEndTime>2015-07-12T12:30:00</dtc:SearchEndTime>
</dtc:GetShipmentUpdatesRequest>
</dtc:GetShipmentUpdates> """
headers = {'Content-Type': 'application/xml'}
r = requests.post('http://127.0.0.1:5000/', data=xml, headers=headers)
print r.content
Does anyone know why this is happening and if so, how can I send a POST request to my flask application running on 127.0.0.1:5000
You aren't returning anything from parsexml. Try returning some content:
#app.route('/', methods=['POST'])
def parsexml():
xmlrequest = xmltodict.parse(request.data)
print xmlrequest
return "Thanks for the data!"
Howdie do,
You can't send POST requests to /
So I changed it to go to the following:
__author__ = 'Jeremy'
from flask import Flask
from flask import request
import xmltodict
app = Flask(__name__)
#app.route('/')
def say_hello():
return "Say goodbye Jeremy"
#app.route('/api', methods=['POST'])
def parsexml():
xmlrequest = xmltodict.parse(request.data)
return xmlrequest
if __name__ == '__main__':
app.run(host='0.0.0.0', port=int("80"))
Work now

Categories