Skip to content

Commit

Permalink
Merge pull request #11 from openearthplatforminitiative/feat/add-code…
Browse files Browse the repository at this point in the history
…-examples

feat: add code examples
  • Loading branch information
A-Stangeland authored Dec 12, 2023
2 parents bb7f64e + 0f805dd commit eca3340
Show file tree
Hide file tree
Showing 14 changed files with 177 additions and 6 deletions.
21 changes: 17 additions & 4 deletions deforestation_api/__main__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import pathlib
from contextlib import asynccontextmanager
import logging

from fastapi import FastAPI

from fastapi.openapi.docs import get_redoc_html
from deforestation_api.openapi import openapi
from deforestation_api.dependencies.deforestationdata import (
fetch_deforestation_data,
deforestation_data_fetcher,
Expand All @@ -21,17 +23,28 @@ async def lifespan(deforestation_app: FastAPI):


app = FastAPI(
title="Deforestation API",
lifespan=lifespan,
version=settings.version,
root_path=settings.api_root_path,
description=settings.api_description,
redoc_url=None,
)
app.include_router(deforestation.router)
app.include_router(healthcheck.router)

logging.basicConfig(level=logging.INFO)

example_code_dir = pathlib.Path(__file__).parent / "example_code"
app.openapi_schema = openapi.custom_openapi(app, example_code_dir)


@app.get("/redoc", include_in_schema=False)
def redoc():
return get_redoc_html(
openapi_url="/openapi.json",
title="Deforestation API",
redoc_favicon_url="https://www.openepi.io/favicon.ico",
)


if __name__ == "__main__":
import uvicorn

Expand Down
1 change: 1 addition & 0 deletions deforestation_api/example_code/curl/liveness.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
curl -i -X GET $endpoint_url
6 changes: 6 additions & 0 deletions deforestation_api/example_code/curl/lossyear.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Get yearly forest cover loss for the river basin at the given point
curl -i -X GET $endpoint_url?lon=30.0619&lat=-1.9441

# Get yearly forest cover loss for all river basins within the given bounding box
curl -i -X GET $endpoint_url?min_lon=28.850951&min_lat=30.909622&max_lon=-2.840114&max_lat=-1.041395

1 change: 1 addition & 0 deletions deforestation_api/example_code/curl/ready.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
curl -i -X GET $endpoint_url
7 changes: 7 additions & 0 deletions deforestation_api/example_code/javascript/liveness.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const response = await fetch(
"$endpoint_url"
);
const json = await response.json();
const message = json.message;

console.log(`Message: ${message}`);
26 changes: 26 additions & 0 deletions deforestation_api/example_code/javascript/lossyear.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Get yearly forest cover loss for the river basin at the given point
const response_point = await fetch(
"$endpoint_url?" + new URLSearchParams({
lat: -1.9441,
lon: 30.0619
})
);
const data_point = await response_point.json();

// Print the total forest cover loss within the returned river basin
console.log(data_point.features[0].properties.daterange_tot_treeloss);


// Get yearly forest cover loss for all river basins within the given bounding box
const response_bbox = await fetch(
"$endpoint_url?" + new URLSearchParams({
min_lon: 28.850951,
min_lat: -2.840114,
max_lon: 30.909622,
max_lat: -1.041395
})
);
const data_bbox = await response_bbox.json();

// Print the total forest cover loss within the first returned river basin
console.log(data_bbox.features[0].properties.daterange_tot_treeloss);
7 changes: 7 additions & 0 deletions deforestation_api/example_code/javascript/ready.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const response = await fetch(
"$endpoint_url"
);
const json = await response.json();
const status = json.status;

console.log(`Status: ${status}`);
5 changes: 5 additions & 0 deletions deforestation_api/example_code/python/liveness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from httpx import Client

with Client() as client:
response = client.get(url="$endpoint_url")
print(response.json()["message"])
29 changes: 29 additions & 0 deletions deforestation_api/example_code/python/lossyear.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from httpx import Client

with Client() as client:
# Get yearly forest cover loss for the river basin at the given point
response_point = client.get(
url="$endpoint_url",
params={"lon": 30.0619, "lat": -1.9441},
)

data_point = response_point.json()

# Print the total forest cover loss within the returned river basin
print(data_point["features"][0]["properties"]["daterange_tot_treeloss"])

# Get yearly forest cover loss for all river basins within the given bounding box
response_bbox = client.get(
url="$endpoint_url",
params={
"min_lon": 28.850951,
"min_lat": -2.840114,
"max_lon": 30.909622,
"max_lat": -1.041395,
},
)

data_bbox = response_bbox.json()

# Print the total forest cover loss within the first returned river basin
print(data_bbox["features"][0]["properties"]["daterange_tot_treeloss"])
5 changes: 5 additions & 0 deletions deforestation_api/example_code/python/ready.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from httpx import Client

with Client() as client:
response = client.get(url="$endpoint_url")
print(response.json()["status"])
Empty file.
62 changes: 62 additions & 0 deletions deforestation_api/openapi/openapi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import logging
import os
from pathlib import Path
from string import Template

from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
from fastapi.routing import APIRoute

from deforestation_api.settings import settings

supported_languages = {"cURL": "sh", "JavaScript": "js", "Python": "py"}


def custom_openapi(app: FastAPI, example_code_dir: Path):
if app.openapi_schema:
return app.openapi_schema

openapi_schema = get_openapi(
title="Deforestation API",
version=settings.version,
description=settings.api_description,
routes=app.routes,
)

openapi_schema["info"]["x-logo"] = {
"url": f"https://{settings.api_domain}/assets/icons/open-epi-logo.svg"
}

routes_that_need_doc = [
route for route in app.routes if isinstance(route, APIRoute)
]
for route in routes_that_need_doc:
code_samples = []
for lang in supported_languages:
file_with_code_sample = (
example_code_dir
/ lang.lower()
/ f"{route.name}.{supported_languages[lang]}"
)
if os.path.isfile(file_with_code_sample):
with open(file_with_code_sample) as f:
code_template = Template(f.read())
code_samples.append(
{
"lang": lang,
"source": code_template.safe_substitute(
endpoint_url=f"{settings.api_url}{route.path}",
),
}
)
else:
logging.warning(
"No code sample found for route %s and language %s",
route.path,
lang,
)

if code_samples:
openapi_schema["paths"][route.path]["get"]["x-codeSamples"] = code_samples

return openapi_schema
9 changes: 9 additions & 0 deletions deforestation_api/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,14 @@ class Settings(BaseSettings):
api_root_path: str = "/"
api_description: str = 'This is a RESTful service that provides aggregated deforestation data over the period from 2001 to 2022 based on data provided by <a href="https://glad.umd.edu/">Global Land Analysis and Discovery (GLAD)</a> laboratory at the University of Maryland, in partnership with <a href="https://www.globalforestwatch.org/">Global Forest Watch (GFW)</a>. The data are freely available for use under a <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International License</a>.<br/><i>Citation: Hansen, M. C., P. V. Potapov, R. Moore, M. Hancher, S. A. Turubanova, A. Tyukavina, D. Thau, S. V. Stehman, S. J. Goetz, T. R. Loveland, A. Kommareddy, A. Egorov, L. Chini, C. O. Justice, and J. R. G. Townshend. 2013. High-Resolution Global Maps of 21st-Century Forest Cover Change. Science 342 (15 November): 850-53. Data available on-line from: <a href="https://glad.earthengine.app/view/global-forest-change">https://glad.earthengine.app/view/global-forest-change</a></i>.<br/><br/>The data provided by the `basin` endpoint are aggregated over river basin polygons provided by <a href="https://www.hydrosheds.org/products/hydrobasins">HydroSHEDS</a>. The basin data are feely available for non-commercial and commercial use under a licence agreement included in the <a href="https://data.hydrosheds.org/file/technical-documentation/HydroSHEDS_TechDoc_v1_4.pdf">HydroSHEDS Technical Documentation</a>.'

api_domain: str = "localhost"

@property
def api_url(self):
if self.api_domain == "localhost":
return f"http://{self.api_domain}:{self.uvicorn_port}"
else:
return f"https://{self.api_domain}{self.api_root_path}"


settings = Settings()
4 changes: 2 additions & 2 deletions deployment/kubernetes/deforestation-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ spec:
app: deforestation-api
spec:
containers:
- image: ghcr.io/openearthplatforminitiative/deforestation-api:0.1.3
- image: ghcr.io/openearthplatforminitiative/deforestation-api:0.2.0
name: deforestation-api
ports:
- containerPort: 8080
env:
- name: API_ROOT_PATH
value: "/deforestation"
- name: VERSION
value: 0.1.3
value: 0.2.0
---
apiVersion: v1
kind: Service
Expand Down

0 comments on commit eca3340

Please sign in to comment.