对接某为云总是报错{"message":"API not found","request_id":"---------"}

问题分析

调用了很多接口,使用域名访问的就会报此错误,使用IP直接访问的就没问题。所以怀疑是域名处理部分有问题,并且域名中有大写字母,更加重怀疑是某云的API网关区分host大小写导致。

解决问题

咱是对接方,只能咱们改。

项目中最后都会调用requests库进行最终的http调用,因此我们跟踪源码调试,发现有几个地方会讲url转换为小写。

  1. requests/packages/urllib3/poolmanager.py文件

    
    def _default_key_normalizer(key_class, request_context):
        """
        Create a pool key of type ``key_class`` for a request.
    	...
        """
        context = {}
        for key in key_class._fields:
            context[key] = request_context.get(key)
        context['scheme'] = context['scheme'].lower()
        # 将此处转小写删掉
        #context['host'] = context['host'].lower()
        return key_class(**context)
    
  2. requests/packages/urllib3/util/url.py文件

    class Url(namedtuple('Url', url_attrs)):
        """
        Datastructure for representing an HTTP URL. Used as a return value for
        :func:`parse_url`. Both the scheme and host are normalized as they are
        both case-insensitive according to RFC 3986.
        """
        __slots__ = ()
    
        def __new__(cls, scheme=None, auth=None, host=None, port=None, path=None,
                    query=None, fragment=None):
            if path and not path.startswith('/'):
                path = '/' + path
            if scheme:
                scheme = scheme.lower()
            # 将此处转小写删掉
            #if host:
            #    host = host.lower()
            return super(Url, cls).__new__(cls, scheme, auth, host, port, path,
                                           query, fragment)
    
  3. requests/models.py文件

    class PreparedRequest(RequestEncodingMixin, RequestHooksMixin):
        ...
        def prepare_url(self, url, params):
         	...
            try:
            	# 将uts46参数改为False
                #host = idna.encode(host, uts46=True).decode('utf-8')
                host = idna.encode(host, uts46=False).decode('utf-8')
            except (UnicodeError, idna.IDNAError):
                if not unicode_is_ascii(host) or host.startswith(u'*'):
                    raise InvalidURL('URL has an invalid label.')  
            ...