Wonderful REST APIs.
Project description
Layab stands for Wonderful
in Somali and is also a shortcut for Layabout
(aren't we all lazy).
This package provides functions and classes that can be used to facilitate the creation of APIs.
If you were using layab 1.* (based on Flask-RestPlus, a project that is now dead and will not be compatible starting with Python 3.9), please refer to the Migration guide as layab now advocate the use of Starlette.
Why didn't you switched from Flask-RestPlus to another Starlette based all-in-one framework (such as FastAPI or Responder)?
Modularity is a key principle in software development. However the use of such framework prevent such development.
An all-in-one framework is more likely to requires hack to fit your usage.
An all-in-one framework is more likely to have a slower development and release pace.
By using layab 2, you can still use an all-in-one framework, but you also can chose what and if you want to:
Generate an OpenAPI definition.
Embed Swagger-UI.
Validate data.
Serialize / Deserialize data.
...
Available features
Starlette
Middleware
You can get a bunch of already created Starlette middleware thanks to layab.starlette.middleware
function.
from starlette.applications import Starlette from layab.starlette import middleware app = Starlette(middleware=middleware())
By default you will have the following middleware:
- LoggingMiddleware: Log requests upon reception and return (failure or success).
- CORSMiddleware: Allow cross origin requests.
- ProxyHeadersMiddleware: Handle requests passing by a reverse proxy.
Responses
Default responses are available to return standard responses.
Location response
from starlette.applications import Starlette from layab.starlette import LocationResponse app = Starlette() @app.route("/resource", methods=["POST", "PUT"]) def handle_resource(request): resource_id = create_update_resource() # Implement this endpoint return LocationResponse(request, "/resource/{resource_id}") @app.route("/resource/{resource_id}", methods=["GET"]) def get_resource(request): pass # Implement this endpoint
Configuration
API and logging configuration should be stored in YAML format.
Configuration is expected to be stored inside a configuration
folder located on the parent folder of the provided file path.
API Configuration is expected to follow the "configuration_{env}.yml" naming where env is the value of the SERVER_ENVIRONMENT environment variable.
If not found, environment will be considered as "default".
Logging configuration is loaded using the same logic and the following naming: "logging_{env}.yml".
import layab # Load logging and service configuration service_configuration = layab.load('path/to/a/file/in/module/folder')
Note that in case your logging configuration file contains execution of Python code, you will need to provide the yaml.UnsafeLoader
loader.
import layab import yaml # Load logging and service configuration service_configuration = layab.load('path/to/a/file/in/module/folder', logging_loader=yaml.UnsafeLoader)
Migration guide
If an information on something that was previously existing is missing, please open an issue.
Create application and OpenAPI definition and Swagger-UI endpoints
Layab 1.*
import layab app, api = layab.create_api( __file__, compress_mimetypes=["text/csv", "application/json"], title="My API.", description="My description.", )
Layab 2.* using flask-restx
import flask import layab from layab.flask_restx import enrich_flask, log_requests, Api app = flask.Flask(__name__) enrich_flask(app, compress_mimetypes=["text/csv", "application/json"]) api = Api( app, title="My API.", description="My description.", version="1.0.0", # You now have to set the version yourself info={"x-server-environment": layab.get_environment()} ) log_requests(skip_paths=["/health"])
Layab 2.* using Starlette
import layab from layab.starlette import middleware from starlette.applications import Starlette import apispec_starlette app = Starlette(middleware=middleware()) spec = apispec_starlette.add_swagger_json_endpoint( app, title="My API.", version="1.0.0", # You now have to set the version yourself info={ "description": "My description.", "x-server-environment": layab.get_environment(), } ) # You will however lose the Swagger-ui that was available on / (root endpoint) # We advise to install it on your Docker image first and then serve the directory as "/" as the last declared route.
Monitoring endpoints
Layab 1.*
import layab api = None def health_details(): pass # Implement this layab.add_monitoring_namespace(api, health_details)
Layab 2.* using flask-restx
import os.path from healthpy.flask_restx import add_consul_health_endpoint from keepachangelog.flask_restx import add_changelog_endpoint api = None async def health_check(): pass # Implement this namespace = api.namespace( "Monitoring", path="/", description="Monitoring operations" ) # You now have to set the release_id yourself add_consul_health_endpoint(namespace, health_check, release_id="1.0.0") # You now have to set the path to the changelog yourself changelog_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "CHANGELOG.md") add_changelog_endpoint(namespace, changelog_path)
Layab 2.* using Starlette
import os.path from starlette.applications import Starlette from healthpy.starlette import add_consul_health_endpoint from keepachangelog.starlette import add_changelog_endpoint app = Starlette() async def health_check(): pass # Implement this add_consul_health_endpoint(app, health_check) # You now have to set the path to the changelog yourself changelog_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "CHANGELOG.md") add_changelog_endpoint(app, changelog_path)
You can now add only one of the two initially provided endpoints (in case you don't have or want to expose your changes).
Refer to healthpy documentation for more information on what is possible to check API health.
Refer to keepachangelog documentation for more information on how changelog is handled.
Created response
Layab 1.*
import layab api = None @api.doc(**layab.created_response_doc(api)) def endpoint(): return layab.created_response("/this_is_the_location")
Layab 2.* using flask-restx
import flask_restx from layab.flask_restx import location_response api = None @api.response(201, "Resource created", flask_restx.fields.String, headers={"location": "Resource location."}) def endpoint(): return location_response("/this_is_the_location")
Layab 2.* using Starlette
from layab.starlette import LocationResponse def endpoint(request): """ responses: 201: description: "Resource created" headers: location: description: "Resource location." type: string schema: type: string """ return LocationResponse(request, "/this_is_the_location")
Updated response
Layab 1.*
import layab api = None @api.doc(**layab.updated_response_doc(api)) def endpoint(): return layab.updated_response("/this_is_the_location")
Layab 2.* using flask-restx
import flask_restx from layab.flask_restx import location_response api = None @api.response(201, "Resource updated", flask_restx.fields.String, headers={"location": "Resource location."}) def endpoint(): return location_response("/this_is_the_location")
Layab 2.* using Starlette
from layab.starlette import LocationResponse def endpoint(request): """ responses: 201: description: "Resource updated" headers: location: description: "Resource location." type: string schema: type: string """ return LocationResponse(request, "/this_is_the_location")
Deleted response
Layab 1.*
import layab api = None @api.response(*layab.deleted_response_doc) def endpoint(): return layab.deleted_response
Layab 2.* using flask-restx
import flask api = None @api.response(204, "Resource deleted") def endpoint(): return flask.Response(b"", status=204)
Layab 2.* using Starlette
from starlette.responses import Response def endpoint(request): """ responses: 204: description: "Resource deleted" """ return Response(status_code=204)
How to install
- python 3.6+ must be installed
- Use pip to install module:
python -m pip install layab
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Filename, size | File type | Python version | Upload date | Hashes |
---|---|---|---|---|
Filename, size layab-2.2.0-py3-none-any.whl (11.3 kB) | File type Wheel | Python version py3 | Upload date | Hashes View |
Filename, size layab-2.2.0.tar.gz (12.7 kB) | File type Source | Python version None | Upload date | Hashes View |