Example #1
0
    def refresh(self, refresh_token=None):
        """Get a new access token from the supplied refresh token
        https://svn.tools.ietf.org/html/draft-hammer-oauth2-00#section-4
        """
        endpoint = 'access_token'
        refresh_token = refresh_token or self.refresh_token
        if not refresh_token:
            raise ValueError("refresh_token can't be empty")

        args = {
            'grant_type': 'refresh_token',
            'client_id': self._api_key,
            'refresh_token': refresh_token,
        }

        uri = urlparse.urljoin(self.BASE_URL, endpoint)
        body = urlencode(args)
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
        }

        req = Request(uri, body, headers)
        resp = urlopen(req)
        content = resp.read()

        if not resp.code == 200:
            raise Error(content)

        response_args = dict(parse_qsl(content))
        self.access_token = response_args.get("access_token", None)
        self.refresh_token = response_args.get("refresh_token", None)
        return response_args
Example #2
0
    def refresh(self, refresh_token=None):
        """Get a new access token from the supplied refresh token
        https://svn.tools.ietf.org/html/draft-hammer-oauth2-00#section-4
        """
        endpoint = 'access_token'
        refresh_token = refresh_token or self.refresh_token
        if not refresh_token:
            raise ValueError("refresh_token can't be empty")

        args = {
            'grant_type': 'refresh_token',
            'client_id': self._api_key,
            'refresh_token': refresh_token,
        }

        uri = urlparse.urljoin(self.BASE_URL, endpoint)
        body = urlencode(args)
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
        }

        req = Request(uri, body, headers)
        resp = urlopen(req)
        content = resp.read()

        if not resp.code == 200:
            raise Error(content)

        response_args = dict(parse_qsl(content))
        self.access_token = response_args.get("access_token", None)
        self.refresh_token = response_args.get("refresh_token", None)
        return response_args
Example #3
0
 def to_string(self):
     data = {
         'oauth_token': self.key,
         'oauth_token_secret': self.secret,
     }
     if self.callback_confirmed is not None:
         data['oauth_callback_confirmed'] = self.callback_confirmed
     return urlencode(data)
Example #4
0
    def get_access_token(self, code):
        """user code to access token
        Get an access token from the supplied code
        https://svn.tools.ietf.org/html/draft-hammer-oauth2-00#section-3.5.2.2
        """
        if code is None:
            raise ValueError("Code must be set.")

        endpoint='access_token'

        params = {}
        if 'state' in self.params:
            params['state'] = self.params['state']

        args = {
            'grant_type': 'authorization_code',
            'client_id': self._api_key,
            'client_secret': self._api_secret,
            'code': code,
            'redirect_uri': self.callback,
        }

        args.update(params or {})

        uri = urlparse.urljoin(self.BASE_URL, endpoint)
        body = urlencode(args)
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
        }
        req = Request(uri, body, headers)
        resp = urlopen(req)
        content = resp.read()

        if not resp.code == 200:
            print (resp, resp.code, content)
            raise Error(content)

        response_args = dict(parse_qsl(content))

        error = response_args.get('error', None)
        if error is not None:
            msg = "%s:%s" % (error,
                             response_args.get('error_description', ''))
            raise Error(msg)

        refresh_token = response_args.get('refresh_token', None)
        access_token = response_args.get('access_token', None)
        openid = response_args.get('openid', None)

        self.refresh_token = refresh_token
        self.access_token = access_token
        self.openid = openid

        if refresh_token is not None:
            response_args = self.refresh(refresh_token)

        return response_args
