ping NewConnectionError('<urllib3.connection.HTTPSConnection object at ...>: 建立新连接失败: [Errno 110] 连接超时'))

ping NewConnectionError('<urllib3.connection.HTTPSConnection object at ...>: Failed to establish a new connection: [Errno 110] Connection timed out'))

我对wsdl, asmx, client, zeep 和其他与SOAP APIs相关的主题很陌生,我必须修复一个系统“REST, SOAP APIs - 服务”,由其他人在 Python 中制作。

目前我只在我的本地机器上工作。这是主要上下文:

在我的项目主文件夹myservice中有:

这是问题所在:

我启动我的服务器 (/service),然后我用 Postman 将 POST 启动到 http://localhost:30205/service/ping(没有输入),但这是我得到的日志和回溯:

[I 2021-11-15 10:37:20.964 myserviceSrv:76] **************************************************
[I 2021-11-15 10:37:20.964 myserviceSrv:77] Starting externalcompany service 2021-11-15 10:37:20 on port 30205 for destination externalcompany
[I 2021-11-15 10:37:20.964 myserviceSrv:78] **************************************************
[I 2021-11-15 10:33:21.354 myserver_api:154] S - post Ping Handler    
[I 2021-11-15 10:33:21.354 myserver_api:158] Destination Ping Handler: externalcompany    
[I 2021-11-15 10:33:21.354 externalcompany_myserver_api:23] S - initialise wsdl    
[W 2021-11-15 10:33:22.833 soap:218] Forcing soap:address location to HTTPS    
[W 2021-11-15 10:33:22.833 soap:218] Forcing soap:address location to HTTPS    
[I 2021-11-15 10:33:22.834 externalcompany_myserver_api:26] Created wsdl externalcompany connection    
[I 2021-11-15 10:33:22.834 externalcompany_myserver_api:27] E - initialise wsdl    
[E 2021-11-15 10:35:33.348 externalcompany_myserver_api:216] Exception error ping: HTTPSConnectionPool(host='10.90.XXX.YY', port=8080): Max retries exceeded with url: /WebServices/Api/SalesApi.asmx (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x7f3a5dfc4cd0>: Failed to establish a new connection: [Errno 110] Connection timed out'))    
[I 2021-11-15 10:35:33.348 web:2239] 200 POST /service/ping (::1) 131994.51ms

这是我的问题:

  1. 我不明白 IP 地址 10.90.XXX.YY 来自哪里。我在整个项目文件夹中找不到对它的引用。
  2. 看起来代码成功初始化了 wsdl,但随后无法建立连接。但为什么?我做错了什么,我该如何解决?

内容如下:

myservice_api.py:

import tornado.web
from tornado import gen
import json
import logging
import config as config

class Ping(tornado.web.RequestHandler):

    def initialize(self, **kwargs):
        self.destination = kwargs["destination"]

    @gen.coroutine
    def post(self):
        logging.info('S - post Ping Handler')
        response = {}

        # Data received
        logging.info("Destination Ping Handler: {}".format(self.destination))

        # Init module with correct destination - start specific method ping()
        try:
            # calls the class associated to key "destination" -> the class ("externalcompanymyserviceApi") is initialized
            # init_wsdl is passed the wsdl sales file for settings
            destination_object_init = config.destination_schema[self.destination]()
            response = yield destination_object_init.ping()

        except Exception as e:
            logging.error("Error Ping Handler: {}".format(e))

        raise gen.Return(self.write(response))

外部公司_myservice_api.py:

import logging
import config as config
import json
import os
from tornado import gen
from zeep import Client, Settings, helpers
from zeep.exceptions import Fault, Error
from utils import utilities as utils

class externalcompanymyserviceApi:
    def __init__(self):
        # Init wsdl object for all methods in class externalcompany - utilities object
        self.wsdl_object_sales = self.init_wsdl(config.WSDL_SALES)

    # wsdl object
    @staticmethod
    def init_wsdl(type_wsdl):
        logging.info("S - initialise wsdl")
        settings = Settings(strict=False, xml_huge_tree=True)
        wsdl_externalcompany = Client(wsdl=type_wsdl, settings=settings)
        logging.info("Created wsdl externalcompany connection")
        logging.info("E - initialise wsdl")
        return wsdl_externalcompany

config.py

from tornado.options import define, parse_command_line
import logging
from handlers.externalcompany_myservice_api import externalcompanymyserviceApi

# LOGGING
logging.basicConfig(format='[%(levelname)1.1s %(asctime)s.%(msecs)03d %(module)s:%(lineno)d] %(message)s',
                    datefmt='%F %T')

# OPTIONS

# default: ip address of externalcompany (alias of externalcompany)
define("destination", default="externalcompany", help="destination of service", type=str)

# default: port of cash service intermediating with externalcompany
define("http_port", default=30205, help="run on the given port", type=int)

parse_command_line()

# SERVICE SETTINGS
DEBUG = True

######
# WSDL
######

# links to externalcompany test server
WSDL_PRODUCTS = "https://externalcompanyapi.vendorcompany.com/webservices/productservice_v1.asmx?WSDL"
WSDL_SALES = "https://externalcompanyapi.vendorcompany.com/WebServices/Api/SalesApi.asmx?WSDL"

# HANDLERS
PING = r"/service/ping"
# ...

destination_schema = {
    "externalcompany": externalcompanymyserviceApi,
    "John": "init class John"
}

myserviceSrv.py:

import config as cf
from config import PING
import logging
import tornado.web
from datetime import datetime
from tornado.log import enable_pretty_logging
from tornado.options import options
from tornado.ioloop import IOLoop
from tornado import httpserver

from handlers.myservice_api import Ping
#...

enable_pretty_logging()

class Destination_Service_Srv:

    def __init__(self):
        app = self.make_app()
        self.http_server = self.make_server(app)

    @staticmethod
    def make_app():
        settings = {
            "debug": cf.DEBUG
        }

        return tornado.web.Application([
            # ...
            (PING, Ping, {"destination": options.destination})
        ], **settings)

    @staticmethod
    def make_server(app):
        http_server = httpserver.HTTPServer(app, decompress_request=True)
        http_server.listen(options.http_port)
        return http_server

    def start(self):
        io_loop = IOLoop.current()
        io_loop.start()

    def stop(self):
        io_loop = IOLoop.current()
        io_loop.stop()

if __name__ == "__main__":

    today = datetime.today().strftime("%Y-%m-%d %H:%M:%S")
    myservice_server = Destination_Service_Srv()

    try:
        logging.info('**************************************************')
        logging.info('Starting myservice service {} on port {} for destination {}'.format(today, options.http_port,
                                                                                          options.destination))
        logging.info('**************************************************')
        myservice_server.start()

    except KeyboardInterrupt:
        myservice_server.stop()

已解决

原来存储在变量WSDL_PRODUCTSWSDL_SALES中的URL是错误的,因为我无法从浏览器访问相应的wsdl文件。

所以我发现正确的 URL 是 HTTP:// 而不是 HTTPS://

WSDL_PRODUCTS = "http://externalcompanyapi.vendorcompany.com/webservices/productservice_v1.asmx?WSDL"
WSDL_SALES = "http://externalcompanyapi.vendorcompany.com/WebServices/Api/SalesApi.asmx?WSDL"

现在我的 post 得到正确的响应:

{"ping": {"MessageNo": 1001, "MessageText": "Ping Response", "MessageInfo": "Response from 'START' on '16/11/2021
10:20:31'", "IsSuccess": true, "Content": null}}

所以,回答我自己的问题:

  1. IP地址10.90.XXX.YY来自URL保存在WSDL_SALES.

    的wsdl文件
  2. 如果我没看错,

    zeep 初始化了 wsdl,但它是按照 HTTPS 协议完成的,以便回溯指示

    [W 2021-11-15 10:33:22.833 soap:218] Forcing soap:address location to HTTPS
    [W 2021-11-15 10:33:22.833 soap:218] Forcing soap:address location to HTTPS

    因此为无效的 wsdl 配置了连接 URL。
    这是行失败

    zeep_response = helpers.serialize_object(self.wsdl_object_sales.service.Ping())

    因为 POST 无法获得响应,所以 zeep 序列化程序无法处理空响应。