arskom / spyne

A transport agnostic sync/async RPC library that focuses on exposing services with a well-defined API using popular protocols.
http://spyne.io
Other
1.13k stars 313 forks source link

soap:address is duplicated #614

Closed jingz closed 5 years ago

jingz commented 5 years ago

I use python3.7 and spyne 2.13.10 (build from source)

I set up services as the Application takes many services on registration.

def create_spyne_app():
    from spyne import ServiceBase
    from .controllers import soap

    services = set()
    for module in _import_submodules_from_package(soap):
        for name, service in inspect.getmembers(module, lambda x: inspect.isclass(x) and issubclass(x, ServiceBase)):
            if service is not ServiceBase:
                services.add(service)

    print(services)
    # from soap to soap protocol
    return WsgiApplication(
               Application(services,
                   tns='spyne.example.flask',
                   in_protocol=Soap11(validator='lxml'),
                   out_protocol=Soap11()
           ))

...

# init with flask

    app.wsgi_app = DispatcherMiddleware(app.wsgi_app, {
        "/LeapServiceWS/services": create_spyne_app(),
        })

Then I access to http://localhost:5000/LeapServiceWS/services/?wsdl I got <wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWorldService/"/> duplicated in each service tag

...
<wsdl:service name="CustomerAccountListInq">
<wsdl:port name="Application" binding="tns:Application">
<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWorldService/"/>
</wsdl:port>
</wsdl:service>
<wsdl:service name="HelloWorldService">
<wsdl:port name="Application" binding="tns:Application">
<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWorldService/"/>
</wsdl:port>
</wsdl:service>
..

then I went to http://localhost:5000/LeapServiceWS/services/HelloWordService/?wsdl which specific service and I got another service description also.

...
<wsdl:service name="CustomerAccountListInq">
<wsdl:port name="Application" binding="tns:Application">
<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWordService/"/>
</wsdl:port>
</wsdl:service>
<wsdl:service name="HelloWorldService">
<wsdl:port name="Application" binding="tns:Application">
<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWordService/"/>
</wsdl:port>
</wsdl:service>
...

so I am not sure this is expected behavior of Soap ? not sure how to solve or I need to register with different wsgi app ?

plq commented 5 years ago

This can be considered a problem only if it violates the WSDL 1.1 spec. Do you think this is the case? Can you provide references?

Spyne's soap bits are more than a decade old at this point and it's very unlikely (yet of course possible) that there are issues in its WSDL generation logic.

jingz commented 5 years ago

here is my services details

from spyne import Iterable, Integer, Unicode, String, srpc, rpc
from spyne.service import ServiceBase
from flask import Response

class CustomerAccountListInq(ServiceBase):

    @rpc
    def response(ctx, name, times, _return=Iterable(Unicode)):
        for i in range(times):
            yield u'Hello, %s' % name

....

from spyne import Iterable, Integer, Unicode, String, srpc, rpc
from spyne.service import ServiceBase
from flask import Response

class HelloWorldService(ServiceBase):

    @rpc(Unicode, Integer, _returns=Iterable(Unicode))
    def hello(ctx, name, times):
        for i in range(times):
            yield u'Hello, %s' % name
plq commented 5 years ago

I did not ask for code, I asked for references to the WSDL spec that makes you think that the generated WSDL is invalid (or at least suboptimal)

jingz commented 5 years ago

here is my expected

...
<wsdl:service name="CustomerAccountListInq">
<wsdl:port name="Application" binding="tns:Application">
# this tag I expected
<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/CustomerAccountListInq/"/>
</wsdl:port>
</wsdl:service>
<wsdl:service name="HelloWorldService">
<wsdl:port name="Application" binding="tns:Application">
<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWordService/"/>
</wsdl:port>
</wsdl:service>
plq commented 5 years ago

For the third time: What makes you think that document excerpt is the right one? What does the WSDL spec say? How does spyne violate it?

jingz commented 5 years ago

I just think that the generated WSDL from spyne should not have duplicated in tag sdlsoap11:address with different services endpoint.

but I got the same endpoint for different services.

plq commented 5 years ago

I just think that the generated WSDL from spyne should not have duplicated in tag sdlsoap11:address with different services endpoint.

What makes you think that?

jingz commented 5 years ago

because It generated from different class and the different services should have the same endpoint.

jingz commented 5 years ago

If the services go into the same address what class will take response ?

jingz commented 5 years ago

In my final goal

I have existing WSDLs that would like to use Spyne mimic them. So I can return correct response for existing WSDL consumers.

jingz commented 5 years ago

please I identify my fault of reporting this. I am new for Soap.

Thanks

plq commented 5 years ago

If the services go into the same address what class will take response ?

the function name

plq commented 5 years ago

In my final goal

I have existing WSDLs that would like to use Spyne mimic them. So I can return correct response for existing WSDL consumers.

So what you really need the ability to override the address?

jingz commented 5 years ago

If the services go into the same address what class will take response ?

the function name

This mean that when registering. I should have single class to be registered and the services seprated by function_name something like



    return WsgiApplication(
               Application([SingleClassService], # <<-- single class service here
                   tns='spyne.example.flask',
                   in_protocol=Soap11(validator='lxml'),
                   out_protocol=Soap11()
           ))```
plq commented 5 years ago

You can have multiple services. Spyne makes sure across services that no duplicate function names are present in a given application.

Further questions should go into either stackoverflow or the mailing list.

jingz commented 5 years ago

In my final goal I have existing WSDLs that would like to use Spyne mimic them. So I can return correct response for existing WSDL consumers.

So what you really need the ability to override the address?

first I try to mimic this address endpoints by separate them in to different files and different classes then register them at one

<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWordService/"/>

and

<wsdlsoap11:address location="http://localhost:5000/LeapServiceWS/services/HelloWordService/"/>

I plan to mimic types by Spyne complexType next.