Python REST-API with Flask-RestX and JavaScript REST-Client served together - python

I run this example: https://flask-restx.readthedocs.io/en/latest/example.html
(A Python REST-API with Flask-RESTX)
Code snippet
app = Flask(__name__)
api = Api(app, ...)
ns = api.namespace('todos', ...)
#ns.route('/')
...
#ns.route('/<int:id>')
...
Result
I get the following URLs for the REST-API:
http://127.0.0.1:5000 -> Swagger Documentation
http://127.0.0.1:5000/swagger.json
http://127.0.0.1:5000/todos/
http://127.0.0.1:5000/todos/{id}
Question
I would like to implement a Webclient with Javascript, which should be reached under following URLs:
http://127.0.0.1:5000 -> index.html
http://127.0.0.1:5000/style.css
http://127.0.0.1:5000/app.js
The URLs for the REST-API should change to:
http://127.0.0.1:5000/api -> Swagger Documentation
http://127.0.0.1:5000/api/swagger.json
http://127.0.0.1:5000/api/todos/
http://127.0.0.1:5000/api/todos/{id}
How can I expand the example to generate the wanted URLs?

Not sure if you have gotten an answer by now. I often clone the below github project for flask restx boilerplate. It is designed as a rest boilerplate to help get you up and running.
https://github.com/cosmic-byte/flask-restplus-boilerplate
The templates and static files can be added to the application and to the controllers to host the pages. Added the below documentation for the static pages. Every this should be there to get you running with a full site
https://flask.palletsprojects.com/en/1.1.x/tutorial/static/

You can wrap flask-restx application with flask.Blueprint to move swagger logic under a specific url_path.
The following example shows how this can be achieved:
import flask
import flask_restx
APP = flask.Flask("my-app")
api_bp = flask.Blueprint("api", __name__, url_prefix="/api")
API = flask_restx.Api(api_bp)
APP.register_blueprint(api_bp)
NAMESPACE = API.namespace("todos")
#NAMESPACE.route("/")
class TODOSAPI(flask_restx.Resource):
def get(self):
return ['todo-1', 'todo-2']

Related

How to overwrite/extend FastAPI - APIRouter route

this question is related to FastAPI with APIRouter plugin system not working , just to give a little bit of context...
So... I'm trying to create a simple pluggable FastAPI application where plugins can add, or not, API endpoints. Now is working fine so every plugin adds its own API endpoints. But what if a plugin can extend other plugins, to add or modify its endpoints...
For that, I build a plugin graph to handle the plugin dependencies and now a plugin can import the router from its dependencies and add some new endpoints. But I canĀ“t overwrite the existing endpoints with the new routes.
To make it simpler I wrote this piece of code to simulate this:
import uvicorn
from fastapi import APIRouter, FastAPI
router = APIRouter()
#router.get("/")
def index():
return "hello world!"
#router.get("/")
def new_index():
return "hello world 2!"
app = FastAPI()
app.include_router(router)
if __name__ == "__main__":
uvicorn.run("server:app")
At this point, I would expect to have the hello world 2! response for the / route but instead of that I have the hello world!
UPDATE
I have also found another interesting thing in the generated api /docs that maybe can be a bug... (I update the routes functions name, to clarify). The code generates this doc... So I may think that it's Ok!. At least the documentation was built from the new_index function
But as I was mentioned before the response is from index

Azure use python flask framework for function app