Example #5
0
    def _normalize_request_parameters(self, oauth_params, req_kwargs):
        '''
        This process normalizes the request parameters as detailed in the OAuth
        1.0 spec.

        Additionally we apply a `Content-Type` header to the request of the
        `FORM_URLENCODE` type if the `Content-Type` was previously set, i.e. if
        this is a `POST` or `PUT` request. This ensures the correct header is
        set as per spec.

        Finally we sort the parameters in preparation for signing and return
        a URL encoded string of all normalized parameters.

        :param oauth_params: OAuth params to sign with.
        :type oauth_params: dict
        :param req_kwargs: Request kwargs to normalize.
        :type req_kwargs: dict
        '''
        normalized = []

        params = req_kwargs.get('params', {})
        data = req_kwargs.get('data', {})
        headers = req_kwargs.get('headers', {})

        # process request parameters
        for k, v in params.items():
            if v is not None:
                normalized += [(k, v)]

        # process request data
        if 'Content-Type' in headers and \
                headers['Content-Type'] == FORM_URLENCODED:
            for k, v in data.items():
                normalized += [(k, v)]

        # extract values from our list of tuples
        all_normalized = []
        for t in normalized:
            k, v = t
            if is_basestring(v) and not isinstance(v, bytes):
                v = v.encode('utf-8')
            all_normalized += [(k, v)]

        # add in the params from oauth_params for signing
        for k, v in oauth_params.items():
            if (k, v) in all_normalized:  # pragma: no cover
                continue
            all_normalized += [(k, v)]

        # sort the params as per the OAuth 1.0/a spec
        all_normalized.sort()

        # finally encode the params as a string
        return urlencode(all_normalized, True)\
            .replace('+', '%20')\
            .replace('%7E', '~')
Example #6
0
    def get_access_token(self, code):
        """user code to access token
        Get an access token from the supplied code
        https://svn.tools.ietf.org/html/draft-hammer-oauth2-00#section-3.5.2.2
        """
        if code is None:
            raise ValueError("Code must be set.")

        endpoint = 'access_token'

        params = {}
        if 'state' in self.params:
            params['state'] = self.params['state']

        args = {
            'grant_type': 'authorization_code',
            'client_id': self._api_key,
            'client_secret': self._api_secret,
            'code': code,
            'redirect_uri': self.callback,
        }

        args.update(params or {})

        uri = urlparse.urljoin(self.BASE_URL, endpoint)
        body = urlencode(args)
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
        }
        req = Request(uri, body, headers)
        resp = urlopen(req)
        content = resp.read()

        if not resp.code == 200:
            print(resp, resp.code, content)
            raise Error(content)

        response_args = dict(parse_qsl(content))

        error = response_args.get('error', None)
        if error is not None:
            msg = "%s:%s" % (error, response_args.get('error_description', ''))
            raise Error(msg)

        refresh_token = response_args.get('refresh_token', None)
        access_token = response_args.get('access_token', None)
        openid = response_args.get('openid', None)

        self.refresh_token = refresh_token
        self.access_token = access_token
        self.openid = openid

        if refresh_token is not None:
            response_args = self.refresh(refresh_token)

        return response_args
Example #7
0
	def _server_submit(self, json):
		# submit json to server
		postdata = urlencode({'json': setupfile.encode_setup(json)})
		res = self._url_json('submit', data=postdata)
		if res.error:
			raise Exception("Submit failed: " + res.error)
		if not res.why_build:
			if not self.subjob_cookie:
				self._printlist(res.jobs)
			self.validate_response(res.jobs)
		return res
Example #8
0
    def get_authorize_url(self, **params):
        '''
        Returns a formatted authorize URL.

        :param \*\*params: Additional keyworded arguments to be added to the
            URL querystring.
        :type \*\*params: dict
        '''

        params.update({'client_id': self.client_id})
        return self.authorize_url + '?' + urlencode(params)
Example #9
0
    def get_authorize_url(self, request_token, **params):
        '''
        Returns a formatted authorize URL.

        :param request_token: The request token as returned by
            :class:`get_request_token`.
        :type request_token: str
        :param \*\*params: Additional keyworded arguments to be added to the
            request querystring.
        :type \*\*params: dict
        '''
        params.update({'oauth_token': request_token})
        return self.authorize_url + '?' + urlencode(params)
Example #10
0
def encode_url_params(params, keep_blank=False):
    # TODO: handle case where params is just a string
    res = []
    for k, vs in get_items(params):
        if is_scalar(vs):
            vs = [vs]
        for v in vs:
            if not v:
                if keep_blank:
                    v = ''
                else:
                    continue
            res.append((get_encoded(k), get_encoded(v)))
    return urlencode(res, doseq=True)
Example #11
0
    def _utf8_urlencode(self, data):

        if self._is_string_type(data):
            return data.encode('utf-8')

        if not isinstance(data, dict):
            return data

        utf8_data = {}
        for k, v in data.items():
            if self._is_string_type(v):
                v = v.encode('utf-8')
            utf8_data[k] = v
        return urlencode(utf8_data)
