Skip to main content

A rest db api designed to be integrated with apache superset

Project description

REST-DB-API

This is a plugin to be used with apache-superset, for importing data via REST APIs.

It builds on top of shillelagh's generic json adapter.

To get started, just do:

pip install rest-db-api

Motivation

  1. Generic json adapter did not support request bodies and headers.
  2. Independence to specify http/https
  3. rest dialect enables this adapter to be used with apache superset.
  4. The dialect enables us to set a base URL, and query multiple endpoints with the same 'connection'.

Examples

GET requests

Querying weather api

Lets assume I am querying for 3 days weather forecast for Bangalore. The response gives the results by hour.

https://api.weatherapi.com/v1/forecast.json?key={{your_key}}&q=Bangalore&days=3&aqi=no&alerts=no

You can get a free key by creating an account there.

You can refer this file to check the response structure. We can query this with rest-db-api:

from sqlalchemy import create_engine  
from rest_db_api.utils import get_virtual_table  
  
engine = create_engine("rest://api.weatherapi.com?ishttps=1")  
  
endpoint = '/v1/forecast.json'  
params = {  
    'key': 'your_key',  
    'q': 'Bangalore',  
    'days': 5  
}  
jsonpath = "$.forecast.forecastday[*]"  
virtual_table = get_virtual_table(endpoint=endpoint,  
                                  params=params,  
                                  jsonpath=jsonpath)  
connection = engine.connect()  
for i in connection.execute(f'SELECT * FROM "{virtual_table}"'):  
    print(i)

The response should return an array of objects/primitives. If not, we need to specify where in the response the array is (using jsonpath). In this case that is at $.forecast.forecastday[*]

As Shillelagh's Adapter class uses in memory storage - sqllite , we can query the data using sqllite syntax.

query = f"""  
SELECT  
  date,
  json_extract(day, "$.maxtemp_c") as max_temp_celsius,  
  json_extract(hour, "$[6].temp_c") as six_am_celsius,  
  json_extract(hour, "$[6].will_it_rain") as will_it_rain
FROM  
  "{virtual_table}"  
"""  
for i in connection.execute(query):  
    print(i)

POST request with headers and request body

Consider this sample request

curl --location -g --request POST 'https://some.api.com/some/api/path?a=60&c=someQuery&b=-50#$[*]' \
--header 'Content-Type: application/json' \
--header 'IAM_ID: satvik' \
--header 'ENVIRONMENT: staging:1.5.3' \
--header 'NAME: MY-REST-SERVICE' \
--data-raw '{
    "name": "satvik",
    "interests": [
        {
            "name": "badminton",
            "category": "sports",
            "stats": {
                "racket": "intermediate",
                "shuttle": "yonex mavis 500"
            }
        },
        {
            "name": "programming",
            "category": "computers",
            "stats": {
                "laptop": "yw",
                "mouse": "5D ergonomic",
                "keyboard": "broken"
            }
        }
    ]
}'

To query this with db-api, follow the snippet:

from sqlalchemy import create_engine  
from rest_db_api.utils import get_virtual_table
  
engine = create_engine("rest://some.api.com?ishttps=1")

endpoint = '/some/api/path'

params = {
	"a": 60,
	"b": -50,
	"c": "someQuery"
}

headers = {  
    'Content-Type': 'application/json',  
    'IAM_ID': 'satvik',  
    'ENVIRONMENT': 'staging:1.5.3',  
    'NAME': 'MY-REST-SERVICE',  
}  
  
body = {  
  "name": "satvik",  
  "interests": [  
    {  
      "name": "badminton",  
      "category": "sports",  
      "stats": { "racket": "intermediate", "shuttle": "yonex mavis 500" }  
    },  
    {  
      "name": "programming",  
      "category": "computers",  
      "stats": {  
        "laptop": "mac book pro",  
        "mouse": "5D ergonomic",  
        "keyboard": "broken"  
      }  
    }  
  ]  
}  

jsonpath = "#$[*]" # set this according to your response  

virtual_table = get_virtual_table(endpoint=endpoint,  
								  params=params,
                                  headers=headers,  
                                  body=body,  
                                  jsonpath=jsonpath)  
  
for i in connection.execute(f'SELECT * FROM "{virtual_table}"'):  
    print(i)

Usage with apache-superset

  1. Go to Connect database and add database

    ss1.png

    ss2.png

  2. Select Shillelagh ss3.png

  3. add the connection string with rest:// prefix eg: rest://api.weatherapi.com?ishttps=1 ss4.png

  4. Gice your connection a name: eg rest-weather-api

  5. Click test connection and then add

  6. Go to SQL lab and select rest-weather-api from database.

    ss5.png

  7. You can leave schema empty and query directly!!

    ss6.png

Query is:

SELECT date, 
      json_extract(day, "$.maxtemp_c") as max_temp_celsius,
      json_extract(hour, "$[6].temp_c") as six_am_celsius,
      json_extract(hour, "$[6].will_it_rain") as will_it_rain
FROM "/v1/forecast.json?key={your_key}&q=Bangalore&days=5#$.forecast.forecastday[*]";

Tables and schema is empty, because there's no concept for tables in REST APIs. It returns a default message. That message is configured in rest_api_dialect.py

Getting the virtual table

In superset's SQL lab, we're directly using

/v1/forecast.json?key={your_key}&q=Bangalore&days=5#$.forecast.forecastday[*]

To get the similar virtual table address for your endpoint (it may have headers or even body), use the utility rest_db_api.utils.get_virtual_table and pass in your configs.

  • POST requests (request body)
  • headers
  • adding write support to adapter (for PUT/DELETE requests)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rest-db-api-0.0.3.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rest_db_api-0.0.3-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file rest-db-api-0.0.3.tar.gz.

File metadata

  • Download URL: rest-db-api-0.0.3.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.8.17

File hashes

Hashes for rest-db-api-0.0.3.tar.gz
Algorithm Hash digest
SHA256 e29c435491ad186362c81fe6021f57fbc1399d56ab04ae6fd4b45ea734523242
MD5 16f3d78e6d0ce28d4dd3cdb6ae791d74
BLAKE2b-256 98458ebb54c7a0491766702bc1e06a43b827ddc87cbea0dd737dddf313481d9e

See more details on using hashes here.

File details

Details for the file rest_db_api-0.0.3-py3-none-any.whl.

File metadata

  • Download URL: rest_db_api-0.0.3-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.2 CPython/3.8.17

File hashes

Hashes for rest_db_api-0.0.3-py3-none-any.whl
Algorithm Hash digest
SHA256 73e84807b5a9d3fc2bbd386af3b83939c75efab36004df75105939f2f1bc9d6d
MD5 5795d1e6e8b149dc47c7319f77a8d4ef
BLAKE2b-256 707dff3da16cefbf5c09732ca84f65596493a31bff3566fdbeb27a8c52d75537

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page