Skip to content

Commit

Permalink
SQUASH THIS: use dev capabilities of globus-sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
sirosen committed Apr 15, 2022
1 parent 8ee54dc commit ea767b3
Showing 1 changed file with 74 additions and 12 deletions.
86 changes: 74 additions & 12 deletions src/globus_cli/commands/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@ def _get_url(service_name: str) -> str:
}[service_name]


def _format_json(res: globus_sdk.GlobusHTTPResponse) -> None:
click.echo(json.dumps(res.data, indent=2, separators=(",", ": "), sort_keys=True))


@group("api")
def api_command() -> None:
"""Make API calls to Globus services"""
Expand Down Expand Up @@ -171,6 +167,20 @@ def build_command(service_name: str) -> click.Command:
type=click.File("r"),
help="A request body to include, as a file. Mutually exclusive with --body",
)
@click.option(
"--allow-errors",
is_flag=True,
help="Allow error responses (4xx and 5xx) to be displayed without "
"triggering normal error handling",
)
@click.option(
"--allow-redirects",
"--location",
"-L",
is_flag=True,
help="If the server responds with a redirect (a 3xx response with a Location "
"header), follow the redirect. By default, redirects are not followed.",
)
@mutex_option_group("--body", "--body-file")
def service_command(
*,
Expand All @@ -182,17 +192,44 @@ def service_command(
body: Optional[str],
body_file: Optional[TextIO],
content_type: str,
allow_errors: bool,
allow_redirects: bool,
):
# the overall flow of this command will be as follows:
# - prepare a client
# - prepare parameters for the request
# - send the request capturing any error raised
# - process the response
# - on success or error with --allow-errors, print
# - on error without --allow-errors, reraise

client = _get_client(login_manager, service_name)
client.app_name = version.app_name + " raw-api-command"

# Prepare Query Params
query_params_d = {}
for param_name, param_value in query_param:
query_params_d[param_name] = param_value

# Prepare Request Body
# the value in 'body' will be passed in the request
# it is intentional that if neither `--body` nor `--body-file` is given,
# then `body=None`
if body_file:
body = body_file.read()

# Prepare Headers
# order of evaluation here matters
# first we process any Content-Type directive, especially for the default case
# of --content-type=auto
# after that, apply any manually provided headers, ensuring that they have
# higher precedence
#
# this also makes the behavior well-defined if a user passes
#
# --content-type=json -H "Content-Type: application/octet-stream"
#
# the explicit header wins and this is intentional and internally documented
headers_d = {}
if content_type != "none":
detected_content_type = detect_content_type(content_type, body)
Expand All @@ -201,14 +238,39 @@ def service_command(
for header_name, header_value in header:
headers_d[header_name] = header_value

res = client.request(
method.upper(),
path,
query_params=query_params_d,
data=body,
headers=headers_d,
)
termio.formatted_print(res, text_format=_format_json)
# try sending and handle any error
try:
res = client.request(
method.upper(),
path,
query_params=query_params_d,
data=body,
headers=headers_d,
allow_redirects=allow_redirects,
)
except globus_sdk.GlobusAPIError as e:
if not allow_errors:
raise

# we're in the allow-errors case, so print the HTTP response as text
if termio.is_verbose():
# if verbose, reconstruct the status line and show headers
click.echo(f"HTTP/1.1 {e.http_status} {e.http_reason}")
for key in e._underlying_response.headers:
click.echo(f"{key}: {e.headers[key]}")
click.echo()
# raw_text must be used here, to present the exact data which was sent, with
# whitespace and other detail preserved
click.echo(e.raw_text)
else:
# this is the success case -- logic is identical to the error handling case
# but on a response object rather than an exception
if termio.is_verbose():
click.echo(f"HTTP/1.1 {res.http_status} {res.http_reason}")
for key in res.headers:
click.echo(f"{key}: {res.headers[key]}")
click.echo()
click.echo(res.text)

return cast(click.Command, service_command)

Expand Down

0 comments on commit ea767b3

Please sign in to comment.