Example #12
0
def _request(url, payload):
    """Make request to Slack's incoming webhooks api."""

    payload = json.dumps(payload)
    data = urlencode({'payload': payload}).encode('utf-8')

    handler = urlrequest.HTTPHandler()
    opener = urlrequest.build_opener(handler)

    request = urlrequest.Request(url)
    response = opener.open(request, data)

    if response.getcode() != 200:
        raise APIError(response.msg)
    return True
Example #13
0
    def get_authorization_url(self):
        """return a url for user to open
        Get the URL to redirect the user for client authorization
        https://svn.tools.ietf.org/html/draft-hammer-oauth2-00#section-3.5.2.1
        """
        endpoint = 'authorize'
        redirect_uri = self.callback
        params = self.params

        args = {'response_type': 'code', 'client_id': self._api_key}

        args['redirect_uri'] = self.callback
        args.update(params or {})

        return '%s?%s' % (urlparse.urljoin(self.BASE_URL,
                                           endpoint), urlencode(args))
Example #14
0
    def get_authorization_url(self):
        """return a url for user to open
        Get the URL to redirect the user for client authorization
        https://svn.tools.ietf.org/html/draft-hammer-oauth2-00#section-3.5.2.1
        """
        endpoint = 'authorize'
        redirect_uri = self.callback
        params = self.params

        args = {
            'response_type': 'code',
            'client_id': self._api_key
        }

        args['redirect_uri'] = self.callback
        args.update(params or {})

        return '%s?%s' % (urlparse.urljoin(self.BASE_URL, endpoint),
                          urlencode(args))
Example #15
0
def spoofer(headers=None,
            _agent=True,
            age_str=randomagent(),
            referer=False,
            ref_str=''):

    append = '|'

    if not headers:
        headers = {}

    if _agent and age_str and not headers:
        headers.update({'User-Agent': age_str})

    if referer and ref_str:
        headers.update({'Referer': ref_str})

    if headers:
        append += urlencode(headers)
    else:
        append = ''

    return append
Example #16
0
    def _getStreamURL(self, **params):
        if self.TYPE not in ('movie', 'episode', 'track'):
            raise exceptions.Unsupported(
                'Fetching stream URL for %s is unsupported.' % self.TYPE)
        mvb = params.get('maxVideoBitrate')
        vr = params.get('videoResolution')

        # import plexapp

        params = {
            'path': self.key,
            'offset': params.get('offset', 0),
            'copyts': params.get('copyts', 1),
            'protocol': params.get('protocol', 'hls'),
            'mediaIndex': params.get('mediaIndex', 0),
            'directStream': '1',
            'directPlay': '0',
            'X-Plex-Platform': params.get('platform', 'Chrome'),
            # 'X-Plex-Platform': params.get('platform', plexapp.INTERFACE.getGlobal('platform')),
            'maxVideoBitrate': max(mvb, 64) if mvb else None,
            'videoResolution': '{0}x{1}'.format(*vr) if vr else None
        }

        final = {}

        for k, v in params.items():
            if v is not None:  # remove None values
                final[k] = v

        streamtype = 'audio' if self.TYPE in ('track', 'album') else 'video'
        server = self.getTranscodeServer(True, self.TYPE)

        return server.buildUrl(
            '/{0}/:/transcode/universal/start.m3u8?{1}'.format(
                streamtype, compat.urlencode(final)),
            includeToken=True)
