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
Related
I am trying to make a rest API in python.flask and I want it to be responsive to python.requests.post(data=data,header=header). But every tutorial and website only shows me Postman and
An API that responds to python.requests.post(PARAMS=data,header=header) but "PARAMS" does not work for my case. I've tried using python.flask.request.get_json(), I've tried using python.flask.Resource, I've tried using another one here:-
from flask import Flask
from flask_restful import Resource, Api, reqparse
from json import loads as dictionary
from flask import request as req
app = Flask(__name__)
api = Api(app)
#app.route('/test', methods=['POST'])
def post(username,token,url):
# gotit=dictionary(gotit)
k = '{"name":'+username+',"password":'+token+',"link":'+url+'}'
print(k)
return k
if __name__ == '__main__':
app.run()#debug=True)
But all in vain. Please help me make an API that responds to this:- python.requests.post(data=data,header=header). And also help with the header thing.
Python.v3.8
Here's your code but with some modification:
Server Code:
from flask import Flask, jsonify, request
import requests
import json
app = Flask(__name__)
#app.route('/test', methods=['POST'])
def post():
# you will get that data in request.data you can simplify/jsonfiy
text = str(request.data)
t = request.data
return t
if __name__ == "__main__":
app.run(debug=True)
python.requests Code:
import requests
header = {
"Content-Type":"text/plain"
}
data = {
"username":"myName",
"password":"myPass",
"url":"myWeb"
}
d = requests.post(url='http://127.0.0.1:5000/test', data=data, headers=header)
#
print(d.content)
Response from server something like this:
response Screenshot
I'm Using Python 3.9.1
Hope it will help You:)
I am trying to pass the path of an xml file to a flask/Python based REST-microservice. When passing the url manually to the service, it works as intended. However, I have problems calling the service from my laravel project.
Call to python rest service from laravel:
function gpxToJson(){
url = "http://127.0.0.1:5000/convert?path=C:/xampp/htdocs/greenlaneAdventures/public/storage/gpx/OOCe4r5Mas8w94uGgEb8qYlI0T3ClZDoclcfrR7s.xml" ;
fetch(url).then(function (response){
var track = JSON.parse(response.json());
return track;
});
}
Python script:
import gpxpy
import pandas as pd
from flask_cors import CORS
from flask import Flask, request, make_response, render_template
from flask_restful import Resource, Api
# create empty web-application
app = Flask(__name__)
api = Api(app)
CORS(app)
# create necessary classes
class Converter(Resource):
def get(self):
# path passed as argument
file = request.args.get('path', '')
# parse gpx file
gpx = gpxpy.parse(open(file))
# define data
track = gpx.tracks[0]
segment = track.segments[0]
# load wanted data into a panda dataframe
data = []
segment_length = segment.length_3d()
for point_idx, point in enumerate(segment.points):
data.append([point.longitude, point.latitude, point.elevation,
point.time, segment.get_speed(point_idx)])
columns = ['Longitude', 'Latitude', 'Altitude', 'Time', 'Speed']
gpx_df = pd.DataFrame(data, columns=columns)
# convert dataframe to json
gpx_json = gpx_df.to_json(orient='index')
print(gpx_json)
#return the converted json (http response code 200 = OK. The request has suceeded)
headers = {"Content-Type": "application/json"}
return make_response(gpx_json, 200, headers)
api.add_resource(Converter, "/convert")
#error handling
#app.errorhandler(404)
def not_found():
"""Page not found."""
return make_response(
render_template("404.html"),
404
)
#app.errorhandler(400)
def bad_request():
"""Bad request."""
return make_response(
render_template("400.html"),
400
)
#app.errorhandler(500)
def server_error():
"""Internal server error."""
return make_response(
render_template("500.html"),
500
)
#main function call
if __name__ == "__main__":
app.run(debug=True)
When calling the function gpxToJson() by submitting a form, I get the following error message in firefox.
I'm new to Python and I try to implement REST API service on Flask. I faced with issue related to testing of my code. My Flask app looks something like that:
from flask import Flask, jsonify, make_response, request
from flask_httpauth import HTTPBasicAuth
import os
auth = HTTPBasicAuth()
#auth.get_password
def get_password(username):
if username == os.environ['SERVICE_KEY']:
return os.environ['SERVICE_PASS']
return None
#auth.error_handler
def unauthorized():
return make_response(jsonify({'error': 'Unauthorized access'}), 403)
app = Flask(__name__)
tweets = [
{
'id': 1,
'profileId': '1',
'message': 'My test tweet'
},
{
'id': 2,
'profileId': '1',
'message': 'Second tweet!'
}
]
#app.route('/api/v1/tweets', methods=['GET'])
#auth.login_required
def get_tweets():
return jsonify({'tweets': tweets}), 200
#app.errorhandler(404)
#auth.login_required
def not_found(error):
return make_response(jsonify({'error': 'Not found'}), 404)
if __name__ == '__main__':
app.run(debug=True)
And here is my test (currently it is only for not_found method):
import unittest
from app import app
class TestApp(unittest.TestCase):
def setUp(self):
self.app = app.test_client()
def test_404(self):
rv = self.app.get('/i-am-not-found')
self.assertEqual(rv.status_code, 404)
if __name__ == '__main__':
unittest.main()
But when I try to run test, it fails due to I get 'Unauthorized access' response:
>python test.py
F
======================================================================
FAIL: test_404 (__main__.TestApp)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test.py", line 25, in test_404
self.assertEqual(rv.status_code, 404)
AssertionError: 403 != 404
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures=1)
Which approach for testing route-methods are more correct to handle authorization? And how can I fix that failed test?
You need to create a custom header that includes your auth details and send it along with your request. Something like this:
from base64 import b64encode
...
headers = {'Authorization': 'Basic ' + b64encode("{0}:{1}".format(username, password))}
rv = self.app.get('/i-am-not-found', headers=headers)
...
import unittest
from app import app
class TestApp(unittest.TestCase):
def setUp(self):
self.app = app.test_client()
def test_404(self):
headers = {
'Authorization': 'Basic ' + b64encode("username:password")
}
rv = self.app.get('/i-am-not-found', headers=headers)
self.assertEqual(rv.status_code, 404)
if __name__ == '__main__':
unittest.main()
Your username and password is sent in the form username:password but is base64 encoded. If expanding this there are ways to make this simpler such as extracting into a function to always pass the header and externalising username/password for testing.
EDIT: Additionally I think you should be returning a 401 code here. 401 is usually used when credentials are incorrect, 403 is usually used when you have successfully authenticated yourself but do not have access to a resource. A very simplified example being logged into Facebook but being restricted from accessing another person's photo that is marked as private.
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.
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