Skip to content

Integrate OPTIMADE with an existing web application

The optimade package can be used to create a standalone web application that serves the OPTIMADE API based on a pre-configured MongoDB backend. In this document, we are going to use optimade differently and use it to add an OPTIMADE API implementation alongside an existing API that employs an Elasticsearch storage layer.

Let's assume we already have a FastAPI application that runs an unrelated web service, and that we use an Elasticsearch backend that contains all structure data, but not necessarily in a form that OPTIMADE expects.

Providing the optimade configuration

optimade can read its configuration from a JSON file. It uses the OPTIMADE_CONFIG_FILE environment variable (or a default path) to find the config file. If you run optimade code inside another application, you might want to provide this config file as part of the source code and not via environment variables. Let's say you have a file optimade_config.json as part of the Python module that you use to create your OPTIMADE API.

Tip

You can find more detailed information about configuring the optimade server in the Configuration section.

Before importing any optimade modules, you can set the OPTIMADE_CONFIG_FILE environment variable to refer to your config file:

import os
from pathlib import Path

os.environ['OPTIMADE_CONFIG_FILE'] = str(Path(__file__).parent / "optimade_config.json")

Customize the EntryCollection implementation

Let's assume that your Elasticsearch backend stores structure data in a different enough manner that you need to provide your own custom implementation. The following code customizes the EntryCollection class for structures, whilst keeping the default MongoDB-based implementation (using MongoCollection) for all other entry types.

from optimade.server.routers import structures

structures.structures_coll = MyElasticsearchStructureCollection()

You can imagine that MyElasticsearchStructureCollection either sub-classes the default optimade Elasticsearch implementation (ElasticsearchCollection) or sub-classes EntryCollection, depending on how deeply you need to customize the default optimade behavior.

Mounting the OPTIMADE Python tools FastAPI app into an existing FastAPI app

Let's assume you have an existing FastAPI app my_app. It already implements a few routers under certain path prefixes, and now you want to add an OPTIMADE implementation under the path prefix /optimade.

First, you have to set the root_path in the optimade configuration, so that the app expects all requests to be prefixed with /optimade.

Second, you simply mount the optimade app into your existing app my_app:

from optimade.server.config import CONFIG

CONFIG.root_path = "/optimade"

from optimade.server import main as optimade

optimade.add_major_version_base_url(optimade.app)
my_app.mount("/optimade", optimade.app)

Tip

In the example above, we imported CONFIG before main so that our config was loaded before app creation. To avoid the need for this, the root_path can be set in your JSON config file, passed as an environment variable, or declared in a custom Python module (see Configuration).

See also the FastAPI documentation on sub-applications.

Now, if you run my_app, it will still serve all its routers as before and in addition it will also serve all OPTIMADE routes under /optimade/ and the versioned URLs /optimade/v1/.