user8571377
user8571377

Reputation: 31

How to change endpoint address in SOAP requests with ZEEP

I am using ZEEP to make SOAP requests and it is easy and works great.

The problem is that the endpoint URL (in the WSDL) isn't correct.

I can solve the problem by editing the WSDL directly, but this isn't scalable.

I reviewed the ZEEP documentation about creating service proxies but I don't understand it and am having errors. Here is the part of the WSDL containing the bad URL:

</binding>
<service name="DeviceConfigurationService">
    <port name="DeviceConfigurationPort" 
binding="xrx:DeviceConfigurationBinding">
        <soap:address 
location="http://localhost/webservices/office/device_configuration/1"/>
    </port>
    </service>

the location is what I need to change. I need to change from "localhost" to a LAN IP address. This value may change frequently so I don't want to have to edit the WSDL every time.

Does anyone know how to do this with Zeep?

Any help is greatly appreciated!

Upvotes: 3

Views: 3316

Answers (2)

thehale
thehale

Reputation: 1736

I know this question is old, but I just had this same issue as I was accessing a third-party SOAP API with a WSDL that pointed to the wrong endpoint (the third party told me the correct endpoint but hadn't updated their WSDL). The accepted answer did point me in the right direction, but I'd like to offer some additional details that weren't immediately apparent to a fairly novice developer such as myself.

Start by noticing that Zeep's documentation shows that the method zeep.Client.create_service() has two parameters.

binding_name – The QName of the binding

address – The address of the endpoint

Figuring out the binding_name

Option 1 - Read through the WSDL

The binding_name comes from the attribute binding in the WSDL. The issue is that the value of that attribute usually includes a reference to a name elsewhere in the WSDL that you have to manually resolve before using it to create a custom service.

In the case of the excerpt from the OP's WSDL, the value of binding is "xrx:DeviceConfigurationBinding".

<service name="DeviceConfigurationService">
    <port name="DeviceConfigurationPort" binding="xrx:DeviceConfigurationBinding">
        <soap:address location="http://localhost/webservices/office/device_configuration/1"/>
    </port>
</service>

While this is the binding_name used by Zeep, you can't just copy and paste it into the parameter of create_service() because it is partially comprised of xrx - a name defined locally within the WSDL. Zeep automatically resolves the value of this kind of name when it originally parses the WSDL, so when you tell Zeep to point an existing binding to a different endpoint you have to resolve the binding name yourself so Zeep knows which binding you are talking about (that's why @jeffgabhart used {https://path-to-xrx-namespace} in his answer). In the end you should end up with complete binding_name of the format {NAMESPACE}BINDING.

Note that xrx isn't the only possible name. For me, the name was tns and for you it may be something different. Whatever it is, you should be able to find the definition of that name somewhere in the WSDL.

Option 2 - Use Zeep's WSDL parsing utility

Another option is the one suggested by @576i. Running the command python -mzeep WSDL_URL will spit out the information Zeep gathers from the given WSDL. One heading should say "Bindings" followed by a list (possibly of length 1) of binding_name's. From there you can copy the one you need to change the endpoint for.

Option 3 - Get it from the Zeep Client object

This one feels more like a hack, but list(zeep_client.wsdl.port_types) gives a list of all binding names that Zeep found in the WSDL used to create the zeep_client.

Figuring out the address

Lastly, for the sake of completeness, the address is simply the new endpoint you want to use instead of the one defined in the WSDL.

I hope this helps smooth out the learning curve for someone!

Upvotes: 4

jeffgabhart
jeffgabhart

Reputation: 1127

client = Client('http://localhost/webservices/office/device_configuration/1?wsdl')

service = client.create_service(
    '{http://path-to-xrx-namespace}DeviceConfigurationBinding',
    'http://127.0.0.1/webservices/office/device_configuration/1')

service.submit('something')

Upvotes: 0

Related Questions