diff --git a/http_prompt/context/__init__.py b/http_prompt/context/__init__.py index 5198759..cdd9e09 100644 --- a/http_prompt/context/__init__.py +++ b/http_prompt/context/__init__.py @@ -1,4 +1,5 @@ from http_prompt.tree import Node +from urllib.parse import urlparse class Context(object): @@ -15,15 +16,28 @@ def __init__(self, url=None, spec=None): # Create a tree for supporting API spec and ls command self.root = Node('root') if spec: + is_open_api = 'openapi' in spec + if not self.url: - schemes = spec.get('schemes') - scheme = schemes[0] if schemes else 'https' - self.url = (scheme + '://' + - spec.get('host', 'http://localhost:8000') + - spec.get('basePath', '')) + if is_open_api: + # In open api, the schemes are in the 'server' element, + self.url = spec.get('servers', [{'url': 'http://localhost:8000'}])[0].get('url') + else: + schemes = spec.get('schemes') + scheme = schemes[0] if schemes else 'https' + self.url = (scheme + '://' + + spec.get('host', 'http://localhost:8000') + + spec.get('basePath', '')) + + # in open api, there is no 'basePath', we should extract that from the url + if is_open_api: + server = spec.get('servers', [{'url': 'http://localhost:8000'}])[0].get('url') + base_path_tokens = list(filter(lambda s: s, + urlparse(server).path.split('/'))) + else: + base_path_tokens = list(filter(lambda s: s, + spec.get('basePath', '').split('/'))) - base_path_tokens = list(filter(lambda s: s, - spec.get('basePath', '').split('/'))) paths = spec.get('paths') if paths: for path in paths: diff --git a/tests/test_cli.py b/tests/test_cli.py index 73e7ef4..e82649b 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -164,6 +164,45 @@ def test_spec_from_local(self): self.assertEqual(set([n.name for n in context.root.children]), set(['users', 'orgs'])) + def test_spec_from_local_yml(self): + spec_filepath = self.make_tempfile(""" + paths: + /users: + get: + description: + /orgs: + get: + description: + """) + result, context = run_and_exit(['example.com', "--spec", + spec_filepath]) + self.assertEqual(result.exit_code, 0) + self.assertEqual(context.url, 'http://example.com') + self.assertEqual(set([n.name for n in context.root.children]), + set(['users', 'orgs'])) + + def test_spec_from_local_yml_openapi(self): + spec_filepath = self.make_tempfile(""" + openapi: "3.0.0" + servers: + - url: https://localhost:8080/ + paths: + /api/users: + get: + description: + /api/orgs: + get: + description: + """) + result, context = run_and_exit(['example.com/api', "--spec", + spec_filepath]) + self.assertEqual(result.exit_code, 0) + self.assertEqual(context.url, 'http://example.com/api') + self.assertEqual(set([n.name for n in context.root.children]), + set(['api'])) + self.assertEqual(set([n.name for n in context.root.ls('api')]), + set(['users', 'orgs'])) + def test_spec_basePath(self): spec_filepath = self.make_tempfile(json.dumps({ 'basePath': '/api/v1', @@ -198,16 +237,16 @@ def test_spec_from_http(self): def test_spec_from_http_only(self): spec_url = ( - 'https://api.apis.guru/v2/specs/medium.com/1.0.0/swagger.json') + 'https://api.apis.guru/v2/specs/medium.com/1.0/openapi.json') result, context = run_and_exit(['--spec', spec_url]) self.assertEqual(result.exit_code, 0) - self.assertEqual(context.url, 'https://api.medium.com/v1') + self.assertEqual(context.url, 'https://medium2.p.rapidapi.com') lv1_names = set([node.name for node in context.root.ls()]) - lv2_names = set([node.name for node in context.root.ls('v1')]) + lv2_names = set([node.name for node in context.root.ls('article')]) - self.assertEqual(lv1_names, set(['v1'])) - self.assertEqual(lv2_names, set(['me', 'publications', 'users'])) + self.assertEqual(lv1_names, set(['/', 'topfeeds', 'related_tags', 'user', 'article', 'list', 'latestposts', 'search', 'top_writer', 'publication'])) + self.assertEqual(lv2_names, set(['{article_id}'])) def test_spec_with_trailing_slash(self): spec_filepath = self.make_tempfile(json.dumps({