Cómo Crear Fácilmente Una API RESTful Con Flask Y APIFairy

Este tutorial demuestra cómo crear fácilmente una API RESTful con Flask y APIFairy.

Objetivos

Al final de este tutorial, podrá:

  1. Cree puntos finales de API en Flask utilizando los decoradores proporcionados por APIFairy
  2. Utilice Flask-Marshmallow para definir los esquemas de entradas/salidas a los puntos finales de la API
  3. Genere la documentación de la API usando APIFairy
  4. Integre una base de datos relacional con los puntos finales de la API
  5. Implemente la autenticación básica y de token mediante Flask-HTTPAuth

¿Qué es APIFairy?

APIFairy es un marco de API escrito por Miguel Grinberg que permite crear fácilmente una API con Flask.

APIFairy proporciona cuatro componentes clave para crear fácilmente una API en Flask:

  1. Decoradores
  2. esquemas
  3. Autenticación
  4. Documentación

Exploremos cada uno en detalle...

Decoradores

APIFairy proporciona un conjunto de decoradores para definir las entradas, las salidas y la autenticación para cada extremo de la API:

Decoradores de hadas API

APIFairy proporciona cinco decoradores principales:

  1. @argumentos : especifica los argumentos de entrada en la cadena de consulta de la URL
  2. @body : especifica el cuerpo JSON de entrada como un esquema
  3. @response : especifica el cuerpo JSON de salida como un esquema
  4. @other_responses : especifica respuestas adicionales (a menudo errores) que se pueden devolver ( solo documentación )
  5. @authenticate - especifica el proceso de autenticación

esquemas

La entrada (usando el @bodydecorador) y la salida (usando el @responsedecorador) de un punto final de API se definen como esquemas:

class EntrySchema(ma.Schema):
    """Schema defining the attributes in a journal entry."""
    id = ma.Integer()
    entry = ma.String()
    user_id = ma.Integer()

Los esquemas utilizan malvavisco para definir los tipos de datos como clases.

Autenticación

El @authenticatedecorador se utiliza para verificar el encabezado de autenticación proporcionado en la solicitud de URL para cada punto final de la API. El esquema de autenticación se implementa mediante Flask-HTTPAuth , que también fue creado por Miguel Grinberg.

Un enfoque típico de autenticación de API sería definir la autenticación básica para proteger la ruta para recuperar un token de autenticación:

basic_auth = HTTPBasicAuth()

@basic_auth.verify_password
def verify_password(email, password):
    user = User.query.filter_by(email=email).first()
    if user.is_password_correct(password):
        return user

Y también para definir la autenticación de token para proteger la mayoría de las rutas basadas en un token de autenticación sensible al tiempo:

token_auth = HTTPTokenAuth()

@token_auth.verify_token
def verify_token(auth_token):
    return User.verify_auth_token(auth_token)

Documentación

Una de las excelentes características de APIFairy es la hermosa documentación de la API que se genera automáticamente:

Documentación API - Página principal

La documentación se genera en base a cadenas de documentación en el código fuente junto con las siguientes variables de configuración:

  1. APIFAIRY_TITLE- nombre del proyecto
  2. APIFAIRY_VERSION- cadena de versión del proyecto
  3. APIFAIRY_UI- formato de la documentación de la API

Para APIFAIRY_UI, puede generar plantillas a partir de uno de los siguientes procesadores de documentación de OpenAPI:

  1. Interfaz de usuario de Swagger
  2. ReDoc
  3. RapiDoc
  4. Elementos

Para obtener una lista completa de las variables de configuración disponibles, consulte los documentos de configuración .

¿Qué estamos construyendo?

Desarrollará una API de diario en este tutorial, lo que permitirá a los usuarios llevar un diario de eventos. Puede encontrar el código fuente completo en el repositorio de Flass -journal-api en GitLab.

Paquetes clave de Python utilizados:

  1. Flask : micro-marco para el desarrollo de aplicaciones web Python
  2. APIFairy : marco API para Flask, que utiliza-
  3. Flask-SQLAlchemy : ORM (asignador relacional de objetos) para Flask

Desarrollará la API de forma incremental:

  1. Cree los puntos finales de API para trabajar con entradas de diario
  2. Generar documentación de la API
  3. Agregar una base de datos relacional para almacenar las entradas del diario
  4. Agregue autenticación para proteger los puntos finales de la API

Puntos finales de la API

Pasemos a crear una API usando Flask y APIFairy...

Inicialización del proyecto

Comience creando una nueva carpeta de proyecto y un entorno virtual:

$ mkdir flask-journal-api
$ cd flask-journal-api
$ python3 -m venv venv
$ source venv/bin/activate
(venv)$

Siéntete libre de cambiar virtualenv y Pip por Poetry o Pipenv . Para obtener más información, revise Entornos modernos de Python .

Continúe y agregue los siguientes archivos y carpetas:

├── app.py
├── instance
│   └── .gitkeep
├── project
│   ├── __init__.py
│   └── journal_api
│       ├── __init__.py
│       └── routes.py
└── requirements.txt

A continuación, para instalar los paquetes de Python necesarios, agregue las dependencias al archivo requirements.txt en la raíz del proyecto:

apifairy==0.9.1
Flask==2.1.2
Flask-SQLAlchemy==2.5.1
marshmallow-sqlalchemy==0.28.0

Instalar:

(venv)$ pip install -r requirements.txt

Este proyecto de Flask utilizará dos prácticas recomendadas para las aplicaciones de Flask:

  1. Application Factory : se utiliza para crear la aplicación Flask en una función
  2. Blueprints : se utiliza para organizar un grupo de vistas relacionadas

Fábrica de aplicaciones

Comience definiendo la función de Application Factory en project/__init__.py :

from apifairy import APIFairy
from flask import Flask, json
from flask_marshmallow import Marshmallow

# -------------
# Configuration
# -------------

# Create the instances of the Flask extensions in the global scope,
# but without any arguments passed in. These instances are not
# attached to the Flask application at this point.
apifairy = APIFairy()
ma = Marshmallow()


# ----------------------------
# Application Factory Function
# ----------------------------

def create_app():
    # Create the Flask application
    app = Flask(__name__)

    initialize_extensions(app)
    register_blueprints(app)
    return app


# ----------------
# Helper Functions
# ----------------

def initialize_extensions(app):
    # Since the application instance is now created, pass it to each Flask
    # extension instance to bind it to the Flask application instance (app)
    apifairy.init_app(app)
    ma.init_app(app)


def register_blueprints(app):
    # Import the blueprints
    from project.journal_api import journal_api_blueprint

    # Since the application instance is now created, register each Blueprint
    # with the Flask application instance (app)
    app.register_blueprint(journal_api_blueprint, url_prefix='/journal')

