apiserver

The apiserver is micro-service framework for python.

It is designed for:

Features

Publishable interface types:

Supported external resources:

Requirements

Apiserver works on following environment:

Limitation

Endpoint Naming Conventions

Service Name:

URL of JSON-RPC service:

  1. http://<service-name>.internal.yuuki0xff.jp/<scope>/json-rpc/v2.0 (Recommended)
  2. http://<service-name>.internal.yuuki0xff.jp/json-rpc/v2.0
  3. https://<service-name>.yuuki0xff.jp/<scope>/json-rpc/v2.0 (Experimental)

URL of gRPC service:

  1. <service-name>_grpc.internal.yuuki0xff.jp:5250 (Experimental)
  2. <service-name>_grpc.yuuki0xff.jp:5250 (Experimental)

TODO: システムがHTTP/2に対応したら、ポート番号を443に変更。

SQLite client configuration

MySQL client configuration

API

RPC

# RPC Server
import api
app = api.Rpc('example-app')
groups = {'foo', 'bar', 'baz'}

@app
def get_groups():
    return list(groups)

@app
def create_group(group: str):
    return groups.add(group)
# RPC Client
import api
with api.RetryPolicy.disable:
    groups = api.rpc.example_app.get_groups()
    print(groups)

REST

RDB

import api
# Use context-local session.
users = api.rdbs.query('SELECT user_id FROM users')
api.rdbs.execute('UPDATE users SET disabled=1')
api.rdbs.commit()

# Use new session with context-manager.
with api.rdb as s:
    users = s.query('SELECT user_id FROM users')
    s.execute('UPDATE users SET disabled=1')
    s.commit()

Context (Internal API)

import api
from api._context import Context

print(api._local.frame.name)  # global
with Context(name='inside'):
    print(api._local.frame.name)  # inside
print(api._local.frame.name)  # global

Access Control

# Server
import api
app = api.Rpc('example')
ac = api.AC(default='deny')

@app
@ac.allow(role='admin')
def register_user(name): pass
# Client
import api
with api.BasicAuth('god', 'password', domain='*.yuuki0xff.jp'):
    api.rpc.example.register_user('bob')

Retry Policy

import api
def job(): pass

api.retry_policies.run('foo', job)  # Use default policy. 

with api.RetryPolicy(times=20, wait=3):  # Policy A
    with api.RetryPolicy(resource_type='foo', times=5, wait=1):  # Policy B
        api.retry_policies.run('foo', job)  # Use the Policy B.

    with api.RetryPolicy.disable:
        api.retry_policies.run(job)  # Run once. Never try again.

    api.retry_policies.run('foo', job)  # Use the Policy A.