Example #17
0
def _mb_request(path, method='GET', auth_required=AUTH_NO,
                client_required=False, args=None, data=None, body=None):
    """Makes a request for the specified `path` (endpoint) on /ws/2 on
    the globally-specified hostname. Parses the responses and returns
    the resulting object.  `auth_required` and `client_required` control
    whether exceptions should be raised if the username/password and
    client are left unspecified, respectively.
    """
    global parser_fun

    if args is None:
        args = {}
    else:
        args = dict(args) or {}

    if _useragent == "":
        raise UsageError("set a proper user-agent with "
                         "set_useragent(\"application name\", \"application version\", \"contact info (preferably URL or email for your application)\")")

    if client_required:
        args["client"] = _client

    if ws_format != "xml":
        args["fmt"] = ws_format

    # Convert args from a dictionary to a list of tuples
    # so that the ordering of elements is stable for easy
    # testing (in this case we order alphabetically)
    # Encode Unicode arguments using UTF-8.
    newargs = []
    for key, value in sorted(args.items()):
        if isinstance(value, compat.unicode):
            value = value.encode('utf8')
        newargs.append((key, value))

    # Construct the full URL for the request, including hostname and
    # query string.
    url = compat.urlunparse((
        'http',
        hostname,
        '/ws/2/%s' % path,
        '',
        compat.urlencode(newargs),
        ''
    ))
    _log.debug("%s request for %s" % (method, url))

    # Set up HTTP request handler and URL opener.
    httpHandler = compat.HTTPHandler(debuglevel=0)
    handlers = [httpHandler]

    # Add credentials if required.
    add_auth = False
    if auth_required == AUTH_YES:
        _log.debug("Auth required for %s" % url)
        if not user:
            raise UsageError("authorization required; "
                             "use auth(user, pass) first")
        add_auth = True

    if auth_required == AUTH_IFSET and user:
        _log.debug("Using auth for %s because user and pass is set" % url)
        add_auth = True

    if add_auth:
        passwordMgr = _RedirectPasswordMgr()
        authHandler = _DigestAuthHandler(passwordMgr)
        authHandler.add_password("musicbrainz.org", (), user, password)
        handlers.append(authHandler)

    opener = compat.build_opener(*handlers)

    # Make request.
    req = _MusicbrainzHttpRequest(method, url, data)
    req.add_header('User-Agent', _useragent)
    _log.debug("requesting with UA %s" % _useragent)
    if body:
        req.add_header('Content-Type', 'application/xml; charset=UTF-8')
    elif not data and not req.has_header('Content-Length'):
        # Explicitly indicate zero content length if no request data
        # will be sent (avoids HTTP 411 error).
        req.add_header('Content-Length', '0')
    resp = _safe_read(opener, req, body)

    return parser_fun(resp)