Con la función Application Factory definida, se puede llamar en app.py en la carpeta de nivel superior del proyecto:

from project import create_app


# Call the application factory function to construct a Flask application
# instance using the development configuration
app = create_app()

Plano

Vamos a definir el journal_apiplan. Comience definiendo el journal_apimodelo en project/journal_api/__init__.py :

"""
The 'journal_api' blueprint handles the API for managing journal entries.
Specifically, this blueprint allows for journal entries to be added, edited,
and deleted.
"""
from flask import Blueprint

journal_api_blueprint = Blueprint('journal_api', __name__, template_folder='templates')

from . import routes

Ahora es el momento de definir los extremos de la API para el diario en project/journal_api/routes.py .

Comience con las importaciones necesarias:

from apifairy import body, other_responses, response
from flask import abort

from project import ma
from . import journal_api_blueprint

Para esta versión inicial de Flask Journal API, la base de datos será una lista de entradas de diario:

# --------
# Database
# --------

messages = [
    dict(id=1, entry='The sun was shining when I woke up this morning.'),
    dict(id=2, entry='I tried a new fruit mixture in my oatmeal for breakfast.'),
    dict(id=3, entry='Today I ate a great sandwich for lunch.')
]

A continuación, defina los esquemas para crear una nueva entrada de diario y para devolver las entradas de diario:

# -------
# Schemas
# -------

class NewEntrySchema(ma.Schema):
    """Schema defining the attributes when creating a new journal entry."""
    entry = ma.String(required=True)


class EntrySchema(ma.Schema):
    """Schema defining the attributes in a journal entry."""
    id = ma.Integer()
    entry = ma.String()


new_entry_schema = NewEntrySchema()
entry_schema = EntrySchema()
entries_schema = EntrySchema(many=True)

Ambas clases de esquema se heredan de ma.Schema , que proporciona Flask-Marshmallow. También es una buena idea crear objetos de estos esquemas, ya que esto le permite definir un esquema que puede devolver múltiples entradas (usando el many=Trueargumento).

¡Ahora estamos listos para definir los puntos finales de la API!

Rutas

Comience recuperando todas las entradas del diario:

@journal_api_blueprint.route('/', methods=['GET'])
@response(entries_schema)
def journal():
    """Return all journal entries"""
    return messages

Esta función de vista usa el @responsedecorador para definir que se devuelvan varias entradas. La función de visualización devuelve la lista completa de entradas de diario ( return messages).

A continuación, cree el extremo de la API para agregar una nueva entrada de diario:

@journal_api_blueprint.route('/', methods=['POST'])
@body(new_entry_schema)
@response(entry_schema, 201)
def add_journal_entry(kwargs):
    """Add a new journal entry"""
    new_message = dict(**kwargs, id=messages[-1]['id']+1)
    messages.append(new_message)
    return new_message

Esta función de vista utiliza el @bodydecorador para definir la entrada al punto final de la API y el @responsedecorador para definir la salida del punto final de la API.

Los datos de entrada que se analizan desde el @bodydecorador se pasan a la add_journal_entry()función de vista como el argumento kwargs( argumentos de palabras clave ) . Estos datos luego se utilizan para crear una nueva entrada de diario y agregarla a la base de datos:

new_message = dict(**kwargs, id=messages[-1]['id']+1)
messages.append(new_message)

A continuación, se devuelve el asiento de diario recién creado ( return new_message). Observe cómo el @responsedecorador define el código de retorno como 201 (Creado) para indicar que la entrada del diario se agregó a la base de datos.

Cree el punto final de API para recuperar una entrada de diario específica:

@journal_api_blueprint.route('/<int:index>', methods=['GET'])
@response(entry_schema)
@other_responses({404: 'Entry not found'})
def get_journal_entry(index):
    """Return a journal entry"""
    if index >= len(messages):
        abort(404)

    return messages[index]

Esta función de vista usa el @other_responsesdecorador para especificar respuestas no estándar.

¡ El @other_responsesdecorador solo se utiliza con fines de documentación! No proporciona ninguna funcionalidad en términos de devolución de códigos de error.

Cree el punto final de API para actualizar una entrada de diario:

@journal_api_blueprint.route('/<int:index>', methods=['PUT'])
@body(new_entry_schema)
@response(entry_schema)
@other_responses({404: 'Entry not found'})
def update_journal_entry(data, index):
    """Update a journal entry"""
    if index >= len(messages):
        abort(404)

    messages[index] = dict(data, id=index+1)
    return messages[index]

Esta función de vista usa los decoradores @bodyy @responsepara definir las entradas y salidas (respectivamente) para este punto final de API. Además, el @other_responsesdecorador define la respuesta no estándar si no se encuentra la entrada del diario.

Finalmente, cree el punto final de API para eliminar una entrada de diario:

@journal_api_blueprint.route('/<int:index>', methods=['DELETE'])
@other_responses({404: 'Entry not found'})
def delete_journal_entry(index):
    """Delete a journal entry"""
    if index >= len(messages):
        abort(404)

    messages.pop(index)
    return '', 204

Esta función de vista no utiliza los decoradores @bodyy @response, ya que no hay entradas ni salidas para este extremo de la API. Si la entrada del diario se elimina correctamente, se devuelve un código de estado 204 (Sin contenido) sin datos.

Ejecución de la aplicación Flask

Para probar las cosas, dentro de una ventana de terminal, configure la aplicación Flask y ejecute el servidor de desarrollo:

(venv) $ export FLASK_APP=app.py
(venv) $ export FLASK_ENV=development
(venv) $ flask run

Luego, en una ventana de terminal diferente, puede interactuar con la API. Siéntase libre de usar la herramienta que prefiera aquí, como cURL, HTTPie , Requests o Postman .

Ejemplo de solicitudes:

$ python3

>>> import requests
>>>
>>> r = requests.get('http://127.0.0.1:5000/journal/')
>>> print(r.text)
>>>
>>> post_data = {'entry': "some message"}
>>> r = requests.post('http://127.0.0.1:5000/journal/', json=post_data)
>>> print(r.text)

¿Quiere probar los puntos finales de la API más fácilmente? Consulte este script , que agrega comandos CLI para interactuar con los puntos finales de la API para recuperar, crear, actualizar y eliminar entradas del diario.

Documentación

¡Una característica increíble de APIFairy es la creación automática de documentación API!

Hay tres aspectos clave para configurar la documentación de la API:

  1. Cadenas de documentos para los puntos finales de la API (es decir, ver funciones)
  2. Docstring para el proyecto API general
  3. Variables de configuración para especificar el aspecto de la documentación de la API

