Home Applications IOP REST Client Framework

IOP REST Client Framework

This application is not supported by InterSystems Corporation. Please be notified that you use it at your own risk.
4.5
0 reviews
0
Awards
66
Views
0
IPM installs
0
0
Details
Releases
Reviews
Issues
Videos  (1)
Framework for creating REST API clients in python with IOP

What's new in this version

Initial Release

iop-rest-client-framework

This framework is a Proof of Concept that aims to simplify the integration of REST API clients inside IRIS Interoperability-enabled productions using Python (IOP) with minimal code required

Features

  • Define your API client in an elegant and declarative syntax, inspired by libraries such as Retrofit or FastAPI
  • Full interoperability with either native IRIS EnsLib.HTTP.OutboundAdapter or python requests as your HTTP backend
  • Automatically generate your dataclass models and API methods by providing an OpenAPI specification
  • Generated code is made to be human-readable with minimal boilerplate code to be easily editable if adjustments needs to be made

Dependencies

Example

api.py

This is all the code you need to define your models and API endpoints

from iop_rest.api import BaseClientREST
from iop import Message
from pydantic import BaseModel
from uplink.arguments import *
from uplink.commands import *
from uplink.decorators import *
from uplink import returns


@dataclass(init=False)
class Pet(BaseModel, Message):
    id: int
    name: str


@returns.json
@headers({
    "Content-Type": "application/json",
    "Accept": "application/json",
    "Charset": "utf-8",
})
class PetstoreClient(BaseClientREST):

    @json
    @post('pet')
    def add_pet(self, body: Body(type=Pet)) -> Pet:
        pass

    @json
    @get('pet/{petId}')
    def get_pet_by_id(self, pet_id: Path("petId", type=int)) -> Pet:
        pass

bo.py

Simple Business Operation that uses a EnsLib.HTTP.OutboundAdapter by default and passes it to our HTTP client

from iop_rest.bo import BaseRESTOperation
from api import PetstoreClient
# from uplink import RequestsClient

class PetstoreOperation(BaseRESTOperation):
    client: PetstoreClient

    def init_client(self, adapter):
        return PetstoreClient(adapter)
        # Alternatively use python requests as the HTTP backend
        # but lose the capabilities of the adapter
        # return PetstoreClient(adapter, client=RequestsClient())

bs.py

from iop import BusinessService
from iop_rest.messages import RESTRequest
from api import Pet

class PetstoreService(BusinessService):
    @staticmethod
    def get_adapter_type():
        return "Ens.InboundAdapter"

    def on_process_input(self, message_input):
        pet = Pet(
            id=1,
            name="Robert",
        )
        response: Pet = self.send_request_sync('PetstoreOperation', RESTRequest.create('add_pet', pet))
        # do something with response...
        self.log_info(response.name)

Demo

The demo can be found inside src/python/demo/ and is a full implementation of the Petstore OpenAPI spec based on the above example

Presentation video

See the demo in action on Youtube
(Please enable subtitles)


  • The bs.py file is a simple BusinessService that is used to call periodically the Petstore BusinessOperation with a sample Pet object

  • The bo.py file is a simple Business Operation that uses a native IRIS EnsLib.HTTP.OutboundAdapter by default and passes it to our HTTP client
    • You can alternatively choose to use python's requests library as the HTTP backend, however you will lose capabilities offered by IRIS's HTTP OutboundAdapter

  • The generated/api.py file contains the API definition generated by the iop_rest module, the generated code uses the uplink library at its core, and provides numerous decorators and type-checking abilities to allow for a very elegant and declarative syntax

  • The generated/models.py file contains the dataclass models generated by the iop_rest module, it uses pydantic's base class to allow for automatic json serialization and deserialization by the uplink library

  • The settings.py file contains the production definition and settings, see the IOP documentation for more information

Prerequisites

Make sure you have git and Docker installed.

Installation

With Docker

Clone/git pull the repo into any local directory

git clone https://github.com/Antoine-dh/iop-rest-client-framework

Open the terminal in this directory and run:

docker compose build

Run the IRIS container with your project:

docker compose up -d

With ZPM

zpm "install iop-rest-client-framework" 

Usage

Code generation

If running Docker, open a bash terminal inside the container

docker compose exec iris bash

otherwise, make sure the iop_rest module is installed or accessible by the python interpreter (or just cd src/python before running the command)

To run the code generation program, use the following command

python -m iop_rest <APIClassName> <path/to/openapi_spec> <path/to/output_folder>

For this demo:

python -m iop_rest PetstoreClient ./misc/petstore.openapi.yaml ./src/python/demo/generated/

Issues and technical limitations

Keep in mind this is a proof of concept, and not a finished product, do not use for production.

  • For now, only JSON APIs and UTF-8 charset is supported
  • Exceptions are not currently handled properly
  • Endpoints that returns JSON lists at the root of the HTTP body are not supported, this is due to a technical limitation with IOP messages that needs to be wrapped into a singular class, see issue
  • Models' schemas inside OpenAPI specs are expected to be defined in #/components/schemas/, and responses to be $refs to thoses schemas
Made with
Install
zpm install iop-rest-client-framework download archive
Version
0.1.025 Sep, 2024
Ideas portal
https://ideas.intersystems.com/ideas/DPI-I-455
Category
Frameworks
Works with
InterSystems IRISEnsemble
First published
22 Sep, 2024