Giter Club home page Giter Club logo

servifier's Introduction

Build Status codecov Maintainability PyPI version

Servifier

Overview

It is an easy-to-use tool for making web service with API from your own Python functions.

The list of the features is as follows:

  • fault tolerance,
  • customizable requests validation,
  • concise error messages for end user,
  • authentication.

As of 2023-08-27, FastAPI is a way more advanced alternative to this package.

Minimal Example

Suppose that you have a file named simple_service.py that looks like this:

from servifier import HandleSpec, create_app


def add_numbers(first: int, second: int) -> int:
    """Add two numbers."""
    return first + second


def subtract_numbers(first: int, second: int) -> int:
    """Subtract two numbers."""
    return first - second


handle_spec_for_adding = HandleSpec(add_numbers, '/add')
handle_spec_for_subtraction = HandleSpec(subtract_numbers, '/subtract')

handle_specs = [handle_spec_for_adding, handle_spec_for_subtraction]

app = create_app(handle_specs)
app.run()

Run this script. A demo server starts and after that you can send requests to it:

>>> curl -X POST -H "Content-Type: application/json" -d '{"first": 1, "second": 3}' http://127.0.0.1:5000/add
{"response":4,"status":200}
>>> curl -X POST -H "Content-Type: application/json" -d '{"first": 1, "second": 3}' http://127.0.0.1:5000/subtract
{"response":-2,"status":200}

Installation

A stable version of the package can be collected from PyPI:

pip install servifier

Tips on Usage

Deployment on a Production Server

In the above minimal example, the development server provided by Flask is used. It is not suitable for production usage.

There are plenty of ways to deploy a Flask application on a production server. For example, you can use Waitress or uWSGI.

Let us discuss uWSGI a bit more. You can create uwsgi.ini config:

[uwsgi]
# {Python module}:{Flask app from there}
module = simple_service:app
# If it is true, there is a master process, not only workers.
master = true
# Number of workers.
processes = 4
# Host and port for API, '0.0.0.0' means to use web address.
http = 0.0.0.0:7070
# Directory with code to be imported.
pythonpath = ./venv/lib/python3.6/site-packages/
# If it is not set, logs are printed. If it is set, logs are written to this file.
logto = /tmp/servifier.log

To use it, you need to install uWSGI Python package:

pip install uwsgi

To start a production server, delete app.run() line from simple_service.py (it launches demo server) and run:

uwsgi --ini uwsgi.ini

It may be enough to have just uWSGI. However, you can also add Nginx in front of uWSGI as a load balancer and a reverse proxy.

Input Data Validation

It is possible to configure servifier so that requests with invalid data are rejected with a proper error code before your function is called.

The minimal example with a simple service can be modified in the following manner:

from servifier import HandleSpec, create_app
from servifier.validation import IntegerField


def add_numbers(first: int, second: int) -> int:
    """Add two numbers."""
    return first + second


def subtract_numbers(first: int, second: int) -> int:
    """Subtract two numbers."""
    return first - second
    
    
class IntegerPair:
    """A pair of two integers."""
    
    first = IntegerField(required=True)
    second = IntegerField(required=True)
    
    def __init__(self, first: int, second: int):
        """Initialize an instance with parameters validation."""
        self.first = first
        self.second = second


handle_spec_for_adding = HandleSpec(
    add_numbers, '/add', IntegerPair
)
handle_spec_for_subtraction = HandleSpec(
    subtract_numbers, '/subtract', IntegerPair
)

handle_specs = [handle_spec_for_adding, handle_spec_for_subtraction]

app = create_app(handle_specs)
app.run()

Behavior of the service is demonstrated below:

>>> curl -X POST -H "Content-Type: application/json" -d '{"first": "1", "second": 3}' http://127.0.0.1:5000/add
{"error":"Invalid Request: check your JSON","status":422}

Comparing to the minimal example, this service returns "Invalid Request" status instead of "Internal Error" status which is harder to debug for end user.

If you need more info about how this example works, read about Python descriptors.

Authentication

It is possible to deny requests that does not include login and token where proper value of token is defined by login and arbitrary salt.

Minimal example with authentication enabled looks like this:

from servifier import HandleSpec, create_app


def add_numbers(first: int, second: int) -> int:
    """Add two numbers."""
    return first + second


def subtract_numbers(first: int, second: int) -> int:
    """Subtract two numbers."""
    return first - second


handle_spec_for_adding = HandleSpec(
    add_numbers, '/add', auth_salt='abcd'
)
handle_spec_for_subtraction = HandleSpec(
    subtract_numbers, '/subtract', auth_salt='1234'
)

handle_specs = [handle_spec_for_adding, handle_spec_for_subtraction]

app = create_app(handle_specs)
app.run()

For a particular login, you can generate its token with servifier.auth.generate_token function and tell this value to someone sending requests under this login. JSON attachment from a request must include two additional fields ('login' and 'token') besides fields with arguments for a Python function.

>>> curl -X POST -H "Content-Type: application/json" -d '{"login": "a", "token": "6491cacf01b2e1c6d08a5609d2f570ea57d71ae7f06e0391276d70d935d29aa51888d566751aa36dc5e12e18da693ece36427c167e2a7a67e48aca8928ba3979", "first": 1, "second": 3}' http://127.0.0.1:5000/subtract
{"result":-2,"status":200}

servifier's People

Contributors

dependabot[bot] avatar nikolay-lysenko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.