Ya cubrimos el primer elemento en la sección anterior, ya que incluimos las cadenas de documentación para cada función de vista. Por ejemplo, la journal()función de vista tiene una breve descripción del propósito de este punto final de la API:

@journal_api_blueprint.route('/', methods=['GET'])
@response(entries_schema)
def journal():
    """Return all journal entries"""
    return messages

A continuación, debemos incluir la cadena de documentación para describir el proyecto general en la parte superior del archivo project/__init__.py :

"""
Welcome to the documentation for the Flask Journal API!

## Introduction

The Flask Journal API is an API (Application Programming Interface) for creating a **daily journal** that documents events that happen each day.

## Key Functionality

The Flask Journal API has the following functionality:

1. Work with journal entries:
  * Create a new journal entry
  * Update a journal entry
  * Delete a journal entry
  * View all journal entries
2. <More to come!>

## Key Modules

This project is written using Python 3.10.1.

The project utilizes the following modules:

* **Flask**: micro-framework for web application development which includes the following dependencies:
  * **click**: package for creating command-line interfaces (CLI)
  * **itsdangerous**: cryptographically sign data
  * **Jinja2**: templating engine
  * **MarkupSafe**: escapes characters so text is safe to use in HTML and XML
  * **Werkzeug**: set of utilities for creating a Python application that can talk to a WSGI server
* **APIFairy**: API framework for Flask which includes the following dependencies:
  * **Flask-Marshmallow** - Flask extension for using Marshmallow (object serialization/deserialization library)
  * **Flask-HTTPAuth** - Flask extension for HTTP authentication
  * **apispec** - API specification generator that supports the OpenAPI specification
* **pytest**: framework for testing Python projects
"""
...

Esta cadena de documentación se utiliza para describir el proyecto general, incluida la funcionalidad clave proporcionada y los paquetes clave de Python utilizados por el proyecto.

Finalmente, es necesario definir algunas variables de configuración para especificar el aspecto de la documentación de la API. Actualice la create_app()función en project/__init__.py :

def create_app():
    # Create the Flask application
    app = Flask(__name__)

    # Configure the API documentation
    app.config['APIFAIRY_TITLE'] = 'Flask Journal API'
    app.config['APIFAIRY_VERSION'] = '0.1'
    app.config['APIFAIRY_UI'] = 'elements'

    initialize_extensions(app)
    register_blueprints(app)

    return app

¿Listo para ver la documentación del proyecto? Inicie el servidor de desarrollo de Flask a través flask runde y luego navegue a http://127.0.0.1:5000/docs para ver la documentación de la API creada por APIFairy:

Documentación API - Página principal

En el panel de la izquierda, hay una lista de puntos finales de API para el journal_apiplan. Al hacer clic en uno de los puntos finales, se muestran todos los detalles sobre ese punto final:

Documentación de la API - Obtener el punto final de la API de entrada de diario

Lo sorprendente de esta documentación de la API es la capacidad de ver cómo funcionan los puntos finales de la API (suponiendo que se esté ejecutando el servidor de desarrollo de Flask). En el panel derecho de la documentación, ingrese un índice de entrada de diario y haga clic en "Enviar solicitud de API". A continuación, se muestra la respuesta de la API:

Documentación de API - Obtener respuesta de API de entrada de diario

¡Esta documentación interactiva facilita a los usuarios la comprensión de la API!

Base de datos

Para fines de demostración, en este tutorial se utilizará una base de datos SQLite.

Configuración

Dado que Flask-SQLAlchemy ya estaba instalado al comienzo de este tutorial, debemos configurarlo en el archivo project/__init__.py .

Comience creando un SQLAlchemy()objeto en la sección 'Configuración':

...

from apifairy import APIFairy
from flask import Flask, json
from flask_marshmallow import Marshmallow
from flask_sqlalchemy import SQLAlchemy  # <-- NEW!!


# -------------
# Configuration
# -------------

# Create the instances of the Flask extensions in the global scope,
# but without any arguments passed in. These instances are not
# attached to the Flask application at this point.
apifairy = APIFairy()
ma = Marshmallow()
database = SQLAlchemy()  # <-- NEW!!

...

A continuación, actualice la create_app()función para especificar las variables de configuración necesarias:

def create_app():
    # Create the Flask application
    app = Flask(__name__)

    # Configure the API documentation
    app.config['APIFAIRY_TITLE'] = 'Flask Journal API'
    app.config['APIFAIRY_VERSION'] = '0.1'
    app.config['APIFAIRY_UI'] = 'elements'

    # NEW!
    # Configure the SQLite database (intended for development only!)
    app.config['SQLALCHEMY_DATABASE_URI'] = f"sqlite:///{os.path.join(os.getcwd(), 'instance', 'app.db')}"
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    initialize_extensions(app)
    register_blueprints(app)

    return app

Agregue la importación a la parte superior:

import os

La SQLALCHEMY_DATABASE_URIvariable de configuración es fundamental para identificar la ubicación de la base de datos SQLite. Para este tutorial, la base de datos se almacena en instance/app.db .

Finalmente, actualice la initialize_extensions()función para inicializar el objeto Flask-SQLAlchemy:

def initialize_extensions(app):
    # Since the application instance is now created, pass it to each Flask
    # extension instance to bind it to the Flask application instance (app)
    apifairy.init_app(app)
    ma.init_app(app)
    database.init_app(app)  # <-- NEW!!

¿Quiere obtener más información sobre cómo se conecta esta aplicación Flask? Consulte mi curso sobre cómo crear, probar e implementar una aplicación Flask:

Modelo de base de datos

Cree un nuevo archivo project/models.py para definir la tabla de la base de datos para representar las entradas del diario:

from project import database


class Entry(database.Model):
    """Class that represents a journal entry."""
    __tablename__ = 'entries'

    id = database.Column(database.Integer, primary_key=True)
    entry = database.Column(database.String, nullable=False)

    def __init__(self, entry: str):
        self.entry = entry

    def update(self, entry: str):
        self.entry = entry

    def __repr__(self):
        return f'<Entry: {self.entry}>'

Esta nueva clase, Entry, especifica que la entriestabla de la base de datos contendrá dos elementos (¡por ahora!) para representar una entrada de diario:

  1. id- la clave principal ( primary_key=True) de la tabla, lo que significa que es un identificador único para cada elemento (fila) de la tabla
  2. entry- cadena para almacenar el texto de la entrada del diario

Si bien models.py define la tabla de la base de datos, no crea las tablas en la base de datos SQLite. Para crear las tablas, inicie Flask shell en una ventana de terminal:

(venv)$ flask shell

>>> from project import database
>>> database.drop_all()
>>> database.create_all()
>>> quit()

(venv)$

Actualizaciones de API de diario

Dado que estamos progresando en el uso de una base de datos SQLite, comience eliminando la temporal database(lista de Python) que se definió en project/journal_api/routes.py :