I saw that Azure now supports Python (preview) in the function apps. I have a existing Flask app and was wondering if it's possible to deploy that one as a function app without major changes?
I have read through the Azure tutorials that uses Python in function apps (https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-python), however not with the flask framework...
Has anyone any experience with it?
I tried different ways to integrate Azure Functions for Python with Flask framework. Finally, I did it success in my HttpTrigger function named TryFlask via app.test_client().
Here is my sample code, as below.
import logging
import azure.functions as func
from flask import Flask, request
app = Flask(__name__)
#app.route('/')
def hello_world():
return 'Hello World!'
#app.route('/hi')
def hi():
return 'Hi World!'
#app.route('/hello')
#app.route('/hello/<name>', methods=['POST', 'GET'])
def hello(name=None):
return name != None and 'Hello, '+name or 'Hello, '+request.args.get('name')
def main(req: func.HttpRequest) -> func.HttpResponse:
logging.info('Python HTTP trigger function processed a request.')
uri=req.params['uri']
with app.test_client() as c:
doAction = {
"GET": c.get(uri).data,
"POST": c.post(uri).data
}
resp = doAction.get(req.method).decode()
return func.HttpResponse(resp, mimetype='text/html')
For testing on local and Azure, to access the urls /, '/hi' and /hello via the url http(s)://<localhost:7071 or azurefunchost>/api/TryFlask with query string ?uri=/, ?uri=/hi and ?uri=/hello/peter-pan in browser, and to do the POST method for the same url above with query string ?uri=/hello/peter-pan, these are all work. Please see the results as the figures locally below, the same on cloud.
Note: In my solution, the url must have to be http(s)://<localhost:7071 or azurefunchost>/<routePrefix defined in host.json, default is api>/<function name>?uri=<uri defined in app.route, like / or /hi or /hello, even /hello/peter-pan?name=peter>.
Flask app is just an WSGI application. WSGI is a rather simple interface (see http://ivory.idyll.org/articles/wsgi-intro/what-is-wsgi.html. So instead of using test_client() as middleware to connect to the Azure function environment, a proper wsgi wrapper implementation should be used, which calls the app=Flask() object.
There is a nice Azure Python wsgi wrapper implementation "azf-wsgi" available in https://github.com/vtbassmatt/azf-wsgi.
In order to use the azf-wsgi wrapper with Flask, I found it useful to use a middleware to rewrite the URL:s from /api/app to / so when developing, I don't need to know where my Flask app gets mounted.
Additional benefit is that my main.py is just a normal Flask application, which I can run locally without using Azure functions environment (way faster).
My HttpTriggerApp/__init__.py of Azure function is attached. The myFlaskApp-folder is located under the HttpTriggerApp. Remember to use rlative import in the http-trigger as well as main.py (from . import myHelperFooBar).
For host.json and function.json, follow the azf-wsgi instructions.
import logging
import azure.functions as func
# note that the package is "azf-wsgi" but the import is "azf_wsgi"
from azf_wsgi import AzureFunctionsWsgi
# Import the Flask wsgi app (note relative import from the folder under the httpTrigger-folder.
from .myFlaskAppFolder.main import app
# rewrite URL:s to Azure function mount point (you can configure this in host.json and function.json)
from werkzeug.middleware.dispatcher import DispatcherMiddleware
app.config["APPLICATION_ROOT"] = "/api/app" # Flask app configuration so it knows correct endpoint urls
application = DispatcherMiddleware(None, {
'/api/app': app,
})
# Wrap the Flask app as WSGI application
def main(req: func.HttpRequest, context: func.Context) -> func.HttpResponse:
return AzureFunctionsWsgi(application).main(req, context)
Flask can be used now out of the box with Python Azure Functions -> see https://github.com/Azure/azure-functions-python-library/pull/45

Centralizing Flask routes

My colleague would like to place all routes for the web server in a single routing file instead of spreading them around on a bunch of functions. This is how he does it in Java/Play:
GET /recovery controllers.application.recovery()
GET /signup controllers.application.signup(lang="sv")
GET /<:lang>/signup controllers.application.signup(lang: String)
Is it feasible/easy to do in Flask?
Yes, very easy:
from flask import Flask
import controllers.application
app = Flask(__name__)
routes = '''\
GET /recovery controllers.application.recovery
GET /signup controllers.application.signup
GET /<lang>/signup controllers.application.signup'''
for route in routes.splitlines():
method,path,func = route.split()
app.add_url_rule(rule=path, view_func=eval(func), methods=[method])
app.run()

Combining resources in Python with Flask

I' trying to combine two independent Flask apps like the example below:
from geventwebsocket import WebSocketServer, Resource
...
server = WebSocketServer(('', 8080), Resource({
'/': frontend,
'/one': flask_app_one,
'/two': flask_app_two}))
server.serve_forever()
Inside each Flask app I declare the full path, isn't that suppose to be relative path, inside flask_app_one:
from flask import Flask
app = Flask(__name__)
#app.route('/one/ping')
def ping():
return 'hello\n'
Why I should specify in #app.route('/one/ping') instead of just #app.route('/ping') since all traffic to /one will be forwarded to the corresponding app?
Let me know if you need any additional info I kept my example clean
Thank you
Finally I have managed to do it with the so called Application Dispatching and the resources found in this page:
http://flask.pocoo.org/docs/0.10/patterns/appdispatch/#app-dispatch
Thanks

Exclude One URL From Python URL Masking

I have never written a python script in my life, but I have a question that can hopefully be solved pretty quickly...
I'm using Google App Engine and Dropbprox. The script uses a custom domain to point to your public DropBox folder for better DropBox URLs. I'd like to be able to redirect users to my main site (jacob.bearce.me) if they visit my dropbox url (dl.bearce.me).
The problems that I'm having:
I've never used GAE or Python before, so I have no idea where to even begin
Putting a index.html file in my GAE project didn't fix it (I was hoping it'd just default to that if there was no filename specified, like it would on a normal site, but no cigar.)
Just a simple redirect if a users visits the main URL is all I'm after, nothing fancy.
My Python file: http://dl.bearce.me/mirror.py
Here's a main.py that issues a redirect for all requests, using the Python 2.5 runtime environment:
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler):
def get(self):
self.redirect('http://jacob.bearce.me/')
application = webapp.WSGIApplication([('/.*', MainHandler)],
debug=True)
def main():
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
And here's the app.yaml file you need to route URLs to this handler:
application: myapp
version: 1
runtime: python
api_version: 1
handlers:
- url: .*
script: main.py
(Replace myapp with your actual app ID.)
For more information about creating and uploading an App Engine app in Python, see the Getting Started tutorial.

Categories