Example #18
0
def request(url,
            close=True,
            redirect=True,
            error=False,
            proxy=None,
            post=None,
            headers=None,
            mobile=False,
            limit=None,
            referer=None,
            cookie=None,
            output='',
            timeout='30',
            username=None,
            password=None):

    if isinstance(post, dict):
        if is_py2:
            post = urlencode(post)
        elif is_py3:
            post = bytes(urlencode(post), encoding='utf-8')
    elif isinstance(post, basestring) and is_py3:
        post = bytes(post, encoding='utf-8')

    try:
        handlers = []

        if username is not None and password is not None and not proxy:
            passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()
            passmgr.add_password(None, uri=url, user=username, passwd=password)
            handlers += [urllib2.HTTPBasicAuthHandler(passmgr)]
            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        if proxy is not None:

            if username is not None and password is not None:
                passmgr = urllib2.ProxyBasicAuthHandler()
                passmgr.add_password(None,
                                     uri=url,
                                     user=username,
                                     passwd=password)
                handlers += [
                    urllib2.ProxyHandler({'http': '{0}'.format(proxy)}),
                    urllib2.HTTPHandler,
                    urllib2.ProxyBasicAuthHandler(passmgr)
                ]
            else:
                handlers += [
                    urllib2.ProxyHandler({'http': '{0}'.format(proxy)}),
                    urllib2.HTTPHandler
                ]
            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        if output == 'cookie' or output == 'extended' or close is not True:

            cookies = cookielib.LWPCookieJar()
            handlers += [
                urllib2.HTTPHandler(),
                urllib2.HTTPSHandler(),
                urllib2.HTTPCookieProcessor(cookies)
            ]

            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        try:

            if (2, 7, 9) < sys.version_info:
                raise BaseException

            import ssl
            try:
                import _ssl
                CERT_NONE = _ssl.CERT_NONE
            except ImportError:
                CERT_NONE = ssl.CERT_NONE
            ssl_context = ssl.create_default_context()
            ssl_context.check_hostname = False
            ssl_context.verify_mode = CERT_NONE
            handlers += [urllib2.HTTPSHandler(context=ssl_context)]
            opener = urllib2.build_opener(*handlers)
            urllib2.install_opener(opener)

        except BaseException:
            pass

        try:
            headers.update(headers)
        except BaseException:
            headers = {}

        if 'User-Agent' in headers:
            pass
        elif not mobile is True:
            #headers['User-Agent'] = agent()
            headers['User-Agent'] = randomagent()
        else:
            headers['User-Agent'] = 'Apple-iPhone/701.341'

        if 'Referer' in headers:
            pass
        elif referer is None:
            headers['Referer'] = '%s://%s/' % (urlparse(url).scheme,
                                               urlparse(url).netloc)
        else:
            headers['Referer'] = referer

        if not 'Accept-Language' in headers:
            headers['Accept-Language'] = 'en-US'

        if 'Cookie' in headers:
            pass
        elif cookie is not None:
            headers['Cookie'] = cookie

        if redirect is False:

            class NoRedirectHandler(urllib2.HTTPRedirectHandler):
                def http_error_302(self, reqst, fp, code, msg, head):

                    infourl = addinfourl(fp, head, reqst.get_full_url())
                    infourl.status = code
                    infourl.code = code

                    return infourl

                http_error_300 = http_error_302
                http_error_301 = http_error_302
                http_error_303 = http_error_302
                http_error_307 = http_error_302

            opener = urllib2.build_opener(NoRedirectHandler())
            urllib2.install_opener(opener)

            try:
                del headers['Referer']
            except Exception:
                pass

        req = urllib2.Request(url, data=post, headers=headers)

        try:

            response = urllib2.urlopen(req, timeout=int(timeout))

        except urllib2.HTTPError as response:

            if response.code == 503:

                if 'cf-browser-verification' in response.read(5242880):

                    netloc = '%s://%s' % (urlparse(url).scheme,
                                          urlparse(url).netloc)

                    cf = cfcookie(netloc, headers['User-Agent'], timeout)

                    headers['Cookie'] = cf

                    req = urllib2.Request(url, data=post, headers=headers)

                    response = urllib2.urlopen(req, timeout=int(timeout))

                elif error is False:
                    return

            elif error is False:
                return

        if output == 'cookie':

            try:
                result = '; '.join(
                    ['%s=%s' % (i.name, i.value) for i in cookies])
            except BaseException:
                pass
            try:
                result = cf
            except BaseException:
                pass

        elif output == 'response':

            if limit == '0':
                result = (str(response.code), response.read(224 * 1024))
            elif limit is not None:
                result = (str(response.code), response.read(int(limit) * 1024))
            else:
                result = (str(response.code), response.read(5242880))

        elif output == 'chunk':

            try:
                content = int(response.headers['Content-Length'])
            except BaseException:
                content = (2049 * 1024)

            if content < (2048 * 1024):
                return
            result = response.read(16 * 1024)

        elif output == 'extended':

            try:
                cookie = '; '.join(
                    ['%s=%s' % (i.name, i.value) for i in cookies])
            except BaseException:
                pass
            try:
                cookie = cf
            except BaseException:
                pass
            content = response.headers
            result = response.read(5242880)
            return result, headers, content, cookie

        elif output == 'geturl':
            result = response.geturl()

        elif output == 'headers':
            content = response.headers
            return content

        else:
            if limit == '0':
                result = response.read(224 * 1024)
            elif limit is not None:
                result = response.read(int(limit) * 1024)
            else:
                result = response.read(5242880)

        if close is True:
            response.close()

        return result

    except BaseException:
        return
