(Migrated) aborting service with a 401 and hot deploying shared code

(This message has been automatically imported from the retired mailing list)

Hello,

I have two questions, but first I’ll illustrate my use case:

Every service we develop checks the client’s authentication before doing
actual work, in order to do this I created a base class MyService which
inherits from Service and implements /before_handle()/, all our services
inherit from MyService.
/before_handle()/ just checks the authentication (the client sends its
credentials).

1)
Now in case the authentication fails in /before_handle()/ I want to
return a 401 status code and the string “Unauthorized” without running
the service’s /handle()/
method. I could achieve this by replacing
self.handle with another function that just does this, but that would be
a dirty method-hijack-hack. Is there any better way to achieve this?

2)
My second question is the following:
Since all my services inherit from MyService, I put the module
containing MyService in zato_extra_path, unfortunately I cannot
hot-deploy it like this. Is there a way to hot-deploy code that will be
imported by services
?

Cheers!

On 29/04/15 13:06, Andrea Peter wrote:

Now in case the authentication fails in /before_handle()/ I want to
return a 401 status code and the string “Unauthorized” without running
the service’s /handle()/
method. I could achieve this by replacing
self.handle with another function that just does this, but that would be
a dirty method-hijack-hack. Is there any better way to achieve this?

This sounds like a good use-case for self.environ, e.g.:

def before_handle(self):
self.environ[‘auth_ok’] = confirm_auth()

def handle(self):
if not self.environ[‘auth_ok’]:
self.response.status_code = httplib.UNAUTHORIZED
return

or:

def before_handle(self):
auth_ok = self.environ[‘auth_ok’] = confirm_auth()
if not auth_ok:
self.response.status_code = httplib.UNAUTHORIZED

def handle(self):
if not self.environ[‘auth_ok’]:
return

Is there a way to hot-deploy code that will be imported by services?

No, this is not possible. Hot-deployment is for services only. It’s a
popular request to have it work with other types of code as well though
and I’m sure that something will be added but today - no, this is not
doable.

Am 29.04.2015 um 16:16 schrieb Dariusz Suchojad:

Is there a way to hot-deploy code that will be imported by services?
=20
No, this is not possible. Hot-deployment is for services only. It’s a
popular request to have it work with other types of code as well though=

and I’m sure that something will be added but today - no, this is not
doable.

Actually, there is a hackish way to do this: you can construct a module
dynamically in the Python file, which you hot-deploy. If tested this
once in Zato 1.1 and at least there it worked, but it’s hack.

It goes like this:

import imp
import sys

def testfunc(a, b):
    return a ** b

# Create the module object
mod =3D imp.new_module('mydynlib')

# populate module namespace
for name in ('testfunc', ...):
    mod.__dict__[name] =3D locals()[name]

# make it available globally for import
sys.modules['mydynlib'] =3D mod

Then in your service module you can do:

from mydynlib import testfunc

Chris

On 29/04/15 16:34, Andrea Peter wrote:

I would like to propose a mechanism which allows to abort a service call
and allows to specify a status code in before_handle(), maybe with the
return value or by raising an exception.
Wouldn’t this be practical?

Indeed it would be, thanks for suggesting it!

Both return values and exceptions make sense though I’m slightly in
favour of the former seeing as it would be more in line with what we
already have.

On the other hand, it would be convenient to simply raise
Unathorized(msg) and have Zato understand how to turn it into a
channel’s specific message and headers.