Cannot deploy REST API with Python on Azure - python

I'm trying to deploy simple Azure web application. I create it exactly as described here
https://learn.microsoft.com/en-us/azure/app-service/app-service-web-get-started-python
but replaced code in main.py with following (and update requirements.txt of course):
from flask import Flask, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
todos = {}
class HelloWorld(Resource):
def get(self):
return {'hello': 'world'}
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]}
api.add_resource(HelloWorld, '/')
api.add_resource(TodoSimple, '/<string:todo_id>')
if __name__ == '__main__':
app.run(debug=True)
Everything works fine locally, but there are issues with deployed version:
-- http://my-app-name-here.azurewebsites.net is just fine and prints {'hello': 'world'} as expected
-- other commands provided by TodoSimple are not accessible.
For example following query
curl http://my-app-name-here.azurewebsites.net/todo -d "data=Remember the milk" -X PUT
would result with "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable." response.
Update: it's all fine when ran locally
$curl http://localhost:5000/todo -d "data=Remember the milk" -X PUT
{
"todo": "Remember the milk"
}
Does anyone know what I'm missing with this app deployment?
Update2: approach without flask_restful won't work either:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello, World!'
#app.route('/data')
def get_data():
return 'The data.'
if __name__ == '__main__':
app.run()
Calling http://my-app-name-here.azurewebsites.net/data results in "The resource you are looking for has been removed, had its name changed, or is temporarily unavailable." message again.

Related

How to access Flask Request header outside route method

I want to access headers for a certain API calls outside of its api route. I tried using the app_context and test_request_context but it doesn't seem to work.
from flask import Flask, request
app = Flask("app")
def access_header_for_something():
with app.test_request_context():
with app.app_context():
print(request.headers.get("Authorization"), request.host, request.path)
#app.route('/')
def index():
access_header_for_something()
return 'hello'
if __name__=="__main__":
app.run(debug=True)
Any suggestions would be really helpful
The above code snippet work with slight tweak:
from flask import Flask, request
app = Flask("app")
def access_header_for_something():
with app.app_context():
print(request.headers.get("Authorization"), request.host, request.path)
#app.route('/')
def index():
access_header_for_something()
return 'hello'
if __name__=="__main__":
app.run(debug=True)

How to extract data from Django api rest framework POST method

I'm trying to build an API that execute a script with some variables,
those variables are in the POST msg, like {'command': 'start', 'name': 'var'}..
The thing is that I can't find the function the extraction those exact values and not all of the data.
after a few days I tried with flask but that idea is the same.
from flask import Flask, request
from flask_restful import Api, Resource
import os
script = 'python /home/USER/somepath/client.py start '
app = Flask(__name__)
api = Api(app)
class Netflix(Resource):
def get(self):
return "Success", 201
def post(self):
name = request.data
os.system(script+name)
print(name)
return "Success", 201
api.add_resource(Netflix, "/netflix")
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=8000)
class Netflix(Resource):
def get(self):
return "Success", 201
def post(self):
command = request.headers.get('command')
name = request.headers.get('name')
print(command+' '+name)
os.system(script+command+' '+name)
return "Success", 201

Python Flask: Error "The method is not allowed for the requested URL"

I am very new to working with Python Flask and i wanted to try a simple API-example:
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def get(self):
some_json = request.get_json()
return {'you sent': some_json}, 201
class Multi(Resource):
def get(self,num):
return {'result': num*10}
api.add_resource(HelloWorld, '/')
api.add_resource(Multi,'/multi/<int:num>')
if __name__ == '__main__':
app.run(debug=True)
and if I type in the terminal
-H "Content-Type: application/json" -X POST -d '{"name":"xyz","address":"myaddress"}' http://127.0.0.1:5000/
I get the following message:
{
"message": "The method is not allowed for the requested URL."
}
I hope someone can help me with this...
Since your are calling the POST HTTP method. You should rename 'get' function in class HelloWorld to 'post'. 'HelloWorld' class can also have both 'get' and a 'post' functions if '/' endpoint should serves both.
from flask import Flask, jsonify, request
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWorld(Resource):
def post(self):
some_json = request.get_json()
return {'you sent': some_json}, 201
class Multi(Resource):
def get(self,num):
return {'result': num*10}
api.add_resource(HelloWorld, '/')
api.add_resource(Multi,'/multi/<int:num>')
if __name__ == '__main__':
app.run(debug=True)

The usage of Flask-restful routing functions is correct?

I can access /v1/folder but cannot access /v1/folder/<folder-id>. Could you tell me the reason? In the flask-request document said add_resource() can route multiple URI. But I cannot. Maybe I misunderstand something. Please tell me if you find the clue.
from flask import request
from flask_restful import Resource, abort
class Folder(Resource):
def post(self, folder_id):
return { "message":"post with folder_id"}, 200
def post(self):
return { "message":"post without folder_id"}, 201
app = Flask(__name__)
.....
api_bp = Blueprint('api', __name__)
api = Api(api_bp, serve_challenge_on_401=True)
api.add_resource( Folder, '/v1/folder', '/v1/folder/<string:folder_id>')
app.register_blueprint(api_bp)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True )
The error messages is "TypeError: post() got an unexpected keyword argument 'folder_id' ". What's wrong?
Python does not support function/method overloading, so the post method you declared last is always going to be the one that's used. Instead, you should use the tools Python does provide - default values for arguments.
I would personally do the following:
from flask import request
from flask_restful import Resource, abort
class Folder(Resource):
def post(self, folder_id=None):
if folder_id is None:
return self.__simple_post()
else:
return self.__parameter_post(folder_id)
def __parameter_post(self, folder_id):
return { "message":"post with folder_id"}, 200
def __simple_post(self):
return { "message":"post without folder_id"}, 201
app = Flask(__name__)
.....
api_bp = Blueprint('api', __name__)
api = Api(api_bp, serve_challenge_on_401=True)
api.add_resource( Folder, '/v1/folder', '/v1/folder/<string:folder_id>')
app.register_blueprint(api_bp)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True )
Or you could handle the logic in the post method, if the logic is similar enough and not too long. If the logic ends up being unreadable, though, consider using the approach I suggested.

Register new module as a REST API in python-flask dynamically

Consider I have this following code:
from flask import Flask
from flask import request
app = Flask(__name__)
#app.route('/test', methods=['GET'])
def get():
if request.method == 'GET':
return 'hello'
#app.route('/post', methods=['POST'])
def post():
if request.method == 'POST':
name = request.form['name']
return name
if __name__ == '__main__':
app.run()
I run the code and the server starts with these two API endpoints.
Now, I want to register one more endpoint in the same flask app without restarting the currently server, so that any transactions going on the existing endpoints are not interrupted.
Is there a way I can register a new endpoint with closing/restarting the server on the same flask app?
You can register new rules at any point in your code using Flasks add_url_rule() function. This function is actually called by the route() decorator as well.
#app.route('/')
def index():
pass
Is equivalent to:
def index():
pass
app.add_url_rule('/', 'index', index)

Categories