Example #19
0
        def execute(self):
            # Build the request URL
            url = self.api_root + self.path
            #if self.api.source is not None:
            #    self.parameters.setdefault('source',self.api.source)

            if len(self.parameters):
                if self.method == 'GET':
                    url = '%s?%s' % (url, urlencode(self.parameters))
                else:
                    self.headers.setdefault("User-Agent", "pyqqweibo")
                    if self.post_data is None:
                        self.headers.setdefault("Accept", "text/html")
                        self.headers.setdefault("Content-Type", "application/x-www-form-urlencoded")
                        # asure in bytes format
                        self.post_data = urlencode(self.parameters).encode('ascii')
            # Query the cache if one is available
            # and this request uses a GET method.
            if self.api.cache and self.method == 'GET':
                cache_result = self.api.cache.get(url)
                # if cache result found and not expired, return it
                if cache_result:
                    # must restore api reference
                    if isinstance(cache_result, list):
                        for result in cache_result:
                            result._api = self.api
                    else:
                        cache_result._api = self.api
                    return cache_result
                #urllib.urlencode(self.parameters)
            # Continue attempting request until successful
            # or maximum number of retries is reached.
            sTime = time.time()
            retries_performed = 0
            while retries_performed < self.retry_count + 1:
                # Open connection
                # FIXME: add timeout
                # Apply authentication
                if self.require_auth and self.api.auth:
                    url_full = self.api.auth.get_authed_url(
                        self.scheme + self.host + url,
                        self.method, self.headers, self.parameters
                    )
                else:                   # this brunch is never accoured
                    url_full = self.api.auth.get_signed_url(
                        self.scheme + self.host + url,
                        self.method, self.headers, self.parameters
                    )
                try:
                    if self.method == 'POST':
                        req = Request(url_full, data=self.post_data, headers=self.headers)
                    else:
                        req = Request(url_full)
                    resp = urlopen(req)
                except Exception as e:
                    raise QWeiboError("Failed to request %s headers=%s %s" % \
                                      (url, self.headers, e))

                # Exit request loop if non-retry error code
                if self.retry_errors:
                    if resp.code not in self.retry_errors:
                        break
                else:
                    if resp.code == 200:
                        break

                # Sleep before retrying request again
                time.sleep(self.retry_delay)
                retries_performed += 1

            # If an error was returned, throw an exception
            body = resp.read()
            self.api.last_response = resp
            if self.api.log is not None:
                requestUrl = "URL:http://" + self.host + url
                eTime = '%.0f' % ((time.time() - sTime) * 1000)
                postData = ""
                if self.post_data is not None:
                    postData = ",post:" + self.post_data[:500]
                self.api.log.debug("%s, time: %s, %s result: %s" % (requestUrl, eTime, postData, body))

            retcode = 0
            errcode = 0
            # for py3k, ^_^
            if not hasattr(body, 'encode'):
                body = str(body, 'utf-8')
            if self.api.parser.payload_format == 'json':
                try:
                    # BUG: API BUG, refer api.doc.rst
                    if body.endswith('out of memery'):
                        body = body[:body.rfind('}')+1]
                    json = self.api.parser.parse_error(self, body)
                    retcode = json.get('ret', 0)
                    msg = json.get('msg', '')
                    # only in some post request
                    errcode = json.get('errcode', 0)
                except ValueError as e:
                    retcode = -1
                    msg = "Bad json format (%s)" % e
                finally:
                    if retcode + errcode != 0:
                        raise QWeiboError("Response error: %s. (ret=%s, errcode=%s)" % \
                                          (msg, retcode, errcode))

            # Parse the response payload
            result = self.api.parser.parse(self, body)

            # Store result into cache if one is available.
            if self.api.cache and self.method == 'GET' and result:
                self.api.cache.store(url, result)
            return result
