• 【待解决】记一次域名大小写导致的API调用失败问题


    在一次项目应用过程中,需要调用另一个组件的API,在url中将其域名配置为了大写,并在本地的/etc/hosts配置了对应的IP和域名的映射关系,但是在项目运行过程中,调用接口的时候仍然出现了错误:

    Failed to establish a new connection: [Errno -2] No address found

    下面分析下在项目中调用API的代码:

    API请求过程代码分析:

    依然以requests.Session.request为例。

    在request方法中,会调用self.send方法进行请求发送:

     在Session.send方法中,会先根据url生成一个adapter对象,然后调用adapter对象的send方法发送请求:

     adapter为requests/adapters.py中HTTPAdapter类的对象,其send方法中,则会调用self.get_connection获取一个conn对象,并调用conn的urlopen方法进行API调用:

     在self.get_connection方法中,先调用 select_proxy获取代理,由于我在发送请求的时候没使用代理,所以proxy为None;接着调用self.poolmanager的connection_from_url方法获取url的连接

     self.poolmanager为HTTPAdapter初始化的时候就配置好了:

     PoolManager为导入的requests.packages.urllib3.poolmanager中的类:

     

     在PoolManager中的connection_from_url方法里,返回的是调用self.connection_from_host的值:

     而在connection_from_host中,又调用了connection_from_context;在connection_from_context中,又调用了connection_from_pool_key

     在connection_from_pool_key中,调用了self._new_pool方法返回一个pool对象:

     在_new_pool中,则是根据scheme获取对应的pool_cls,再对其进行初始化对象:

     而pool_classes_by_scheme定义为:

     HTTPConnectionPool又是从requests.connectionpool中导入进来的:

     所以最终,conn就是一个requests.packages.urllib3.connectionpool.py中的HTTPConnectionPool对象。

    下面则是对conn.urlopen方法的调用:

    再来看看urlopen方法的定义。
    在requests.packages.urllib3.connectionpool.py中,HTTPConnectionPool的urlopen方法定义为:

    其中会先获取一个conn对象,再调用self._make_request方法发送请求。

    在self._get_conn中,是从self.pool中获取block对应的conn对象,如果没有,则调用self._new_conn生成一个新的conn对象:

     在HTTPConnectionPool中,_new_conn定义为:

     而HTTPConnectionPool中,已经定义了ConnectionCls属性:

     HTTPConnection是被导入进来的一个类:

     所以,这里返回的就是一个requests/packages/urllib3/connection.py中的HTTPConnection对象

    在_make_request中,chunked为默认的False,则调用conn.request方法:

    而在requests/packages/urllib3/connection.py中,HTTPConnection为导入进来的模块:

    from .packages.six.moves.http_client import HTTPConnection as _HTTPConnection

    在requests/packages/urllib3/packages/six.py中,

     

     通过MoveModule将httplib模块命名为http_client(对于python3,则是将httplib命名为http.client)

    所以最终调用的是httplib模块的request方法:

     在httplib中,_send_request定义如下,会调用self.endheaders方法:

     在endheaders方法中,定义如下,会调用self._send_output方法发送数据:

     httplib中,_send_output方法定义如下,其中会调用self.send方法:

     httplib中send方法定义为:

     self.sock初始为None,self.auto_open初始为1:

     所以会调用self.connect方法建立连接。

    回到requests/packages/urllib3/connection.py中的HTTPConnection类中,connect方法定义为:

     其中,_new_conn定义为:

     这里会调用requests/packages/urllib3/util/connection.py中的create_connection方法:

    在create_connection中,会调用socket的getaddrinfo获取host对应的IP信息:

    如果本地域名解析中配置了对应的host的映射关系,如:

    • 只配置大写:
    100.73.54.21 IRONIC

    则可以解析出对应的IP,如果没有配置映射关系,则解析失败:

    •  只配置小写
    100.73.54.21 ironic

    则可以解析出对应的IP,如果没有配置映射关系,则解析失败:

    •  大小写都配置:
    100.73.54.21 IRONIC ironic

    则都能解析:

    以上是在项目运行过程发现的问题,但是我直接用python的IDLE的时候,如果只配置某一个,则仍然可以解析:

    • 只配置大写
    100.73.54.21 IRONIC

    •  只配置小写
    100.73.54.21 ironic

    很神奇!!!

    天道酬勤
  • 相关阅读:
    React中路由的基本使用
    React中props
    一款超级炫酷的编辑代码的插件 Power Mode
    React中使用styled-components的基础使用
    对ES6的一次小梳理
    动态规划法(七)鸡蛋掉落问题(二)
    动态规划法(六)鸡蛋掉落问题(一)(egg dropping problem)
    三对角线性方程组(tridiagonal systems of equations)的求解
    Sherman-Morrison公式及其应用
    动态规划法(四)0-1背包问题(0-1 Knapsack Problem)
  • 原文地址:https://www.cnblogs.com/wangwei1/p/15785434.html
Copyright © 2020-2023  润新知