spyne icon indicating copy to clipboard operation
spyne copied to clipboard

header namespace gets lost with gunicorn/django

Open costela opened this issue 8 years ago • 1 comments

Hi there,

It seems the following code fails to parse in_header when used with gunicorn or DjangoApplication, but works with wsgiref:

class MyHeader(ComplexModel):
    myinfo = Unicode

class SomeService(ServiceBase):
    __in_header__ = MyHeader

    @rpc(Unicode)
    def MyMethod(ctx, mymethodparam):
        print("I got:", mymethodparam, ctx.in_header)


_app = Application([SomeService],
                   tns='myapp',
                   in_protocol=Soap11(validator='lxml'),
                   out_protocol=Soap11(),
                   )

application = Application([SomeService],
                          tns='myapp',
                          in_protocol=Soap11(validator='lxml'),
                          out_protocol=Soap11())

app = WsgiApplication(application)

if __name__ == '__main__':
    from wsgiref.simple_server import make_server
    server = make_server('0.0.0.0', 8000, app)
    server.serve_forever()

If you start it as a script, it returns:

('I got:', 'somevalue', MyHeader(myinfo='someinfo'))

However, starting the same script with gunicorn spyne_header_test:app (or wrapping it in a DjangoApplication) leads to:

('I got:', u'somevalue', None)

Both tests use this as POST content (found in this old stackoverflow question):

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
               xmlns:ns="http://resources.mydomain.com/soap/1.1"
               xmlns:ns0="myapp">
  <soap:Header>
    <ns0:MyHeader>       
      <ns0:myinfo>someinfo</ns0:myinfo>
    </ns0:MyHeader>       
  </soap:Header>
  <soap:Body>
    <ns0:MyMethod>
      <ns0:mymethodparam>somevalue</ns0:mymethodparam>
    </ns0:MyMethod>
  </soap:Body>
</soap:Envelope>

The debug log gives some clues: Working:

(...)
DEBUG:spyne.interface._base:  enumerating classes for method 'MyMethod'
DEBUG:spyne.interface._base:    adding class "<class 'spyne_header_test.MyHeader'>" for '{myapp}MyHeader'
(...)

Failing:

(...)
DEBUG:spyne.interface._base:  enumerating classes for method 'MyMethod'
DEBUG:spyne.interface._base:    adding class "<class 'spyne_header_test.MyHeader'>" for '{spyne_header_test}MyHeader'
(...)

Giving the derived ComplexModel an explicit __namespace__ attribute solves the issue.

Am I maybe missing something obvious?

PS.: this has been tested on py2 and py3, with the same results. All tests with 2.12.14 and current master.

costela avatar Aug 12 '17 09:08 costela

FWIW I dislike greenlet & friends.

looks like the namespace autofill doesn't work. it depends on name which depends on how the code is imported. Probably has to do with greenlet magic.

plq avatar Aug 14 '17 23:08 plq