Example #20
0
def _mb_request(path, method='GET', auth_required=False, client_required=False,
				args=None, data=None, body=None):
	"""Makes a request for the specified `path` (endpoint) on /ws/2 on
	the globally-specified hostname. Parses the responses and returns
	the resulting object.  `auth_required` and `client_required` control
	whether exceptions should be raised if the client and
	username/password are left unspecified, respectively.
	"""
	if args is None:
		args = {}
	else:
		args = dict(args) or {}

	if _useragent == "":
		raise UsageError("set a proper user-agent with "
						 "set_useragent(\"application name\", \"application version\", \"contact info (preferably URL or email for your application)\")")

	if client_required:
		args["client"] = _client

	# Encode Unicode arguments using UTF-8.
	for key, value in args.items():
		if isinstance(value, compat.unicode):
			args[key] = value.encode('utf8')

	# Construct the full URL for the request, including hostname and
	# query string.
	url = compat.urlunparse((
		'http',
		hostname,
		'/ws/2/%s' % path,
		'',
		compat.urlencode(args),
		''
	))
	_log.debug("%s request for %s" % (method, url))

	# Set up HTTP request handler and URL opener.
	httpHandler = compat.HTTPHandler(debuglevel=0)
	handlers = [httpHandler]

	# Add credentials if required.
	if auth_required:
		_log.debug("Auth required for %s" % url)
		if not user:
			raise UsageError("authorization required; "
							 "use auth(user, pass) first")
		passwordMgr = _RedirectPasswordMgr()
		authHandler = _DigestAuthHandler(passwordMgr)
		authHandler.add_password("musicbrainz.org", (), user, password)
		handlers.append(authHandler)

	opener = compat.build_opener(*handlers)

	# Make request.
	req = _MusicbrainzHttpRequest(method, url, data)
	req.add_header('User-Agent', _useragent)
	_log.debug("requesting with UA %s" % _useragent)
	if body:
		req.add_header('Content-Type', 'application/xml; charset=UTF-8')
	elif not data and not req.has_header('Content-Length'):
		# Explicitly indicate zero content length if no request data
		# will be sent (avoids HTTP 411 error).
		req.add_header('Content-Length', '0')
	f = _safe_open(opener, req, body)

	# Parse the response.
	try:
		return mbxml.parse_message(f)
	except UnicodeError as exc:
		raise ResponseError(cause=exc)
	except Exception as exc:
		if isinstance(exc, ETREE_EXCEPTIONS):
			raise ResponseError(cause=exc)
		else:
			raise
Example #21
0
def _mb_request(path,
                method='GET',
                auth_required=AUTH_NO,
                client_required=False,
                args=None,
                data=None,
                body=None):
    """Makes a request for the specified `path` (endpoint) on /ws/2 on
    the globally-specified hostname. Parses the responses and returns
    the resulting object.  `auth_required` and `client_required` control
    whether exceptions should be raised if the username/password and
    client are left unspecified, respectively.
    """
    global parser_fun

    if args is None:
        args = {}
    else:
        args = dict(args) or {}

    if _useragent == "":
        raise UsageError(
            "set a proper user-agent with "
            "set_useragent(\"application name\", \"application version\", \"contact info (preferably URL or email for your application)\")"
        )

    if client_required:
        args["client"] = _client

    if ws_format != "xml":
        args["fmt"] = ws_format

    # Convert args from a dictionary to a list of tuples
    # so that the ordering of elements is stable for easy
    # testing (in this case we order alphabetically)
    # Encode Unicode arguments using UTF-8.
    newargs = []
    for key, value in sorted(args.items()):
        if isinstance(value, compat.unicode):
            value = value.encode('utf8')
        newargs.append((key, value))

    # Construct the full URL for the request, including hostname and
    # query string.
    url = compat.urlunparse(('http', hostname, '/ws/2/%s' % path, '',
                             compat.urlencode(newargs), ''))
    _log.debug("%s request for %s" % (method, url))

    # Set up HTTP request handler and URL opener.
    httpHandler = compat.HTTPHandler(debuglevel=0)
    handlers = [httpHandler]

    # Add credentials if required.
    add_auth = False
    if auth_required == AUTH_YES:
        _log.debug("Auth required for %s" % url)
        if not user:
            raise UsageError("authorization required; "
                             "use auth(user, pass) first")
        add_auth = True

    if auth_required == AUTH_IFSET and user:
        _log.debug("Using auth for %s because user and pass is set" % url)
        add_auth = True

    if add_auth:
        passwordMgr = _RedirectPasswordMgr()
        authHandler = _DigestAuthHandler(passwordMgr)
        authHandler.add_password("musicbrainz.org", (), user, password)
        handlers.append(authHandler)

    opener = compat.build_opener(*handlers)

    # Make request.
    req = _MusicbrainzHttpRequest(method, url, data)
    req.add_header('User-Agent', _useragent)
    _log.debug("requesting with UA %s" % _useragent)
    if body:
        req.add_header('Content-Type', 'application/xml; charset=UTF-8')
    elif not data and not req.has_header('Content-Length'):
        # Explicitly indicate zero content length if no request data
        # will be sent (avoids HTTP 411 error).
        req.add_header('Content-Length', '0')
    resp = _safe_read(opener, req, body)

    return parser_fun(resp)