# --------
# Database
# --------

messages = [
    dict(id=1, entry='The sun was shining when I woke up this morning.'),
    dict(id=2, entry='I tried a new fruit mixture in my oatmeal for breakfast.'),
    dict(id=3, entry='Today I ate a great sandwich for lunch.')
]

A continuación, debemos actualizar cada extremo de la API (es decir, las funciones de vista) para utilizar la base de datos SQLite.

Comience actualizando la journal()función de vista:

@journal_api_blueprint.route('/', methods=['GET'])
@response(entries_schema)
def journal():
    """Return all journal entries"""
    return Entry.query.all()

La lista completa de entradas de diario ahora se recupera de la base de datos SQLite. Observe cómo los esquemas o decoradores para esta función de vista no necesitaban cambiar... ¡solo el proceso subyacente para cambiar a los usuarios!

Añadir la importación:

from project.models import Entry

A continuación, actualice la add_journal_entry()función de vista:

@journal_api_blueprint.route('/', methods=['POST'])
@body(new_entry_schema)
@response(entry_schema, 201)
def add_journal_entry(kwargs):
    """Add a new journal entry"""
    new_message = Entry(**kwargs)
    database.session.add(new_message)
    database.session.commit()
    return new_message

Las entradas a esta función de vista se especifican mediante new_entry_schema:

class NewEntrySchema(ma.Schema):
    """Schema defining the attributes when creating a new journal entry."""
    entry = ma.String(required=True)

new_entry_schema = NewEntrySchema()

La entrycadena se usa para crear una nueva instancia de la Entryclase (definida en models.py ) y esta entrada de diario se agrega a la base de datos.

Añadir la importación:

from project import database

A continuación, actualice get_journal_entry():

@journal_api_blueprint.route('/<int:index>', methods=['GET'])
@response(entry_schema)
@other_responses({404: 'Entry not found'})
def get_journal_entry(index):
    """Return a journal entry"""
    entry = Entry.query.filter_by(id=index).first_or_404()
    return entry

Esta función ahora intenta buscar la entrada de diario especificada (basada en index):

entry = Entry.query.filter_by(id=index).first_or_404()

Si la entrada existe, se devuelve al usuario. Si la entrada no existe, se devuelve un error 404 (No encontrado).

A continuación, actualice update_journal_entry():

@journal_api_blueprint.route('/<int:index>', methods=['PUT'])
@body(new_entry_schema)
@response(entry_schema)
@other_responses({404: 'Entry not found'})
def update_journal_entry(data, index):
    """Update a journal entry"""
    entry = Entry.query.filter_by(id=index).first_or_404()
    entry.update(data['entry'])
    database.session.add(entry)
    database.session.commit()
    return entry

La update_journal_entry()función de vista ahora intenta recuperar la entrada de diario especificada:

entry = Entry.query.filter_by(id=index).first_or_404()

Si la entrada de diario existe, la entrada se actualiza con el nuevo texto y luego se guarda en la base de datos.

Por último, actualiza delete_journal_entry():

@journal_api_blueprint.route('/<int:index>', methods=['DELETE'])
@other_responses({404: 'Entry not found'})
def delete_journal_entry(index):
    """Delete a journal entry"""
    entry = Entry.query.filter_by(id=index).first_or_404()
    database.session.delete(entry)
    database.session.commit()
    return '', 204

Si se encuentra la entrada de diario especificada, se elimina de la base de datos.

Ejecute el servidor de desarrollo. Pruebe cada uno de los puntos finales para asegurarse de que aún funcionan.

Manejo de errores

Dado que este proyecto de Flask es una API, los códigos de error deben devolverse en formato JSON en lugar del formato HTML típico.

En el proyecto Flask, esto se puede lograr mediante el uso de un controlador de errores personalizado. En project/__init__.py , defina una nueva función ( register_error_handlers()) en la parte inferior del archivo:

def register_error_handlers(app):
    @app.errorhandler(HTTPException)
    def handle_http_exception(e):
        """Return JSON instead of HTML for HTTP errors."""
        # Start with the correct headers and status code from the error
        response = e.get_response()
        # Replace the body with JSON
        response.data = json.dumps({
            'code': e.code,
            'name': e.name,
            'description': e.description,
        })
        response.content_type = 'application/json'
        return response

Esta función registra un nuevo controlador de errores para cuando HTTPExceptionse genera un correo electrónico para convertir la salida en formato JSON.

Añadir la importación:

from werkzeug.exceptions import HTTPException

Además, actualice la función Application Factory create_app(), para llamar a esta nueva función:

def create_app():
    # Create the Flask application
    app = Flask(__name__)

    # Configure the API documentation
    app.config['APIFAIRY_TITLE'] = 'Flask Journal API'
    app.config['APIFAIRY_VERSION'] = '0.1'
    app.config['APIFAIRY_UI'] = 'elements'

    # Configure the SQLite database (intended for development only!)
    app.config['SQLALCHEMY_DATABASE_URI'] = f"sqlite:///{os.path.join(os.getcwd(), 'instance', 'app.db')}"
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    initialize_extensions(app)
    register_blueprints(app)
    register_error_handlers(app)  # NEW!!

    return app

Autenticación

La autenticación es el proceso de validación de la identidad de un usuario que intenta acceder a un sistema, que en este caso es la API.

La autorización, por otro lado, es el proceso de verificar a qué recursos específicos debe tener acceso un usuario específico.

APIFairy utiliza Flask-HTTPAuth para el soporte de autenticación. En este tutorial, usaremos Flask-HTTPAuth de dos maneras:

  1. Autenticación básica : se utiliza para generar un token basado en el correo electrónico/contraseña del usuario
  2. Autenticación de token : se utiliza para autenticar al usuario en todos los demás puntos finales de la API

La autenticación de token utilizada a través de Flask-HTTPAuth a menudo se denomina autenticación de portador, ya que el proceso invoca la concesión de acceso al "portador" del token. El token debe incluirse en los encabezados HTTP en el encabezado Autorización, como "Autorización: Portador".

El siguiente diagrama ilustra un flujo típico de cómo un nuevo usuario interactúa con la aplicación para recuperar un token de autenticación:

Diagrama de flujo de API de Flask Journal

Configuración

Dado que Flask-HTTPAuth ya estaba instalado cuando se instaló APIFairy al comienzo de este tutorial, solo necesitamos configurarlo en el archivo project/__init__.py .

Comience creando objetos separados para la autenticación básica y de token:

...

import os

from apifairy import APIFairy
from flask import Flask, json
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth  # NEW!!
from flask_marshmallow import Marshmallow
from flask_sqlalchemy import SQLAlchemy
from werkzeug.exceptions import HTTPException


