44from __future__ import annotations
55
66import argparse
7+ import base64
78import copy
89import filecmp
910import json
1718from dataclasses import dataclass
1819from typing import Any , Dict , Iterable , List , Optional , Sequence , Tuple
1920from urllib .error import HTTPError , URLError
20- from urllib .parse import parse_qsl , urlencode , urlparse , urlunparse
2121from urllib .request import Request , urlopen
2222
2323
@@ -102,27 +102,29 @@ def load_package_version(version_path: pathlib.Path) -> str:
102102
103103
104104def resolve_source_url (manifest : Dict [str , Any ], explicit_url : Optional [str ]) -> str :
105- source_url = explicit_url or os .getenv ("JUSTSERPAPI_OPENAPI_URL" ) or manifest ["spec" ]["source_url" ]
106- parsed = urlparse (source_url )
107- query = parse_qsl (parsed .query , keep_blank_values = True )
108- has_api_key = any (key == "api_key" for key , _ in query )
109- env_api_key = os .getenv ("JUSTSERPAPI_OPENAPI_API_KEY" )
110- if env_api_key and not has_api_key :
111- query .append (("api_key" , env_api_key ))
112- return urlunparse (parsed ._replace (query = urlencode (query )))
105+ return explicit_url or os .getenv ("JUSTSERPAPI_OPENAPI_URL" ) or manifest ["spec" ]["source_url" ]
106+
107+
108+ def resolve_fetch_headers () -> Dict [str , str ]:
109+ headers = {
110+ "Accept" : "application/json" ,
111+ "User-Agent" : "justserpapi-ruby-sdkctl/0.1" ,
112+ }
113+
114+ username = os .getenv ("JUSTSERPAPI_OPENAPI_USERNAME" )
115+ password = os .getenv ("JUSTSERPAPI_OPENAPI_PASSWORD" )
116+ if username is not None and password is not None :
117+ encoded = base64 .b64encode (("%s:%s" % (username , password )).encode ("utf-8" )).decode ("ascii" )
118+ headers ["Authorization" ] = "Basic %s" % encoded
119+
120+ return headers
113121
114122
115123def fetch_spec_command (args : argparse .Namespace , manifest : Dict [str , Any ]) -> None :
116124 source_url = resolve_source_url (manifest , args .source_url )
117125 output_path = resolve_path (args .output or manifest ["spec" ]["raw_path" ])
118126
119- request = Request (
120- source_url ,
121- headers = {
122- "Accept" : "application/json" ,
123- "User-Agent" : "justserpapi-ruby-sdkctl/0.1"
124- },
125- )
127+ request = Request (source_url , headers = resolve_fetch_headers ())
126128
127129 log ("Fetching spec from %s" % source_url )
128130 try :
@@ -131,7 +133,8 @@ def fetch_spec_command(args: argparse.Namespace, manifest: Dict[str, Any]) -> No
131133 except HTTPError as exc :
132134 if exc .code == 401 :
133135 raise CLIError (
134- "Spec fetch returned HTTP 401. Set JUSTSERPAPI_OPENAPI_API_KEY or JUSTSERPAPI_OPENAPI_URL."
136+ "Spec fetch returned HTTP 401. Set JUSTSERPAPI_OPENAPI_USERNAME and "
137+ "JUSTSERPAPI_OPENAPI_PASSWORD, or JUSTSERPAPI_OPENAPI_URL if the docs URL changed."
135138 ) from exc
136139 raise CLIError ("Unable to fetch spec from %s: HTTP %s" % (source_url , exc .code )) from exc
137140 except URLError as exc :
@@ -560,4 +563,3 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
560563
561564if __name__ == "__main__" :
562565 raise SystemExit (main ())
563-
0 commit comments