: 无法建立新连接:[Errno 110] Connection timed out')),python,soap,wsdl,asmx,zeep"/>

首页 > 解决方案 > ping NewConnectionError(': 无法建立新连接:[Errno 110] Connection timed out'))

问题描述

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

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

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

这就是问题:

我启动我的服务器(/服务),然后用 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))

externalcompany_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

配置文件

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()

标签: pythonsoapwsdlasmxzeep

解决方案


解决了

原来存储在变量中的 URLWSDL_PRODUCTSWSDL_SALES错误的,因为我无法从浏览器访问相应的 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"

现在我的帖子得到了正确的回应:

{"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 来自 wsdl 文件,其 URL 保存在WSDL_SALES.

  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 序列化程序无法处理空响应。


推荐阅读