# -------------
# Configuration
# -------------

# Create the instances of the Flask extensions in the global scope,
# but without any arguments passed in. These instances are not
# attached to the Flask application at this point.
apifairy = APIFairy()
ma = Marshmallow()
database = SQLAlchemy()
basic_auth = HTTPBasicAuth()  # NEW!!
token_auth = HTTPTokenAuth()  # NEW!!

...

No se necesitan más actualizaciones en project/__init__.py .

Modelo de base de datos

En project/models.py , se debe crear un nuevo Usermodelo para representar a un usuario:

class User(database.Model):
    __tablename__ = 'users'

    id = database.Column(database.Integer, primary_key=True)
    email = database.Column(database.String, unique=True, nullable=False)
    password_hashed = database.Column(database.String(128), nullable=False)
    entries = database.relationship('Entry', backref='user', lazy='dynamic')
    auth_token = database.Column(database.String(64), index=True)
    auth_token_expiration = database.Column(database.DateTime)

    def __init__(self, email: str, password_plaintext: str):
        """Create a new User object."""
        self.email = email
        self.password_hashed = self._generate_password_hash(password_plaintext)

    def is_password_correct(self, password_plaintext: str):
        return check_password_hash(self.password_hashed, password_plaintext)

    def set_password(self, password_plaintext: str):
        self.password_hashed = self._generate_password_hash(password_plaintext)

    @staticmethod
    def _generate_password_hash(password_plaintext):
        return generate_password_hash(password_plaintext)

    def generate_auth_token(self):
        self.auth_token = secrets.token_urlsafe()
        self.auth_token_expiration = datetime.utcnow() + timedelta(minutes=60)
        return self.auth_token

    @staticmethod
    def verify_auth_token(auth_token):
        user = User.query.filter_by(auth_token=auth_token).first()
        if user and user.auth_token_expiration > datetime.utcnow():
            return user

    def revoke_auth_token(self):
        self.auth_token_expiration = datetime.utcnow()

    def __repr__(self):
        return f'<User: {self.email}>'

Agrega las importaciones:

import secrets
from datetime import datetime, timedelta

from werkzeug.security import check_password_hash, generate_password_hash

El Usermodelo utiliza werkzeug.securitypara cifrar la contraseña del usuario antes de almacenarla en la base de datos.

Recuerde: ¡Nunca almacene la contraseña de texto sin formato en una base de datos!

El Usermodelo se utiliza secretspara generar un token de autenticación para un usuario específico. Este token se crea en el generate_auth_token()método e incluye una fecha/hora de vencimiento de 60 minutos en el futuro:

def generate_auth_token(self):
    self.auth_token = secrets.token_urlsafe()
    self.auth_token_expiration = datetime.utcnow() + timedelta(minutes=60)
    return self.auth_token

Hay un método estático verify_auth_token(), que se usa para verificar el token de autenticación (teniendo en cuenta el tiempo de vencimiento) y devolver al usuario un token válido:

@staticmethod
def verify_auth_token(auth_token):
    user = User.query.filter_by(auth_token=auth_token).first()
    if user and user.auth_token_expiration > datetime.utcnow():
        return user

Otro método de interés es revoke_auth_token(), que se utiliza para revocar el token de autenticación de un usuario específico:

def revoke_auth_token(self):
    self.auth_token_expiration = datetime.utcnow()

Modelo de entrada

Para establecer la relación de uno a muchos entre el usuario ("uno") y sus entradas ("muchos"), el Entrymodelo debe actualizarse para vincular las tablas entriesy entre sí:users

class Entry(database.Model):
    """Class that represents a journal entry."""
    __tablename__ = 'entries'

    id = database.Column(database.Integer, primary_key=True)
    entry = database.Column(database.String, nullable=False)
    user_id = database.Column(database.Integer, database.ForeignKey('users.id'))  # <-- NEW!!

    def __init__(self, entry: str):
        self.entry = entry

    def update(self, entry: str):
        self.entry = entry

    def __repr__(self):
        return f'<Entry: {self.entry}>'

El Usermodelo ya contiene el enlace de regreso a la entriestabla:

entries = database.relationship('Entry', backref='user', lazy='dynamic')

Plan de API de usuarios

La funcionalidad de administración de usuarios del proyecto Flask se definirá en un Blueprint separado llamado users_api_blueprint.

Comience creando un nuevo directorio en "proyecto" llamado "users_api". Dentro de ese directorio, cree un archivo __init__.py :

from flask import Blueprint


users_api_blueprint = Blueprint('users_api', __name__)

from . import authentication, routes

Este nuevo Blueprint debe registrarse con Flask appen projects/__init__.py dentro de la register_blueprints()función:

def register_blueprints(app):
    # Import the blueprints
    from project.journal_api import journal_api_blueprint
    from project.users_api import users_api_blueprint  # NEW!!

    # Since the application instance is now created, register each Blueprint
    # with the Flask application instance (app)
    app.register_blueprint(journal_api_blueprint, url_prefix='/journal')
    app.register_blueprint(users_api_blueprint, url_prefix='/users')  # NEW!!

Funciones de autenticación

Para usar Flask-HTTPAuth, se deben definir varias funciones para manejar la verificación de las credenciales del usuario.

Cree un nuevo archivo project/users_api/authentication.py para manejar la autenticación básica y la autenticación de token.

Para la autenticación básica (comprobar el correo electrónico y la contraseña de un usuario):

from werkzeug.exceptions import Forbidden, Unauthorized

from project import basic_auth, token_auth
from project.models import User


@basic_auth.verify_password
def verify_password(email, password):
    user = User.query.filter_by(email=email).first()
    if user is None:
        return None

    if user.is_password_correct(password):
        return user


@basic_auth.error_handler
def basic_auth_error(status=401):
    error = (Forbidden if status == 403 else Unauthorized)()
    return {
        'code': error.code,
        'message': error.name,
        'description': error.description,
    }, error.code, {'WWW-Authenticate': 'Form'}

La verify_password()función se utiliza para comprobar que existe un usuario y que su contraseña es correcta. Flask-HTTPAuth utilizará esta función para verificar la contraseña cuando se necesite una autenticación básica (gracias al @basic_auth.verify_passworddecorador).

Además, se define un controlador de errores para la autenticación básica que devuelve información sobre el error en formato JSON.

Para la autenticación del token (procesar un token para determinar si el usuario es válido):

@token_auth.verify_token
def verify_token(auth_token):
    return User.verify_auth_token(auth_token)


@token_auth.error_handler
def token_auth_error(status=401):
    error = (Forbidden if status == 403 else Unauthorized)()
    return {
        'code': error.code,
        'message': error.name,
        'description': error.description,
    }, error.code

