mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-09-23 07:18:12 +08:00
separate backend base url from frontend (#1819)
* separate backend base url from frontend This is needed for auth, and to support a different location for the backend api server, than the frontend. part of chanzuckerberg/cellxgene#1778 new server config parameters: app__api_base_url, app__web_base_url Also changed api_base_url in the oauth config section to "oauth_api_base_url" to be less confusing with the app's api_base_url Other minor changes: changed how the jwt decode options are handled. Previously they needed to be set in a test case, and there was some extra logic to handle that. Now they are handled through comfig parameters, which makes it more general. Also, add a feature to set the CORS support credentials, which seems to be necessary for the backend/frontend separation, at least when run locally. This part is sort of experimental, and may be removed or changed later.
This commit is contained in:
@@ -7,6 +7,7 @@ import requests
|
||||
|
||||
from server.common.app_config import AppConfig
|
||||
from server.common.errors import ConfigurationError
|
||||
from server.common.utils.utils import find_available_port
|
||||
from server.test import PROJECT_ROOT, test_server, FIXTURES_ROOT
|
||||
|
||||
|
||||
@@ -19,46 +20,46 @@ def mockenv(**envvars):
|
||||
|
||||
class AppConfigTest(unittest.TestCase):
|
||||
def test_update(self):
|
||||
c = AppConfig()
|
||||
c.update_server_config(app__verbose=True, multi_dataset__dataroot="datadir")
|
||||
v = c.server_config.changes_from_default()
|
||||
self.assertCountEqual(v, [("app__verbose", True, False), ("multi_dataset__dataroot", "datadir", None)])
|
||||
config = AppConfig()
|
||||
config.update_server_config(app__verbose=True, multi_dataset__dataroot="datadir")
|
||||
vars = config.server_config.changes_from_default()
|
||||
self.assertCountEqual(vars, [("app__verbose", True, False), ("multi_dataset__dataroot", "datadir", None)])
|
||||
|
||||
c = AppConfig()
|
||||
c.update_default_dataset_config(app__scripts=(), app__inline_scripts=())
|
||||
v = c.server_config.changes_from_default()
|
||||
self.assertCountEqual(v, [])
|
||||
config = AppConfig()
|
||||
config.update_default_dataset_config(app__scripts=(), app__inline_scripts=())
|
||||
vars = config.server_config.changes_from_default()
|
||||
self.assertCountEqual(vars, [])
|
||||
|
||||
c = AppConfig()
|
||||
c.update_default_dataset_config(app__scripts=[], app__inline_scripts=[])
|
||||
v = c.default_dataset_config.changes_from_default()
|
||||
self.assertCountEqual(v, [])
|
||||
config = AppConfig()
|
||||
config.update_default_dataset_config(app__scripts=[], app__inline_scripts=[])
|
||||
vars = config.default_dataset_config.changes_from_default()
|
||||
self.assertCountEqual(vars, [])
|
||||
|
||||
c = AppConfig()
|
||||
c.update_default_dataset_config(app__scripts=("a", "b"), app__inline_scripts=["c", "d"])
|
||||
v = c.default_dataset_config.changes_from_default()
|
||||
self.assertCountEqual(v, [("app__scripts", ["a", "b"], []), ("app__inline_scripts", ["c", "d"], [])])
|
||||
config = AppConfig()
|
||||
config.update_default_dataset_config(app__scripts=("a", "b"), app__inline_scripts=["c", "d"])
|
||||
vars = config.default_dataset_config.changes_from_default()
|
||||
self.assertCountEqual(vars, [("app__scripts", ["a", "b"], []), ("app__inline_scripts", ["c", "d"], [])])
|
||||
|
||||
def test_multi_dataset(self):
|
||||
|
||||
c = AppConfig()
|
||||
config = AppConfig()
|
||||
# test for illegal url_dataroots
|
||||
for illegal in ("../b", "!$*", "\\n", "", "(bad)"):
|
||||
c.update_server_config(
|
||||
config.update_server_config(
|
||||
multi_dataset__dataroot={"tag": {"base_url": illegal, "dataroot": "{PROJECT_ROOT}/example-dataset"}}
|
||||
)
|
||||
with self.assertRaises(ConfigurationError):
|
||||
c.complete_config()
|
||||
config.complete_config()
|
||||
|
||||
# test for legal url_dataroots
|
||||
for legal in ("d", "this.is-okay_", "a/b"):
|
||||
c.update_server_config(
|
||||
config.update_server_config(
|
||||
multi_dataset__dataroot={"tag": {"base_url": legal, "dataroot": "{PROJECT_ROOT}/example-dataset"}}
|
||||
)
|
||||
c.complete_config()
|
||||
config.complete_config()
|
||||
|
||||
# test that multi dataroots work end to end
|
||||
c.update_server_config(
|
||||
config.update_server_config(
|
||||
multi_dataset__dataroot=dict(
|
||||
s1=dict(dataroot=f"{PROJECT_ROOT}/example-dataset", base_url="set1/1/2"),
|
||||
s2=dict(dataroot=f"{FIXTURES_ROOT}", base_url="set2"),
|
||||
@@ -67,46 +68,46 @@ class AppConfigTest(unittest.TestCase):
|
||||
)
|
||||
|
||||
# Change this default to test if the dataroot overrides below work.
|
||||
c.update_default_dataset_config(app__about_legal_tos="tos_default.html")
|
||||
config.update_default_dataset_config(app__about_legal_tos="tos_default.html")
|
||||
|
||||
# specialize the configs for set1
|
||||
c.add_dataroot_config(
|
||||
config.add_dataroot_config(
|
||||
"s1", user_annotations__enable=False, diffexp__enable=True, app__about_legal_tos="tos_set1.html"
|
||||
)
|
||||
|
||||
# specialize the configs for set2
|
||||
c.add_dataroot_config(
|
||||
config.add_dataroot_config(
|
||||
"s2", user_annotations__enable=True, diffexp__enable=False, app__about_legal_tos="tos_set2.html"
|
||||
)
|
||||
|
||||
# no specializations for set3 (they get the default dataset config)
|
||||
c.complete_config()
|
||||
config.complete_config()
|
||||
|
||||
with test_server(app_config=c) as server:
|
||||
with test_server(app_config=config) as server:
|
||||
session = requests.Session()
|
||||
|
||||
r = session.get(f"{server}/set1/1/2/pbmc3k.h5ad/api/v0.2/config")
|
||||
data_config = r.json()
|
||||
response = session.get(f"{server}/set1/1/2/pbmc3k.h5ad/api/v0.2/config")
|
||||
data_config = response.json()
|
||||
assert data_config["config"]["displayNames"]["dataset"] == "pbmc3k"
|
||||
assert data_config["config"]["parameters"]["annotations"] is False
|
||||
assert data_config["config"]["parameters"]["disable-diffexp"] is False
|
||||
assert data_config["config"]["parameters"]["about_legal_tos"] == "tos_set1.html"
|
||||
|
||||
r = session.get(f"{server}/set2/pbmc3k.cxg/api/v0.2/config")
|
||||
data_config = r.json()
|
||||
response = session.get(f"{server}/set2/pbmc3k.cxg/api/v0.2/config")
|
||||
data_config = response.json()
|
||||
assert data_config["config"]["displayNames"]["dataset"] == "pbmc3k"
|
||||
assert data_config["config"]["parameters"]["annotations"] is True
|
||||
assert data_config["config"]["parameters"]["about_legal_tos"] == "tos_set2.html"
|
||||
|
||||
r = session.get(f"{server}/set3/pbmc3k.cxg/api/v0.2/config")
|
||||
data_config = r.json()
|
||||
response = session.get(f"{server}/set3/pbmc3k.cxg/api/v0.2/config")
|
||||
data_config = response.json()
|
||||
assert data_config["config"]["displayNames"]["dataset"] == "pbmc3k"
|
||||
assert data_config["config"]["parameters"]["annotations"] is True
|
||||
assert data_config["config"]["parameters"]["disable-diffexp"] is False
|
||||
assert data_config["config"]["parameters"]["about_legal_tos"] == "tos_default.html"
|
||||
|
||||
r = session.get(f"{server}/health")
|
||||
assert r.json()["status"] == "pass"
|
||||
response = session.get(f"{server}/health")
|
||||
assert response.json()["status"] == "pass"
|
||||
|
||||
@mockenv(CXG_AWS_SECRET_NAME="TESTING", CXG_AWS_SECRET_REGION_NAME="TEST_REGION")
|
||||
@patch('server.common.aws_secret_utils.get_secret_key')
|
||||
@@ -133,3 +134,23 @@ class AppConfigTest(unittest.TestCase):
|
||||
self.assertEqual(config.server_config.app__flask_secret_key, "mock_flask_secret")
|
||||
self.assertEqual(config.server_config.authentication__params_oauth__client_secret, "mock_oauth_secret")
|
||||
self.assertEqual(config.default_dataset_config.user_annotations__hosted_tiledb_array__db_uri, "mock_db_uri")
|
||||
|
||||
def test_api_base_url(self):
|
||||
|
||||
# test the api_base_url feature, and that it can contain a path
|
||||
config = AppConfig()
|
||||
backend_port = find_available_port("localhost", 10000)
|
||||
config.update_server_config(
|
||||
app__api_base_url=f"http://localhost:{backend_port}/additional/path/before/dataroot",
|
||||
multi_dataset__dataroot=f"{PROJECT_ROOT}/example-dataset"
|
||||
)
|
||||
|
||||
config.complete_config()
|
||||
|
||||
with test_server(["-p", str(backend_port)], app_config=config) as server:
|
||||
session = requests.Session()
|
||||
self.assertEqual(server, f"http://localhost:{backend_port}")
|
||||
response = session.get(f"{server}/additional/path/before/dataroot/d/pbmc3k.h5ad/api/v0.2/config")
|
||||
self.assertEqual(response.status_code, 200)
|
||||
data_config = response.json()
|
||||
self.assertEqual(data_config["config"]["displayNames"]["dataset"], "pbmc3k")
|
||||
|
||||
Reference in New Issue
Block a user