From bf5999c78dabcc4a104f7ec0c61811911a235fbb Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 02:44:59 -0400 Subject: [PATCH 01/17] turn allowed origins for CORS into env var to be parsed as list --- app/api/utility.py | 11 +++++++++++ app/main.py | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/api/utility.py b/app/api/utility.py index 358b945..fb60f3e 100644 --- a/app/api/utility.py +++ b/app/api/utility.py @@ -6,6 +6,11 @@ # Request constants EnvVar = namedtuple("EnvVar", ["name", "val"]) + +ALLOWED_ORIGINS = EnvVar( + "NB_API_ALLOWED_ORIGINS", os.environ.get("NB_API_ALLOWED_ORIGINS", "") +) + GRAPH_USERNAME = EnvVar( "NB_GRAPH_USERNAME", os.environ.get("NB_GRAPH_USERNAME") ) @@ -27,6 +32,7 @@ ) QUERY_URL = f"http://{GRAPH_ADDRESS.val}:{GRAPH_PORT.val}/{GRAPH_DB.val}" +print(QUERY_URL) QUERY_HEADER = { "Content-Type": "application/sparql-query", "Accept": "application/sparql-results+json", @@ -58,6 +64,11 @@ IS_CONTROL_TERM = "purl:NCIT_C94342" # TODO: Remove once https://github.com/neurobagel/bagel-cli/issues/139 is resolved. +def parse_origins_as_list(allowed_origins: str) -> list: + """Returns user-defined allowed origins as a list.""" + return list(allowed_origins.split(" ")) + + def create_query( return_agg: bool, age: Optional[tuple] = (None, None), diff --git a/app/main.py b/app/main.py index 1a8fc5a..1ad6bec 100644 --- a/app/main.py +++ b/app/main.py @@ -14,7 +14,7 @@ app.add_middleware( CORSMiddleware, - allow_origins=["*"], + allow_origins=util.parse_origins_as_list(util.ALLOWED_ORIGINS.val), allow_credentials=True, allow_methods=["*"], allow_headers=["*"], From 22f4e3bbba3312852acfe6dff2947dbfb184d591 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 02:52:22 -0400 Subject: [PATCH 02/17] add allowed origins to template .env and docker compose config --- docker-compose.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/docker-compose.yml b/docker-compose.yml index 48f4f19..21aee43 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,6 +12,7 @@ services: NB_GRAPH_DB: ${NB_GRAPH_DB:-test_data/query} NB_RETURN_AGG: ${NB_RETURN_AGG:-true} NB_API_PORT: ${NB_API_PORT:-8000} + NB_API_ALLOWED_ORIGINS: ${NB_API_ALLOWED_ORIGINS} graph: image: "${NB_GRAPH_IMG:-stardog/stardog:8.2.2-java11-preview}" volumes: From f383c14e99fa53051c0fb9ef6b06aac41a721ce6 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 11:41:18 -0400 Subject: [PATCH 03/17] update template allowed origins --- .template-env | 1 + 1 file changed, 1 insertion(+) diff --git a/.template-env b/.template-env index 98541cd..8a57c56 100644 --- a/.template-env +++ b/.template-env @@ -4,6 +4,7 @@ NB_GRAPH_PASSWORD=DBPASSWORD # REPLACE DBPASSWORD WITH YOUR GRAPH DATABASE PASS NB_GRAPH_DB=test_data/query NB_RETURN_AGG=true NB_API_TAG=latest +NB_API_ALLOWED_ORIGINS="https://localhost:3000 http://localhost:3000" NB_GRAPH_IMG=stardog/stardog:8.2.2-java11-preview ## ADDITIONAL CONFIGURABLE PARAMETERS: Uncomment and modify values of the below variables as needed to use non-default values. # NB_API_PORT_HOST=8000 From 25f4f5e3e0f198d0186b797d91b18d7e81bcd7e8 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 11:43:58 -0400 Subject: [PATCH 04/17] add check for non-empty allowed origins env var --- app/main.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/app/main.py b/app/main.py index 1ad6bec..39fbde0 100644 --- a/app/main.py +++ b/app/main.py @@ -1,6 +1,7 @@ """Main app.""" import os +import warnings import uvicorn from fastapi import FastAPI @@ -25,6 +26,7 @@ async def auth_check(): """Checks whether username and password environment variables are set.""" if ( + # TODO: Check if this error is still raised when variables are empty strings os.environ.get(util.GRAPH_USERNAME.name) is None or os.environ.get(util.GRAPH_PASSWORD.name) is None ): @@ -33,6 +35,17 @@ async def auth_check(): ) +@app.on_event("startup") +async def allowed_origins_check(): + """Raises warning if allowed origins environment variable has not been set or is an empty string.""" + if os.environ.get(util.ALLOWED_ORIGINS.name, "") == "": + warnings.warn( + f"The API was launched without providing any values for the {util.ALLOWED_ORIGINS.name} environment variable. " + f"This means that the API will not be accessible from any origin. To fix this, explicitly set the value of {util.ALLOWED_ORIGINS.name} to at least one origin (e.g. http://localhost:3000). " + "Multiple allowed origins should be separated with spaces in a single string enclosed in quotes. " + ) + + app.include_router(query.router) # Automatically start uvicorn server on execution of main.py From 1e334f0c90a671e01e13585ef8082beb172d46f4 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 11:46:25 -0400 Subject: [PATCH 05/17] add tests for parsing user-defined allowed origins --- tests/test_query.py | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/tests/test_query.py b/tests/test_query.py index da444e4..d1c23b7 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -1,5 +1,8 @@ """Test API to query subjects from the Stardog graph who match user-specified criteria.""" +import os +import warnings + import httpx import pytest from fastapi import HTTPException @@ -114,6 +117,66 @@ def mock_httpx_post(**kwargs): assert response.status_code == 401 +def test_app_with_unset_allowed_origins(test_app, monkeypatch): + """Tests that when the environment variable for allowed origins has not been set, a warning is raised and the app uses a default value.""" + monkeypatch.delenv(util.ALLOWED_ORIGINS.name, raising=False) + + with pytest.warns( + UserWarning, + match=f"API was launched without providing any values for the {util.ALLOWED_ORIGINS.name} environment variable", + ): + with test_app: + pass + + assert util.parse_origins_as_list( + os.environ.get(util.ALLOWED_ORIGINS.name, "") + ) == [""] + + +@pytest.mark.parametrize( + "allowed_origins, parsed_origins, expectation", + [ + ( + "", + [""], + pytest.warns( + UserWarning, + match=f"API was launched without providing any values for the {util.ALLOWED_ORIGINS.name} environment variable", + ), + ), + ( + "http://localhost:3000", + ["http://localhost:3000"], + warnings.catch_warnings(), + ), + ( + "http://localhost:3000 https://localhost:3000", + ["http://localhost:3000", "https://localhost:3000"], + warnings.catch_warnings(), + ), + ], +) +def test_app_with_set_allowed_origins( + test_app, monkeypatch, allowed_origins, parsed_origins, expectation +): + """ + Test that when the environment variable for allowed origins has been explicitly set, the app correctly parses it into a list + and raises a warning if the value is an empty string. + """ + monkeypatch.setenv(util.ALLOWED_ORIGINS.name, allowed_origins) + + with expectation: + with test_app: + pass + + assert ( + util.parse_origins_as_list( + os.environ.get(util.ALLOWED_ORIGINS.name, "") + ) + == parsed_origins + ) + + def test_get_all(test_app, mock_successful_get, monkeypatch): """Given no input for the sex parameter, returns a 200 status code and a non-empty list of results (should correspond to all subjects in graph).""" From 8bcf15a19b23a6dca6e6ea78829ca65061bb7978 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 16:26:13 -0400 Subject: [PATCH 06/17] add info about configuring allowed origins to README --- README.md | 54 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index d95118a..46ec520 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ The Neurobagel API is a REST API, developed in [Python](https://www.python.org/) - [Quickstart](#quickstart) - [Local installation](#local-installation) - [Environment variables](#set-the-environment-variables) + - [Using a graphical query tool](#using-a-graphical-query-tool-to-send-api-requests) - [Docker](#docker) - [Python](#python) - [Testing](#testing) @@ -49,26 +50,27 @@ git clone https://github.com/neurobagel/api.git ### Set the environment variables Create a file called `.env` in the root of the repository will house the environment variables used by the app. -To run API requests against a graph, at least two environment variables must be set, `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD`. +To run API requests against a graph, at least two environment variables must be set, `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD`. This repository contains a [template `.env` file](/.template-env) that you can copy and edit. Below are explanations of all the possible Neurobagel environment variables that you can set in `.env`, depending on your mode of installation of the API and graph server software. -| Environment variable | Required in .env? | Description | Default value if not set | Relevant installation mode(s) | -| -------------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ----------------------------- | -| `NB_GRAPH_USERNAME` | Yes | Username to access Stardog graph database that API will communicate with | - | Docker, Python | -| `NB_GRAPH_PASSWORD` | Yes | Password to access Stardog graph database that API will communicate with | - | Docker, Python | -| `NB_GRAPH_ADDRESS` | No | IP address for the graph database (or container name, if graph is hosted locally) | `206.12.99.17` (`graph`) ** | Docker, Python | -| `NB_GRAPH_DB` | No | Name of graph database endpoint to query (e.g., for a Stardog database, this will take the format of `{database_name}/query`) | `test_data/query` | Docker, Python | -| `NB_RETURN_AGG` | No | Whether to return only dataset-level query results (including data locations) and exclude subject-level attributes. One of [true, false] | `true` | Docker, Python | -| `NB_API_TAG` | No | Tag for API Docker image | `latest` | Docker | -| `NB_API_PORT_HOST` | No | Port number on the _host machine_ to map the API container port to | `8000` | Docker | -| `NB_API_PORT` | No | Port number on which to run the API | `8000` | Docker, Python | -| `NB_GRAPH_IMG` | No | Graph server Docker image | `stardog/stardog:8.2.2-java11-preview` | Docker | -| `NB_GRAPH_ROOT_HOST` | No | Path to directory containing a Stardog license file on the _host machine_ | `~/stardog-home` | Docker | -| `NB_GRAPH_ROOT_CONT` | No | Path to directory for graph databases in the _graph server container_ | `/var/opt/stardog` * | Docker | -| `NB_GRAPH_PORT_HOST` | No | Port number on the _host machine_ to map the graph server container port to | `5820` | Docker | -| `NB_GRAPH_PORT` | No | Port number used by the _graph server container_ | `5820` * | Docker, Python | +| Environment variable | Required in .env? | Description | Default value if not set | Relevant installation mode(s) | +| ------------------------ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | ----------------------------- | +| `NB_GRAPH_USERNAME` | Yes | Username to access Stardog graph database that API will communicate with | - | Docker, Python | +| `NB_GRAPH_PASSWORD` | Yes | Password to access Stardog graph database that API will communicate with | - | Docker, Python | +| `NB_GRAPH_ADDRESS` | No | IP address for the graph database (or container name, if graph is hosted locally) | `206.12.99.17` (`graph`) ** | Docker, Python | +| `NB_GRAPH_DB` | No | Name of graph database endpoint to query (e.g., for a Stardog database, this will take the format of `{database_name}/query`) | `test_data/query` | Docker, Python | +| `NB_RETURN_AGG` | No | Whether to return only dataset-level query results (including data locations) and exclude subject-level attributes. One of [true, false] | `true` | Docker, Python | +| `NB_API_TAG` | No | Tag for API Docker image | `latest` | Docker | +| `NB_API_PORT_HOST` | No | Port number on the _host machine_ to map the API container port to | `8000` | Docker | +| `NB_API_PORT` | No | Port number on which to run the API | `8000` | Docker, Python | +| `NB_API_ALLOWED_ORIGINS` | Yes, if using a query tool | Origins allowed to make [cross-origin resource sharing](https://fastapi.tiangolo.com/tutorial/cors/) requests. _At least one origin must be specified to make the API accessible from a frontend query tool._ Multiple origins should be separated with spaces in a single string enclosed in quotes. | `""` | Docker, Python | +| `NB_GRAPH_IMG` | No | Graph server Docker image | `stardog/stardog:8.2.2-java11-preview` | Docker | +| `NB_GRAPH_ROOT_HOST` | No | Path to directory containing a Stardog license file on the _host machine_ | `~/stardog-home` | Docker | +| `NB_GRAPH_ROOT_CONT` | No | Path to directory for graph databases in the _graph server container_ | `/var/opt/stardog` * | Docker | +| `NB_GRAPH_PORT_HOST` | No | Port number on the _host machine_ to map the graph server container port to | `5820` | Docker | +| `NB_GRAPH_PORT` | No | Port number used by the _graph server container_ | `5820` * | Docker, Python | _* These defaults are configured for a Stardog backend - you should not have to change them if you are running a Stardog backend._ @@ -84,6 +86,26 @@ also ensure that any variables defined in your `.env` are not already set in you The below instructions for Docker and Python assume that you have at least set `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD` in your `.env`. +### Using a graphical query tool to send API requests +To make the API accessible by a frontend tool such as our [browser query tool](https://github.com/neurobagel/query-tool), you must explicitly specify the origin(s) for the frontend using `NB_API_ALLOWED_ORIGINS` in `.env` (see also above table). +This variable defaults to an empty string (`""`) when unset, meaning that your deployed API will only accessible via direct `curl` requests to the URL where the API is hosted (see [this section](#send-a-test-query-to-the-api) for an example `curl` request). + +Note: The `.template-env` file in this repo assumes you want to allow API requests from a query tool hosted at a specific port on `localhost`. + +Other examples: +```bash +# ---- .env file ---- + +# do not allow requests from any frontend origins +NB_API_ALLOWED_ORIGINS="" # or, exclude variable from .env + +# allow requests from only one origin +NB_API_ALLOWED_ORIGINS="https://query.neurobagel.org" + +# allow requests from 3 different origins +NB_API_ALLOWED_ORIGINS="https://query.neurobagel.org https://localhost:3000 http://localhost:3000" +``` + ### Docker First, [install docker](https://docs.docker.com/get-docker/). From 00a0fe2f59374d4d24f027e5e4d0626a2808bbe4 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 16:33:44 -0400 Subject: [PATCH 07/17] add example for allow all origins --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 46ec520..3dc016b 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,9 @@ NB_API_ALLOWED_ORIGINS="https://query.neurobagel.org" # allow requests from 3 different origins NB_API_ALLOWED_ORIGINS="https://query.neurobagel.org https://localhost:3000 http://localhost:3000" + +# allow requests from any origin - use with caution +NB_API_ALLOWED_ORIGINS="*" ``` ### Docker From 214ed1b034e44ec5b432ca618dab73d43898173c Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Tue, 29 Aug 2023 17:07:24 -0400 Subject: [PATCH 08/17] set random credentials to test new startup event --- tests/test_query.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_query.py b/tests/test_query.py index d1c23b7..32d5343 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -120,6 +120,9 @@ def mock_httpx_post(**kwargs): def test_app_with_unset_allowed_origins(test_app, monkeypatch): """Tests that when the environment variable for allowed origins has not been set, a warning is raised and the app uses a default value.""" monkeypatch.delenv(util.ALLOWED_ORIGINS.name, raising=False) + # set random username and password to avoid RuntimeError from other startup check + monkeypatch.setenv(util.GRAPH_USERNAME.name, "DBUSER") + monkeypatch.setenv(util.GRAPH_PASSWORD.name, "DBPASSWORD") with pytest.warns( UserWarning, @@ -164,6 +167,9 @@ def test_app_with_set_allowed_origins( and raises a warning if the value is an empty string. """ monkeypatch.setenv(util.ALLOWED_ORIGINS.name, allowed_origins) + # set random username and password to avoid RuntimeError from other startup check + monkeypatch.setenv(util.GRAPH_USERNAME.name, "DBUSER") + monkeypatch.setenv(util.GRAPH_PASSWORD.name, "DBPASSWORD") with expectation: with test_app: From c47f3a7ab7822a0ad642d26bce04c2d62fb90920 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 15:04:51 -0400 Subject: [PATCH 09/17] remove leftover debug --- app/api/utility.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/api/utility.py b/app/api/utility.py index fb60f3e..129c9e1 100644 --- a/app/api/utility.py +++ b/app/api/utility.py @@ -32,7 +32,6 @@ ) QUERY_URL = f"http://{GRAPH_ADDRESS.val}:{GRAPH_PORT.val}/{GRAPH_DB.val}" -print(QUERY_URL) QUERY_HEADER = { "Content-Type": "application/sparql-query", "Accept": "application/sparql-results+json", @@ -66,6 +65,7 @@ def parse_origins_as_list(allowed_origins: str) -> list: """Returns user-defined allowed origins as a list.""" + print(list(allowed_origins.split(" "))) return list(allowed_origins.split(" ")) From b108bb81cbc584d9fd9f7fa1d9fd21c4de793772 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 15:49:28 -0400 Subject: [PATCH 10/17] add comment for multiple origins example in template .env --- .template-env | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.template-env b/.template-env index 8a57c56..93078cc 100644 --- a/.template-env +++ b/.template-env @@ -4,7 +4,7 @@ NB_GRAPH_PASSWORD=DBPASSWORD # REPLACE DBPASSWORD WITH YOUR GRAPH DATABASE PASS NB_GRAPH_DB=test_data/query NB_RETURN_AGG=true NB_API_TAG=latest -NB_API_ALLOWED_ORIGINS="https://localhost:3000 http://localhost:3000" +NB_API_ALLOWED_ORIGINS="https://localhost:3000 http://localhost:3000" # Example of allowing multiple origins, edit as needed for your own setup NB_GRAPH_IMG=stardog/stardog:8.2.2-java11-preview ## ADDITIONAL CONFIGURABLE PARAMETERS: Uncomment and modify values of the below variables as needed to use non-default values. # NB_API_PORT_HOST=8000 From 0e156689fee36f7897315a3678c5fad3e471b36f Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 16:04:46 -0400 Subject: [PATCH 11/17] add test condition for origins list with empty strings --- tests/test_query.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/test_query.py b/tests/test_query.py index 32d5343..480c688 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -157,6 +157,11 @@ def test_app_with_unset_allowed_origins(test_app, monkeypatch): ["http://localhost:3000", "https://localhost:3000"], warnings.catch_warnings(), ), + ( + " http://localhost:3000 https://localhost:3000 ", + ["http://localhost:3000", "https://localhost:3000"], + warnings.catch_warnings(), + ), ], ) def test_app_with_set_allowed_origins( @@ -175,11 +180,10 @@ def test_app_with_set_allowed_origins( with test_app: pass - assert ( + assert set(parsed_origins).issubset( util.parse_origins_as_list( os.environ.get(util.ALLOWED_ORIGINS.name, "") ) - == parsed_origins ) From edba7ae603226563c01dfa5e64a605c533cdc27c Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 16:08:13 -0400 Subject: [PATCH 12/17] Expand warning for not setting origins Co-authored-by: Sebastian Urchs --- app/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/main.py b/app/main.py index 39fbde0..4517ac9 100644 --- a/app/main.py +++ b/app/main.py @@ -41,7 +41,7 @@ async def allowed_origins_check(): if os.environ.get(util.ALLOWED_ORIGINS.name, "") == "": warnings.warn( f"The API was launched without providing any values for the {util.ALLOWED_ORIGINS.name} environment variable. " - f"This means that the API will not be accessible from any origin. To fix this, explicitly set the value of {util.ALLOWED_ORIGINS.name} to at least one origin (e.g. http://localhost:3000). " + f"This means that the API will only be accessible from the same origin it is hosted from: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy. If you want to access the API from tools hosted at other origins such as the Neurobagel query tool, explicitly set the value of {util.ALLOWED_ORIGINS.name} to the origin(s) of these tools (e.g. http://localhost:3000). " "Multiple allowed origins should be separated with spaces in a single string enclosed in quotes. " ) From 0635841b042ade0b4c7ceca80aa4af8799638dbe Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 16:10:15 -0400 Subject: [PATCH 13/17] adjust line formatting for warning --- app/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/main.py b/app/main.py index 4517ac9..58643a4 100644 --- a/app/main.py +++ b/app/main.py @@ -41,7 +41,8 @@ async def allowed_origins_check(): if os.environ.get(util.ALLOWED_ORIGINS.name, "") == "": warnings.warn( f"The API was launched without providing any values for the {util.ALLOWED_ORIGINS.name} environment variable. " - f"This means that the API will only be accessible from the same origin it is hosted from: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy. If you want to access the API from tools hosted at other origins such as the Neurobagel query tool, explicitly set the value of {util.ALLOWED_ORIGINS.name} to the origin(s) of these tools (e.g. http://localhost:3000). " + "This means that the API will only be accessible from the same origin it is hosted from: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy. " + f"If you want to access the API from tools hosted at other origins such as the Neurobagel query tool, explicitly set the value of {util.ALLOWED_ORIGINS.name} to the origin(s) of these tools (e.g. http://localhost:3000). " "Multiple allowed origins should be separated with spaces in a single string enclosed in quotes. " ) From 4728cd4832995369af3baa8f8b873329bb6a81a8 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 21:36:57 -0400 Subject: [PATCH 14/17] expand info on CORS expectations in README --- README.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3dc016b..45a435c 100644 --- a/README.md +++ b/README.md @@ -65,8 +65,8 @@ Below are explanations of all the possible Neurobagel environment variables that | `NB_API_TAG` | No | Tag for API Docker image | `latest` | Docker | | `NB_API_PORT_HOST` | No | Port number on the _host machine_ to map the API container port to | `8000` | Docker | | `NB_API_PORT` | No | Port number on which to run the API | `8000` | Docker, Python | -| `NB_API_ALLOWED_ORIGINS` | Yes, if using a query tool | Origins allowed to make [cross-origin resource sharing](https://fastapi.tiangolo.com/tutorial/cors/) requests. _At least one origin must be specified to make the API accessible from a frontend query tool._ Multiple origins should be separated with spaces in a single string enclosed in quotes. | `""` | Docker, Python | -| `NB_GRAPH_IMG` | No | Graph server Docker image | `stardog/stardog:8.2.2-java11-preview` | Docker | +| `NB_API_ALLOWED_ORIGINS` | No [†](#using-a-graphical-query-tool-to-send-api-requests) | Origins allowed to make [cross-origin resource sharing](https://fastapi.tiangolo.com/tutorial/cors/) requests. Multiple origins should be separated with spaces in a single string enclosed in quotes. _NOTE: To make the API accessible from a frontend query tool, you will need to explicitly provide the origin in `.env`. See_ [†](#using-a-graphical-query-tool-to-send-api-requests) _for more info_ | `""` | Docker, Python | +| `NB_GRAPH_IMG` | No | Graph server Docker image | `stardog/stardog:8.2.2-java11-preview` | Docker | | `NB_GRAPH_ROOT_HOST` | No | Path to directory containing a Stardog license file on the _host machine_ | `~/stardog-home` | Docker | | `NB_GRAPH_ROOT_CONT` | No | Path to directory for graph databases in the _graph server container_ | `/var/opt/stardog` * | Docker | | `NB_GRAPH_PORT_HOST` | No | Port number on the _host machine_ to map the graph server container port to | `5820` | Docker | @@ -87,17 +87,19 @@ also ensure that any variables defined in your `.env` are not already set in you The below instructions for Docker and Python assume that you have at least set `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD` in your `.env`. ### Using a graphical query tool to send API requests -To make the API accessible by a frontend tool such as our [browser query tool](https://github.com/neurobagel/query-tool), you must explicitly specify the origin(s) for the frontend using `NB_API_ALLOWED_ORIGINS` in `.env` (see also above table). -This variable defaults to an empty string (`""`) when unset, meaning that your deployed API will only accessible via direct `curl` requests to the URL where the API is hosted (see [this section](#send-a-test-query-to-the-api) for an example `curl` request). +The `NB_API_ALLOWED_ORIGINS` variable defaults to an empty string (`""`) when unset, meaning that your deployed API will only accessible via direct `curl` requests to the URL where the API is hosted (see [this section](#send-a-test-query-to-the-api) for an example `curl` request). -Note: The `.template-env` file in this repo assumes you want to allow API requests from a query tool hosted at a specific port on `localhost`. +However, in many cases you may want to make the API accessible by a frontend tool such as our [browser query tool](https://github.com/neurobagel/query-tool). +To do so, you must explicitly specify the origin(s) for the frontend using `NB_API_ALLOWED_ORIGINS` in `.env`. + +For example, the `.template-env` file in this repo assumes you want to allow API requests from a query tool hosted at a specific port on `localhost`. Other examples: ```bash # ---- .env file ---- # do not allow requests from any frontend origins -NB_API_ALLOWED_ORIGINS="" # or, exclude variable from .env +NB_API_ALLOWED_ORIGINS="" # this is the default value that will also be set if the variable is excluded from the .env file # allow requests from only one origin NB_API_ALLOWED_ORIGINS="https://query.neurobagel.org" @@ -109,6 +111,8 @@ NB_API_ALLOWED_ORIGINS="https://query.neurobagel.org https://localhost:3000 http NB_API_ALLOWED_ORIGINS="*" ``` +**A note for more technical users:** If you have configured an NGINX reverse proxy (or proxy requests to the remote origin) to serve both the API and the query tool from the same origin, you can skip the step of enabling CORS for the API. For an example, see https://stackoverflow.com/a/28599481. + ### Docker First, [install docker](https://docs.docker.com/get-docker/). From 60f99808a45282600631e6f2235fb6048120df3c Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 21:41:16 -0400 Subject: [PATCH 15/17] update README --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 45a435c..27a2123 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ also ensure that any variables defined in your `.env` are not already set in you The below instructions for Docker and Python assume that you have at least set `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD` in your `.env`. -### Using a graphical query tool to send API requests +### Using a graphical query tool to send API requests (†) The `NB_API_ALLOWED_ORIGINS` variable defaults to an empty string (`""`) when unset, meaning that your deployed API will only accessible via direct `curl` requests to the URL where the API is hosted (see [this section](#send-a-test-query-to-the-api) for an example `curl` request). However, in many cases you may want to make the API accessible by a frontend tool such as our [browser query tool](https://github.com/neurobagel/query-tool). @@ -111,7 +111,8 @@ NB_API_ALLOWED_ORIGINS="https://query.neurobagel.org https://localhost:3000 http NB_API_ALLOWED_ORIGINS="*" ``` -**A note for more technical users:** If you have configured an NGINX reverse proxy (or proxy requests to the remote origin) to serve both the API and the query tool from the same origin, you can skip the step of enabling CORS for the API. For an example, see https://stackoverflow.com/a/28599481. +**A note for more technical users:** If you have configured an NGINX reverse proxy (or proxy requests to the remote origin) to serve both the API and the query tool from the same origin, you can skip the step of enabling CORS for the API. +For an example, see https://stackoverflow.com/a/28599481. ### Docker First, [install docker](https://docs.docker.com/get-docker/). From f2dc786718161a58da402e2addb92ab466b92169 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Wed, 30 Aug 2023 22:52:55 -0400 Subject: [PATCH 16/17] update table note in README --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 27a2123..22f4b5a 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ Below are explanations of all the possible Neurobagel environment variables that | `NB_API_TAG` | No | Tag for API Docker image | `latest` | Docker | | `NB_API_PORT_HOST` | No | Port number on the _host machine_ to map the API container port to | `8000` | Docker | | `NB_API_PORT` | No | Port number on which to run the API | `8000` | Docker, Python | -| `NB_API_ALLOWED_ORIGINS` | No [†](#using-a-graphical-query-tool-to-send-api-requests) | Origins allowed to make [cross-origin resource sharing](https://fastapi.tiangolo.com/tutorial/cors/) requests. Multiple origins should be separated with spaces in a single string enclosed in quotes. _NOTE: To make the API accessible from a frontend query tool, you will need to explicitly provide the origin in `.env`. See_ [†](#using-a-graphical-query-tool-to-send-api-requests) _for more info_ | `""` | Docker, Python | +| `NB_API_ALLOWED_ORIGINS` | No † | Origins allowed to make [cross-origin resource sharing](https://fastapi.tiangolo.com/tutorial/cors/) requests. Multiple origins must be separated with spaces in a single string enclosed in quotes. _NOTE: To make the API accessible from a frontend query tool, the origin must be explicitly set. See_ † _for more info_ | `""` | Docker, Python | | `NB_GRAPH_IMG` | No | Graph server Docker image | `stardog/stardog:8.2.2-java11-preview` | Docker | | `NB_GRAPH_ROOT_HOST` | No | Path to directory containing a Stardog license file on the _host machine_ | `~/stardog-home` | Docker | | `NB_GRAPH_ROOT_CONT` | No | Path to directory for graph databases in the _graph server container_ | `/var/opt/stardog` * | Docker | @@ -77,6 +77,8 @@ _* These defaults are configured for a Stardog backend - you should not have to _** If using the [docker compose installation route](#option-1-recommended-use-the-docker-composeyaml-file), do not change `NB_API_ADDRESS` from its default value (`graph`) as this corresponds to the preset container name of the graph database server within the docker compose network._ +_† See section [Using a graphical query tool to send API requests](#using-a-graphical-query-tool-to-send-api-requests)_ + --- **IMPORTANT:** - Variables set in the shell environment where the API is launched **_should not be used as a replacement for the `.env` file_** to configure options for the API or graph server software. @@ -86,7 +88,7 @@ also ensure that any variables defined in your `.env` are not already set in you The below instructions for Docker and Python assume that you have at least set `NB_GRAPH_USERNAME` and `NB_GRAPH_PASSWORD` in your `.env`. -### Using a graphical query tool to send API requests (†) +### Using a graphical query tool to send API requests The `NB_API_ALLOWED_ORIGINS` variable defaults to an empty string (`""`) when unset, meaning that your deployed API will only accessible via direct `curl` requests to the URL where the API is hosted (see [this section](#send-a-test-query-to-the-api) for an example `curl` request). However, in many cases you may want to make the API accessible by a frontend tool such as our [browser query tool](https://github.com/neurobagel/query-tool). From 34714a7bb9cccd98c6f52b4b674d33d0f5a93df5 Mon Sep 17 00:00:00 2001 From: Alyssa Dai Date: Thu, 31 Aug 2023 12:09:54 -0400 Subject: [PATCH 17/17] remove leftover debug --- app/api/utility.py | 1 - 1 file changed, 1 deletion(-) diff --git a/app/api/utility.py b/app/api/utility.py index 129c9e1..c0882b7 100644 --- a/app/api/utility.py +++ b/app/api/utility.py @@ -65,7 +65,6 @@ def parse_origins_as_list(allowed_origins: str) -> list: """Returns user-defined allowed origins as a list.""" - print(list(allowed_origins.split(" "))) return list(allowed_origins.split(" "))