La verify_token()función se utiliza para comprobar si un token de autenticación es válido. Flask-HTTPAuth utilizará esta función para verificar el token cuando se necesite la autenticación del token (gracias al @token_auth.verify_tokendecorador).

Además, se define un controlador de errores para la autenticación del token que devuelve información sobre el error en formato JSON.

Rutas de usuarios

En el users_api_blueprint, habrá dos rutas:

  1. Registro de un nuevo usuario
  2. Recuperar un token de autenticación

Para comenzar, se debe definir un nuevo conjunto de esquemas (usando malvavisco) en projects/users_api/routes.py :

from project import ma

from . import users_api_blueprint

# -------
# Schemas
# -------

class NewUserSchema(ma.Schema):
    """Schema defining the attributes when creating a new user."""
    email = ma.String()
    password_plaintext = ma.String()


class UserSchema(ma.Schema):
    """Schema defining the attributes of a user."""
    id = ma.Integer()
    email = ma.String()


class TokenSchema(ma.Schema):
    """Schema defining the attributes of a token."""
    token = ma.String()


new_user_schema = NewUserSchema()
user_schema = UserSchema()
token_schema = TokenSchema()

Estos esquemas se utilizarán para definir las entradas y salidas de las funciones de vista definidas en este archivo.

Registro de un nuevo usuario

A continuación, defina la función de vista para registrar un nuevo usuario:

@users_api_blueprint.route('/', methods=['POST'])
@body(new_user_schema)
@response(user_schema, 201)
def register(kwargs):
    """Create a new user"""
    new_user = User(**kwargs)
    database.session.add(new_user)
    database.session.commit()
    return new_user

Agrega las importaciones:

from apifairy import authenticate, body, other_responses, response

from project import basic_auth, database, ma
from project.models import User

Este extremo de la API usa new_user_schemapara especificar que el correo electrónico y la contraseña son las entradas.

NOTA: Dado que el correo electrónico y la contraseña se envían a este extremo de la API, es un buen momento para recordar que el uso de HTTP es aceptable durante las pruebas de desarrollo, pero siempre se debe usar HTTPS (seguro) en la producción.

El correo electrónico y la contraseña (definidos como los kwargsargumentos de palabra clave) se desempaquetan para crear un nuevo Userobjeto, que se guarda en la base de datos:

new_user = User(**kwargs)
database.session.add(new_user)
database.session.commit()

La salida del extremo de la API se define mediante user_schema, que es el ID y el correo electrónico del nuevo usuario.

Recuperar un token de autenticación

La otra función de vista para definir en projects/users_api/routes.py es para recuperar el token de autenticación:

@users_api_blueprint.route('/get-auth-token', methods=['POST'])
@authenticate(basic_auth)
@response(token_schema)
@other_responses({401: 'Invalid username or password'})
def get_auth_token():
    """Get authentication token"""
    user = basic_auth.current_user()
    token = user.generate_auth_token()
    database.session.add(user)
    database.session.commit()
    return dict(token=token)

El @authenticatedecorador se usa por primera vez en este tutorial y especifica que se debe usar la autenticación básica para proteger esta ruta:

@authenticate(basic_auth)

Cuando el usuario desea recuperar su token de autenticación, debe enviar una solicitud POST a este extremo de la API con el correo electrónico y la contraseña incrustados en el encabezado "Autorización". Como ejemplo, el siguiente comando de Python que utiliza el paquete de solicitudes podría realizarse en este punto final de la API:

>>> import requests
>>> r = requests.post(
    'http://127.0.0.1:5000/users/get-auth-token',
    auth=('pkennedy@hey.com', 'FlaskIsAwesome123')
)

Si la autenticación básica es exitosa, la función de visualización recupera al usuario actual mediante el current_user()método proporcionado por Flask-HTTPAuth:

user = basic_auth.current_user()

Se crea un nuevo token de autenticación para ese usuario:

token = user.generate_auth_token()

Y ese token se guarda en la base de datos para que pueda usarse para autenticar al usuario en el futuro (¡al menos durante los próximos 60 minutos!).

Finalmente, el nuevo token de autenticación se devuelve para que el usuario lo guarde para todas las llamadas API posteriores.

Actualizaciones de puntos finales de API

Con un proceso de autenticación implementado, es hora de agregar algunas protecciones a los puntos finales de API existentes para asegurarse de que solo los usuarios válidos puedan acceder a la aplicación.

Estas actualizaciones son para las funciones de visualización definidas en projects/journal_api/routes.py .

Primero, actualice journal()para devolver solo las entradas de diario para el usuario actual:

@journal_api_blueprint.route('/', methods=['GET'])
@authenticate(token_auth)
@response(entries_schema)
def journal():
    """Return journal entries"""
    user = token_auth.current_user()
    return Entry.query.filter_by(user_id=user.id).all()

Actualice las importaciones en la parte superior así:

from apifairy import authenticate, body, other_responses, response
from flask import abort

from project import database, ma, token_auth
from project.models import Entry

from . import journal_api_blueprint

El @authenticatedecorador especifica que se debe usar la autenticación de token al acceder a este punto final de la API. Como ejemplo, la siguiente solicitud GET podría realizarse mediante Solicitudes ( después de que se haya recuperado el token de autenticación ):

>>> import requests
>>> headers = {'Authorization': f'Bearer {auth_token}'}
>>> r = requests.get('http://127.0.0.1:5000/journal/', headers=headers)

Una vez que el usuario está autenticado, la lista completa de entradas de diario se recupera de la base de datos según la identificación del usuario:

user = token_auth.current_user()
return Entry.query.filter_by(user_id=user.id).all()

El decorador define la salida de este extremo de la API @response, que es una lista de entradas de diario (ID, entrada, ID de usuario).

A continuación, actualice add_journal_entry():

@journal_api_blueprint.route('/', methods=['POST'])
@authenticate(token_auth)
@body(new_entry_schema)
@response(entry_schema, 201)
def add_journal_entry(kwargs):
    """Add a new journal entry"""
    user = token_auth.current_user()
    new_message = Entry(user_id=user.id, **kwargs)
    database.session.add(new_message)
    database.session.commit()
    return new_message

Al igual que con la función de vista anterior, el @authenticatedecorador se usa para especificar que se debe usar la autenticación de token al acceder a este punto final de la API. Además, la entrada de diario ahora se agrega especificando el ID de usuario que debe asociarse con la entrada de diario:

user = token_auth.current_user()
new_message = Entry(user_id=user.id, **kwargs)

La nueva entrada de diario se guarda en la base de datos y se devuelve la entrada de diario (según lo definido por el @responsedecorador).

A continuación, actualice get_journal_entry():

