mirror of
https://github.com/openSUSE/osc.git
synced 2025-02-04 18:46:17 +01:00
Merge pull request #145 from OlegGirko/api-fix-root-path
Add support for non-root paths in API URLs.
This commit is contained in:
commit
f9e54d0488
54
osc/conf.py
54
osc/conf.py
@ -382,17 +382,17 @@ cookiejar = None
|
|||||||
|
|
||||||
def parse_apisrv_url(scheme, apisrv):
|
def parse_apisrv_url(scheme, apisrv):
|
||||||
if apisrv.startswith('http://') or apisrv.startswith('https://'):
|
if apisrv.startswith('http://') or apisrv.startswith('https://'):
|
||||||
return urlsplit(apisrv)[0:2]
|
return urlsplit(apisrv)[0:3]
|
||||||
elif scheme != None:
|
elif scheme != None:
|
||||||
# the split/join is needed to get a proper url (e.g. without a trailing slash)
|
# the split/join is needed to get a proper url (e.g. without a trailing slash)
|
||||||
return urlsplit(urljoin(scheme, apisrv))[0:2]
|
return urlsplit(urljoin(scheme, apisrv))[0:3]
|
||||||
else:
|
else:
|
||||||
msg = 'invalid apiurl \'%s\' (specify the protocol (http:// or https://))' % apisrv
|
msg = 'invalid apiurl \'%s\' (specify the protocol (http:// or https://))' % apisrv
|
||||||
raise URLError(msg)
|
raise URLError(msg)
|
||||||
|
|
||||||
|
|
||||||
def urljoin(scheme, apisrv):
|
def urljoin(scheme, apisrv, path=''):
|
||||||
return '://'.join([scheme, apisrv])
|
return '://'.join([scheme, apisrv]) + path
|
||||||
|
|
||||||
|
|
||||||
def is_known_apiurl(url):
|
def is_known_apiurl(url):
|
||||||
@ -401,6 +401,21 @@ def is_known_apiurl(url):
|
|||||||
return apiurl in config['api_host_options']
|
return apiurl in config['api_host_options']
|
||||||
|
|
||||||
|
|
||||||
|
def extract_known_apiurl(url):
|
||||||
|
"""
|
||||||
|
Return longest prefix of given url that is known apiurl,
|
||||||
|
None if there is no known apiurl that is prefix of given url.
|
||||||
|
"""
|
||||||
|
scheme, host, path = parse_apisrv_url(None, url)
|
||||||
|
p = path.split('/')
|
||||||
|
while p:
|
||||||
|
apiurl = urljoin(scheme, host, '/'.join(p))
|
||||||
|
if apiurl in config['api_host_options']:
|
||||||
|
return apiurl
|
||||||
|
p.pop()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_apiurl_api_host_options(apiurl):
|
def get_apiurl_api_host_options(apiurl):
|
||||||
"""
|
"""
|
||||||
Returns all apihost specific options for the given apiurl, None if
|
Returns all apihost specific options for the given apiurl, None if
|
||||||
@ -441,10 +456,9 @@ def get_apiurl_usr(apiurl):
|
|||||||
# So we need to build a new opener everytime we switch the
|
# So we need to build a new opener everytime we switch the
|
||||||
# apiurl (because different apiurls may have different
|
# apiurl (because different apiurls may have different
|
||||||
# cafile/capath locations)
|
# cafile/capath locations)
|
||||||
def _build_opener(url):
|
def _build_opener(apiurl):
|
||||||
from osc.core import __version__
|
from osc.core import __version__
|
||||||
global config
|
global config
|
||||||
apiurl = urljoin(*parse_apisrv_url(None, url))
|
|
||||||
if 'last_opener' not in _build_opener.__dict__:
|
if 'last_opener' not in _build_opener.__dict__:
|
||||||
_build_opener.last_opener = (None, None)
|
_build_opener.last_opener = (None, None)
|
||||||
if apiurl == _build_opener.last_opener[0]:
|
if apiurl == _build_opener.last_opener[0]:
|
||||||
@ -644,18 +658,18 @@ def config_set_option(section, opt, val=None, delete=False, update=True, **kwarg
|
|||||||
general_opts = [i for i in DEFAULTS.keys() if not i in ['user', 'pass', 'passx']]
|
general_opts = [i for i in DEFAULTS.keys() if not i in ['user', 'pass', 'passx']]
|
||||||
if section != 'general':
|
if section != 'general':
|
||||||
section = config['apiurl_aliases'].get(section, section)
|
section = config['apiurl_aliases'].get(section, section)
|
||||||
scheme, host = \
|
scheme, host, path = \
|
||||||
parse_apisrv_url(config.get('scheme', 'https'), section)
|
parse_apisrv_url(config.get('scheme', 'https'), section)
|
||||||
section = urljoin(scheme, host)
|
section = urljoin(scheme, host, path)
|
||||||
|
|
||||||
sections = {}
|
sections = {}
|
||||||
for url in cp.sections():
|
for url in cp.sections():
|
||||||
if url == 'general':
|
if url == 'general':
|
||||||
sections[url] = url
|
sections[url] = url
|
||||||
else:
|
else:
|
||||||
scheme, host = \
|
scheme, host, path = \
|
||||||
parse_apisrv_url(config.get('scheme', 'https'), url)
|
parse_apisrv_url(config.get('scheme', 'https'), url)
|
||||||
apiurl = urljoin(scheme, host)
|
apiurl = urljoin(scheme, host, path)
|
||||||
sections[apiurl] = url
|
sections[apiurl] = url
|
||||||
|
|
||||||
section = sections.get(section.rstrip('/'), section)
|
section = sections.get(section.rstrip('/'), section)
|
||||||
@ -702,19 +716,20 @@ def write_initial_config(conffile, entries, custom_template=''):
|
|||||||
config.update(entries)
|
config.update(entries)
|
||||||
# at this point use_keyring and gnome_keyring are str objects
|
# at this point use_keyring and gnome_keyring are str objects
|
||||||
if config['use_keyring'] == '1' and GENERIC_KEYRING:
|
if config['use_keyring'] == '1' and GENERIC_KEYRING:
|
||||||
protocol, host = \
|
protocol, host, path = \
|
||||||
parse_apisrv_url(None, config['apiurl'])
|
parse_apisrv_url(None, config['apiurl'])
|
||||||
keyring.set_password(host, config['user'], config['pass'])
|
keyring.set_password(host, config['user'], config['pass'])
|
||||||
config['pass'] = ''
|
config['pass'] = ''
|
||||||
config['passx'] = ''
|
config['passx'] = ''
|
||||||
elif config['gnome_keyring'] == '1' and GNOME_KEYRING:
|
elif config['gnome_keyring'] == '1' and GNOME_KEYRING:
|
||||||
protocol, host = \
|
protocol, host, path = \
|
||||||
parse_apisrv_url(None, config['apiurl'])
|
parse_apisrv_url(None, config['apiurl'])
|
||||||
gnomekeyring.set_network_password_sync(
|
gnomekeyring.set_network_password_sync(
|
||||||
user=config['user'],
|
user=config['user'],
|
||||||
password=config['pass'],
|
password=config['pass'],
|
||||||
protocol=protocol,
|
protocol=protocol,
|
||||||
server=host)
|
server=host,
|
||||||
|
object=path)
|
||||||
config['user'] = ''
|
config['user'] = ''
|
||||||
config['pass'] = ''
|
config['pass'] = ''
|
||||||
config['passx'] = ''
|
config['passx'] = ''
|
||||||
@ -741,19 +756,20 @@ def add_section(filename, url, user, passwd):
|
|||||||
# Section might have existed, but was empty
|
# Section might have existed, but was empty
|
||||||
pass
|
pass
|
||||||
if config['use_keyring'] and GENERIC_KEYRING:
|
if config['use_keyring'] and GENERIC_KEYRING:
|
||||||
protocol, host = parse_apisrv_url(None, url)
|
protocol, host, path = parse_apisrv_url(None, url)
|
||||||
keyring.set_password(host, user, passwd)
|
keyring.set_password(host, user, passwd)
|
||||||
cp.set(url, 'keyring', '1')
|
cp.set(url, 'keyring', '1')
|
||||||
cp.set(url, 'user', user)
|
cp.set(url, 'user', user)
|
||||||
cp.remove_option(url, 'pass')
|
cp.remove_option(url, 'pass')
|
||||||
cp.remove_option(url, 'passx')
|
cp.remove_option(url, 'passx')
|
||||||
elif config['gnome_keyring'] and GNOME_KEYRING:
|
elif config['gnome_keyring'] and GNOME_KEYRING:
|
||||||
protocol, host = parse_apisrv_url(None, url)
|
protocol, host, path = parse_apisrv_url(None, url)
|
||||||
gnomekeyring.set_network_password_sync(
|
gnomekeyring.set_network_password_sync(
|
||||||
user=user,
|
user=user,
|
||||||
password=passwd,
|
password=passwd,
|
||||||
protocol=protocol,
|
protocol=protocol,
|
||||||
server=host)
|
server=host,
|
||||||
|
object=path)
|
||||||
cp.set(url, 'keyring', '1')
|
cp.set(url, 'keyring', '1')
|
||||||
cp.remove_option(url, 'pass')
|
cp.remove_option(url, 'pass')
|
||||||
cp.remove_option(url, 'passx')
|
cp.remove_option(url, 'passx')
|
||||||
@ -836,8 +852,8 @@ def get_config(override_conffile=None,
|
|||||||
aliases = {}
|
aliases = {}
|
||||||
for url in [x for x in cp.sections() if x != 'general']:
|
for url in [x for x in cp.sections() if x != 'general']:
|
||||||
# backward compatiblity
|
# backward compatiblity
|
||||||
scheme, host = parse_apisrv_url(config.get('scheme', 'https'), url)
|
scheme, host, path = parse_apisrv_url(config.get('scheme', 'https'), url)
|
||||||
apiurl = urljoin(scheme, host)
|
apiurl = urljoin(scheme, host, path)
|
||||||
user = None
|
user = None
|
||||||
password = None
|
password = None
|
||||||
if config['use_keyring'] and GENERIC_KEYRING:
|
if config['use_keyring'] and GENERIC_KEYRING:
|
||||||
@ -851,7 +867,7 @@ def get_config(override_conffile=None,
|
|||||||
elif config['gnome_keyring'] and GNOME_KEYRING:
|
elif config['gnome_keyring'] and GNOME_KEYRING:
|
||||||
# Read from gnome keyring if available
|
# Read from gnome keyring if available
|
||||||
try:
|
try:
|
||||||
gk_data = gnomekeyring.find_network_password_sync(protocol=scheme, server=host)
|
gk_data = gnomekeyring.find_network_password_sync(protocol=scheme, server=host, object=path)
|
||||||
if not 'user' in gk_data[0]:
|
if not 'user' in gk_data[0]:
|
||||||
raise oscerr.ConfigError('no user found in keyring', conffile)
|
raise oscerr.ConfigError('no user found in keyring', conffile)
|
||||||
user = gk_data[0]['user']
|
user = gk_data[0]['user']
|
||||||
|
11
osc/core.py
11
osc/core.py
@ -3148,8 +3148,8 @@ def makeurl(baseurl, l, query=[]):
|
|||||||
elif isinstance(query, type(dict())):
|
elif isinstance(query, type(dict())):
|
||||||
query = urlencode(query)
|
query = urlencode(query)
|
||||||
|
|
||||||
scheme, netloc = urlsplit(baseurl)[0:2]
|
scheme, netloc, path = urlsplit(baseurl)[0:3]
|
||||||
return urlunsplit((scheme, netloc, '/'.join(l), query, ''))
|
return urlunsplit((scheme, netloc, '/'.join([path] + l), query, ''))
|
||||||
|
|
||||||
|
|
||||||
def http_request(method, url, headers={}, data=None, file=None):
|
def http_request(method, url, headers={}, data=None, file=None):
|
||||||
@ -3174,10 +3174,11 @@ def http_request(method, url, headers={}, data=None, file=None):
|
|||||||
|
|
||||||
req = URLRequest(url)
|
req = URLRequest(url)
|
||||||
api_host_options = {}
|
api_host_options = {}
|
||||||
if conf.is_known_apiurl(url):
|
apiurl = conf.extract_known_apiurl(url)
|
||||||
|
if apiurl is not None:
|
||||||
# ok no external request
|
# ok no external request
|
||||||
install_opener(conf._build_opener(url))
|
install_opener(conf._build_opener(apiurl))
|
||||||
api_host_options = conf.get_apiurl_api_host_options(url)
|
api_host_options = conf.get_apiurl_api_host_options(apiurl)
|
||||||
for header, value in api_host_options['http_headers']:
|
for header, value in api_host_options['http_headers']:
|
||||||
req.add_header(header, value)
|
req.add_header(header, value)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user