# soaplib_handler.py
from soaplib.wsgi_soap import SimpleWSGISoapApp
from soaplib.service import soapmethod
from soaplib.serializers import primitive as soap_types
from django.http import HttpResponse
class DjangoSoapApp(SimpleWSGISoapApp):
def __call__(self, request):
django_response = HttpResponse()
def start_response(status, headers):
status, reason = status.split(' ', 1)
django_response.status_code = int(status)
for header, value in headers:
django_response[header] = value
response = super(SimpleWSGISoapApp, self).__call__(request.META, start_response)
django_response.content = "\n".join(response)
return django_response
# views.py - sample view
from soaplib_handler import DjangoSoapApp, soapmethod, soap_types
class HelloWorldService(DjangoSoapApp):
__tns__ = 'http://my.namespace.org/soap/'
@soapmethod(soap_types.String, soap_types.Integer, _returns=soap_types.Array(soap_types.String))
def say_hello(self, name, times):
results = []
for i in range(0, times):
results.append('Hello, %s'%name)
return results
hello_world_service = HelloWorldService()
# urls.py
urlpatterns = patterns(
'',
(r'^hello_world/', 'foo.views.hello_world_service'),
(r'^hello_world/service.wsdl', 'foo.views.hello_world_service'),
)
Comments
This is a great example. Thanks!
#
This doesn't work for me because of problems with wsgi.input - have you actually successfully run this? The server just hangs for me trying to read the request from the client. I really wish it would work cause it's such a simple way of structuring this and soaplib looked pretty nice.
#
I've just started to use this (it works). I have 2 comments:
When you use super() you usually pass the class you are in (not the base class).
To automatically follow Django model relationships I have written a little
SoapDjangoArraytype; which will follow a reverse foreign key or m2m relationship:`` class SoapDjangoArray(soap_types.Array):
#
If you are having a problem with wsgi input, you may want to ensure your webserver is correctly serving WSGI. If you're using apache, you can follow the guide here to set up mod_wsgi: http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
I had a problem with it hanging as well, but I didn't have mod_wsgi set up correctly. This fixed the issue.
I'm having another issue though, from inside soaplib if I try to 'say_hello': File "/usr/lib/python2.5/site-packages/soaplib/soap.py", line 129, in from_soap if len(body.getchildren()): AttributeError: 'NoneType' object has no attribute 'getchildren'
#
In reference to my last post : this was a user error. I had set up my client as http://localhost:8000/hello_world/service.wsdl instead of http://localhost:8000/hello_world/. Works as intended now.
#
You guys are so close!
Ok, so the way I see it is that manage.py (calling manage.py runserver) is setup by default to execute the command (in /usr/lib/python/site-packages/django/core/management/commands) depending on your install runserver.py which seems to me is written with the RESTful pattern in mind. Here is a tutorial that describes how to write a custom command:
http://oebfare.com/blog/2008/nov/03/writing-custom-management-command/
Note that this tutorial demonstrates some interesting ways to use the WSGIServer provided by CherryPy.
Seeing as how we're working with SOAP, it would stand to reason to follow this pattern by implementing a new command and going from there. Could even go so far as to implement a command that supports both the CherryPy WSGI and the soaplib WSGI.
Personally I intend to write my own which initially I only care to have support for the soaplib wsgi but also the ability to allow each SOAP project app its ability to have a sudo-static instance or an instance of an object that remains intact so long as manage.py runsoapserver is running. Since this is the server instance.
Something I haven't thought of yet is whether or not the Django.core.handler.wsgihandler will suffice for use with the soaplib wsgi server. it would stand to reason that since I need to get a "sudo-static" instance of an object that remains as such so long as the WSGI server is running that I'll need to get that object to the appropriate views somehow. Not to mention the handler's filename is "wsgi.py" which kinda pushes anything I might want to write that's "wsgi" out of the way assuming I can't do that, any thoughts or suggestions to this approach I've come up with would be awesome!
Since requests are handled this way, "sudo-static" object instances would be pretty easy to conceal from views that they don't belong to. The idea being, the server gets a request, decides what app is being called on, then passes the instance that belongs to it. Some uses for this would be a way to have something like for example a thread pool that I can have control over via a SOAP API... something that runs while I'm away :)
... again any thoughts are welcome
#
@csar: I'm having the same problem. Do you have a solution yet?
#
Got it: change soaplib_handler into:
soaplib_handler.py
from soaplib.wsgi_soap import SimpleWSGISoapApp from soaplib.service import soapmethod from soaplib.serializers import primitive as soap_types import StringIO
from django.http import HttpResponse
class DumbStringIO(StringIO.StringIO): def read(self, n): return self.getvalue()
class DjangoSoapApp(SimpleWSGISoapApp):
#
It also hangs for me also,
emilianoheyns's patch works fine.
Thanks
#
The snippet works very well, the only problem I have is that the reply has no namespace defined :S
#
There is a bug in soaplib v8.1 The generated wsdl contains an error.
see: http://github.com/jkp/soaplib/issues/#issue/12
soapui & axis clients don't accept this wsdl
#
Just FYI the WSDL issue in soaplib v0.8.1 is fixed in the trunk so emilianoheyns version of soaplib_handler works like a charm.
#
Looks like optio got purchased, and the link no longer works. You can still get soaplib here though: http://github.com/jkp/soaplib
#
http://github.com/jkp/soaplib is not working now.
I tried http://github.com/arskom/soaplib alpha but it's not working with this code.
Where can I find a correct version of soaplib without that bug?
#
This version is for soaplib 0.9+
#
emilianoheyns patch saved me... one hint: instead of
you can simply use
#
I try to use this snippet, but get things like this:
>>> from soaplib.client import make_service_client
>>> from ws.hello.views import HelloWorldService
>>> client = make_service_client('http://localhost:6677/hello_world/', HelloWorldService())
>>> client.say_hello('foo',2)
Traceback (most recent call last): File "\<stdin>", line 1, in \<module> File "/opt/portal/python/lib/python2.7/site-packages/soaplib-0.8.1-py2.7.egg/soaplib/client.py", line 173, in call raise Exception(ex) Exception: 403 FORBIDDEN localhost 6677 /hello_world/
>>> client.server.say_hello('foo',2)
['Hello, foo', 'Hello, foo']
I use apache 2.2.16 + mod_wsgi 3.3, python 2.7.1
Any suggestions why client.say_hello('foo',2) is not working?
#
ealekseev I also got 403 forbidden.
I fixed it by turning off the CSRF middleware in the Django settings file.
#
Hi,
To avoid CSRF Error just add:
@csrf_exempt class HelloWorldService(DjangoSoapApp):
#
soapui is throwing
[HTML_REMOVED]say_helloFault[HTML_REMOVED] [HTML_REMOVED]'say_hello'[HTML_REMOVED] [HTML_REMOVED][HTML_REMOVED] [HTML_REMOVED]
whenever I try to invoke say_hello service, however it works well with suds client.
#
If you are willing to buy a house, you would have to receive the credit loans. Furthermore, my sister usually uses a term loan, which seems to be the most useful.
#
@csrf_exempt really work at soaplib 0.8.1 it work too
#
I have tried to get this snippet to work to no avail. Coded as is. I get a 405 from the web server. What I have left out?
#
In the disection of the 405, the message indiates that the GET is not allowed, but POST is.
#