@journal_api_blueprint.route('/<int:index>', methods=['GET'])
@authenticate(token_auth)
@response(entry_schema)
@other_responses({403: 'Forbidden', 404: 'Entry not found'})
def get_journal_entry(index):
    """Return a journal entry"""
    user = token_auth.current_user()
    entry = Entry.query.filter_by(id=index).first_or_404()

    if entry.user_id != user.id:
        abort(403)
    return entry

El @authenticatedecorador se agrega para especificar que se necesita autenticación de token para acceder a este punto final de API.

Al intentar recuperar una entrada de diario, se agrega una verificación adicional para asegurarse de que el usuario que intenta acceder a la entrada de diario es el "propietario" real de la entrada. De lo contrario, se devuelve un código de error 403 (Prohibido) a través de la abort()función de Flask:

if entry.user_id != user.id:
        abort(403)

Tenga en cuenta que este punto final de la API tiene dos respuestas no nominales especificadas por el @other_responsesdecorador:

@other_responses({403: 'Forbidden', 404: 'Entry not found'})

Recordatorio: El @other_responsesdecorador es solo para documentación; es responsabilidad de la función de vista generar estos errores.

A continuación, actualice update_journal_entry():

@journal_api_blueprint.route('/<int:index>', methods=['PUT'])
@authenticate(token_auth)
@body(new_entry_schema)
@response(entry_schema)
@other_responses({403: 'Forbidden', 404: 'Entry not found'})
def update_journal_entry(data, index):
    """Update a journal entry"""
    user = token_auth.current_user()
    entry = Entry.query.filter_by(id=index).first_or_404()

    if entry.user_id != user.id:
        abort(403)

    entry.update(data['entry'])
    database.session.add(entry)
    database.session.commit()
    return entry

Las actualizaciones de esta función de vista son similares a las otras funciones de vista en esta sección:

  1. @authenticatedecorador especifica que se necesita autenticación de token para acceder a este punto final de API
  2. Solo el usuario que "posee" la entrada del diario puede actualizar la entrada (de lo contrario, 403 (Prohibido))

Por último, actualiza delete_journal_entry():

@journal_api_blueprint.route('/<int:index>', methods=['DELETE'])
@authenticate(token_auth)
@other_responses({403: 'Forbidden', 404: 'Entry not found'})
def delete_journal_entry(index):
    """Delete a journal entry"""
    user = token_auth.current_user()
    entry = Entry.query.filter_by(id=index).first_or_404()

    if entry.user_id != user.id:
        abort(403)

    database.session.delete(entry)
    database.session.commit()
    return '', 204

Conclusión

Este tutorial proporcionó un recorrido de cómo crear fácil y rápidamente una API en Flask usando APIFairy.

Los decoradores son la clave para definir los puntos finales de la API:

  • Entradas :
    • @arguments- argumentos de entrada de la cadena de consulta de la URL
    • @body- estructura de la solicitud JSON
  • Salidas :
    • @response- estructura de la respuesta JSON
  • Autenticación :
    • @authenticate- enfoque de autenticación usando Flask-HTTPAuth
  • Errores :
    • @other_responses- respuestas no nominales, como códigos de error HTTP

Además, la documentación de API generada por APIFairy es excelente y proporciona información clave para los usuarios de la aplicación.

Fuente:  https://testdriven.io

#api #flask 

What is GEEK

Buddha Community

Cómo Crear Fácilmente Una API RESTful Con Flask Y APIFairy
Wilford  Pagac

Wilford Pagac

1594289280

What is REST API? An Overview | Liquid Web

What is REST?

The REST acronym is defined as a “REpresentational State Transfer” and is designed to take advantage of existing HTTP protocols when used for Web APIs. It is very flexible in that it is not tied to resources or methods and has the ability to handle different calls and data formats. Because REST API is not constrained to an XML format like SOAP, it can return multiple other formats depending on what is needed. If a service adheres to this style, it is considered a “RESTful” application. REST allows components to access and manage functions within another application.

REST was initially defined in a dissertation by Roy Fielding’s twenty years ago. He proposed these standards as an alternative to SOAP (The Simple Object Access Protocol is a simple standard for accessing objects and exchanging structured messages within a distributed computing environment). REST (or RESTful) defines the general rules used to regulate the interactions between web apps utilizing the HTTP protocol for CRUD (create, retrieve, update, delete) operations.

What is an API?

An API (or Application Programming Interface) provides a method of interaction between two systems.

What is a RESTful API?

A RESTful API (or application program interface) uses HTTP requests to GET, PUT, POST, and DELETE data following the REST standards. This allows two pieces of software to communicate with each other. In essence, REST API is a set of remote calls using standard methods to return data in a specific format.

The systems that interact in this manner can be very different. Each app may use a unique programming language, operating system, database, etc. So, how do we create a system that can easily communicate and understand other apps?? This is where the Rest API is used as an interaction system.

When using a RESTful API, we should determine in advance what resources we want to expose to the outside world. Typically, the RESTful API service is implemented, keeping the following ideas in mind:

  • Format: There should be no restrictions on the data exchange format
  • Implementation: REST is based entirely on HTTP
  • Service Definition: Because REST is very flexible, API can be modified to ensure the application understands the request/response format.
  • The RESTful API focuses on resources and how efficiently you perform operations with it using HTTP.

The features of the REST API design style state:

  • Each entity must have a unique identifier.
  • Standard methods should be used to read and modify data.
  • It should provide support for different types of resources.
  • The interactions should be stateless.

For REST to fit this model, we must adhere to the following rules:

  • Client-Server Architecture: The interface is separate from the server-side data repository. This affords flexibility and the development of components independently of each other.
  • Detachment: The client connections are not stored on the server between requests.
  • Cacheability: It must be explicitly stated whether the client can store responses.
  • Multi-level: The API should work whether it interacts directly with a server or through an additional layer, like a load balancer.

#tutorials #api #application #application programming interface #crud #http #json #programming #protocols #representational state transfer #rest #rest api #rest api graphql #rest api json #rest api xml #restful #soap #xml #yaml

An API-First Approach For Designing Restful APIs | Hacker Noon

I’ve been working with Restful APIs for some time now and one thing that I love to do is to talk about APIs.

So, today I will show you how to build an API using the API-First approach and Design First with OpenAPI Specification.

First thing first, if you don’t know what’s an API-First approach means, it would be nice you stop reading this and check the blog post that I wrote to the Farfetchs blog where I explain everything that you need to know to start an API using API-First.

Preparing the ground

Before you get your hands dirty, let’s prepare the ground and understand the use case that will be developed.

Tools

If you desire to reproduce the examples that will be shown here, you will need some of those items below.

  • NodeJS
  • OpenAPI Specification
  • Text Editor (I’ll use VSCode)
  • Command Line

Use Case

