Whatever22
Whatever22

Reputation: 46

How to deploy SOAP-service on Apache + Gunicorn +Flask + Spyne

I need to deploy SOAP-service based on Spyne framework on Apache + Gunicorn + Flask.

I already have REST-service and it works fine.

My apache virtualHost configuration:

<VirtualHost *:80>
    ServerAdmin root@ubuntu

    ErrorLog ${APACHE_LOG_DIR}/flaskrest-error.log
    CustomLog ${APACHE_LOG_DIR}/flaskrest-access.log combined

    <Location />
        ProxyPass unix:/var/www/app_on_mod_wsgi/flaskrest.sock|http://localhost/
        ProxyPassReverse unix:/var/www/app_on_mod_wsgi/flaskrest.sock|http://localhost/
    </Location>

</VirtualHost>

Gunicorn's configuration file:

import multiprocessing

workers = multiprocessing.cpu_count() * 2 + 1
bind = 'unix:flaskrest.sock'
umask = 0o007
reload = True

#logging
accesslog = '-'
errorlog = '/var/log/gunicorn/error_log_archive'

I have my main python module where I initialize Flask and REST-service:

import soap_api # import my soap_api module

app = Flask(__name__) # init Flask app
api = Api(app) # init Flask_restful.Api

And I wrote soap_api.py module like in example:

import logging
import main_archive # my main module
from lxml import etree
from spyne import Application, rpc, ServiceBase, Integer, Unicode
from spyne import Iterable
from spyne.protocol.json import JsonDocument
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication
from wsgiref.simple_server import make_server


logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
formatter = logging.Formatter('%(asctime)s %(levelname)s - %(message)s')
file_handler = logging.FileHandler("/var/www/app_on_mod_wsgi/logs/" + 'info_logs.log')
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
logger.info("SOAP service successfuly started")

class HelloWorldService(ServiceBase):
    @rpc(Unicode, Integer, _returns=Iterable(Unicode))
    def say_hello(ctx, name, times):
        for i in range(times):
            yield 'Hello, %s' % name
            
application = Application([HelloWorldService],
    tns='spyne.examples.hello',
    in_protocol=JsonDocument(validator='soft'),
    out_protocol=Soap11()
)

wsgi_app = WsgiApplication(application)
server = make_server('0.0.0.0', 8000, wsgi_app) # OSError: [Errno 98] Address already in use
server.serve_forever()

So if I keep line server = make_server('0.0.0.0', 8000, wsgi_app), python returns OSError: [Errno 98] Address already in use. If I remove this line and the next one the server successfully run but I don't see wsdl file when I call localhost:80?wsdl, instead I get the main page (index) of my project.

The question is: what am I doing wrong and how I can deploy my SOAP-service and get access to wsdl file?

Thank you in advance!

Upvotes: 0

Views: 106

Answers (1)

Whatever22
Whatever22

Reputation: 46

Finally I have found the solution. The problem was the incorrect Apache2.4 configuration. I post the answer in case if someone else runs into the similar problem.

First of all I replaced Gunicorn with mod_wsgi because I understood better how to configure it.

Second step: I already had .wsgi file for my Flask app, so I create additional .wsgi file for the SOAP service:

import os
import sys

sys.path.append('/var/www/my_project/')
os.chdir('/var/www/my_project/')

from soap_api import app as application

Third step: creating the separate virtual host for SOAP service in Apache's .conf file:

Listen 81

# already existed main virtual host for the Flask app
<VirtualHost *:80>
    ServerName app-mod-wsgi

    WSGIDaemonProcess my_project python-home=/var/www/my_project/venv threads=5
    WSGIScriptAlias / /var/www/my_project/main.wsgi \
        process-group=my_project application-group=%{GLOBAL}

    <Directory /var/www/my_project>
        WSGIProcessGroup my_project
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

# This virtual host I added for the Spyne's SOAP service
<VirtualHost *:81>
    ServerName app-mod-wsgi-soap

    WSGIDaemonProcess my_project_soap python-home=/var/www/my_project/venv threads=2
    WSGIScriptAlias /soap /var/www/my_project/my_project_soap.wsgi \
        process-group=my_project_soap application-group=%{GLOBAL}

    <Directory /var/www/my_project>
        WSGIProcessGroup my_project_soap
        WSGIApplicationGroup %{GLOBAL}
        Require all granted
    </Directory>
</VirtualHost>

Final steps: restarting Apache web server (debian: systemctl restart apache2) and check that WSDL-file is accessible in browser by localhost:81/soap/?wsdl URL.

I will be glad if it turns out to be useful to someone.

Upvotes: 0

Related Questions