To keep easy to understand, let’s use the Todo List App, it is a very common concept beyond the software development community.

#api #rest-api #openai #api-first-development #api-design #apis #restful-apis #restful-api

Lets Cms

Lets Cms

1652251528

Opencart REST API extensions - V3.x | Rest API Integration, Affiliate

Opencart REST API extensions - V3.x | Rest API Integration : OpenCart APIs is fully integrated with the OpenCart REST API. This is interact with your OpenCart site by sending and receiving data as JSON (JavaScript Object Notation) objects. Using the OpenCart REST API you can register the customers and purchasing the products and it provides data access to the content of OpenCart users like which is publicly accessible via the REST API. This APIs also provide the E-commerce Mobile Apps.

Opencart REST API 
OCRESTAPI Module allows the customer purchasing product from the website it just like E-commerce APIs its also available mobile version APIs.

Opencart Rest APIs List 
Customer Registration GET APIs.
Customer Registration POST APIs.
Customer Login GET APIs.
Customer Login POST APIs.
Checkout Confirm GET APIs.
Checkout Confirm POST APIs.


If you want to know Opencart REST API Any information, you can contact us at -
Skype: jks0586,
Email: letscmsdev@gmail.com,
Website: www.letscms.com, www.mlmtrees.com
Call/WhatsApp/WeChat: +91–9717478599.

Download : https://www.opencart.com/index.php?route=marketplace/extension/info&extension_id=43174&filter_search=ocrest%20api
View Documentation : https://www.letscms.com/documents/api/opencart-rest-api.html
More Information : https://www.letscms.com/blog/Rest-API-Opencart
VEDIO : https://vimeo.com/682154292  

#opencart_api_for_android #Opencart_rest_admin_api #opencart_rest_api #Rest_API_Integration #oc_rest_api #rest_api_ecommerce #rest_api_mobile #rest_api_opencart #rest_api_github #rest_api_documentation #opencart_rest_admin_api #rest_api_for_opencart_mobile_app #opencart_shopping_cart_rest_api #opencart_json_api

Lets Cms

Lets Cms

1652251629

Unilevel MLM Wordpress Rest API FrontEnd | UMW Rest API Woocommerce

Unilevel MLM Wordpress Rest API FrontEnd | UMW Rest API Woocommerce Price USA, Philippines : Our API’s handle the Unilevel MLM woo-commerce end user all functionalities like customer login/register. You can request any type of information which is listed below, our API will provide you managed results for your all frontend needs, which will be useful for your applications like Mobile App etc.
Business to Customer REST API for Unilevel MLM Woo-Commerce will empower your Woo-commerce site with the most powerful Unilevel MLM Woo-Commerce REST API, you will be able to get and send data to your marketplace from other mobile apps or websites using HTTP Rest API request.
Our plugin is used JWT authentication for the authorization process.

REST API Unilevel MLM Woo-commerce plugin contains following APIs.
User Login Rest API
User Register Rest API
User Join Rest API
Get User info Rest API
Get Affiliate URL Rest API 
Get Downlines list Rest API
Get Bank Details Rest API
Save Bank Details Rest API
Get Genealogy JSON Rest API
Get Total Earning Rest API
Get Current Balance Rest API
Get Payout Details Rest API
Get Payout List Rest API
Get Commissions List Rest API
Withdrawal Request Rest API
Get Withdrawal List Rest API

If you want to know more information and any queries regarding Unilevel MLM Rest API Woocommerce WordPress Plugin, you can contact our experts through 
Skype: jks0586, 
Mail: letscmsdev@gmail.com,
Website: www.letscms.com, www.mlmtrees.com,
Call/WhatsApp/WeChat: +91-9717478599.  

more information : https://www.mlmtrees.com/product/unilevel-mlm-woocommerce-rest-api-addon

Visit Documentation : https://letscms.com/documents/umw_apis/umw-apis-addon-documentation.html

#Unilevel_MLM_WooCommerce_Rest_API's_Addon #umw_mlm_rest_api #rest_api_woocommerce_unilevel #rest_api_in_woocommerce #rest_api_woocommerce #rest_api_woocommerce_documentation #rest_api_woocommerce_php #api_rest_de_woocommerce #woocommerce_rest_api_in_android #woocommerce_rest_api_in_wordpress #Rest_API_Woocommerce_unilevel_mlm #wp_rest_api_woocommerce

Adonis  Kerluke

Adonis Kerluke

1596509565

RESTful API Design Driven Approach

In this tutorial I will show you the fundamentals of designing a RESTful API specification by applying REST principles and best practices, then you’ll be ready to try my online tutorial: How to design a REST API with API Designer?

If you already know what is meant by API in the context of RESTful web services, you can skip to the next section. If not, read on.

Level-Set on API

The abbreviation API stands for Application Programming Interface this in itself, does not help us understand what it is, however in the context of web services, it can refer to one of two things:

  1. The RESTful API specification is written using a modeling language such as Open API specification or RAML (RESTful API Modeling Language) that defines a contract for how software components can interact with a service.
  2. The implementation of a web service or microservice whose contract is designed by REST principles that describe how other services must interact with it.

In this post, I will use the first understanding of this term. Even though both are correct, the most technically relevant for this post is the first: an API is a contract for how software applications talk to each other.

Level-Set on REST

The acronym REST stands for REpresentational State Transfer. It is an architectural style used to represent the transmission of data from one application component to another. In the context of web services, we are talking about the representation of resources (i.e. data) transferred over HTTP by calling a URI that represents the data and via an HTTP method that represents the action to perform against the given data.

What Is RESTful API design?

RESTful API design is the activity of describing the behavior of a web service in terms of its data structures and the actions you allow other application components to perform on its data by the principles of REST. Those principles are covered later in this blog.

Why Design a RESTful API?

Imagine that you are an Architect (the kind the design building) and you set out to build an office block without a blueprint. You turn up on the first day with a truck full of bricks and some cement. What are the chances that you’ll be successful and build a structure that conforms to code and more importantly, doesn’t fall? It’s about zero. Without a blueprint the chance of failure is high.

The same approach applies to web service development. You need a blueprint, or more appropriately, an API specification. This is necessary to evaluate the API design and solicit feedback before even starting to build the implementation.

In addition to providing a specification for the web service’s development, an API contract serves to document its expected behavior, data types, and security requirements.

You should now be satisfied that API design is necessary for a RESTful web service, and should start to wonder how is the best approach to actually designing an API specification.

API Design Tooling

The tooling chosen by an API designer has substantial influence over the designer’s productivity. Highly productive tools such as the Anypoint API Designer from MuleSoft is perfect for designing APIs with OAS (swagger) or RAML.

#integration #api #rest #rest api #restful #api design #raml #rest api design