WebSocket-for-Python icon indicating copy to clipboard operation
WebSocket-for-Python copied to clipboard

CherryPy, how to pass parameters into the websocket class

Open nicklasb opened this issue 10 years ago • 13 comments

Hi, I have a problem, and I cannot find this information anywhere in the documentation. I need to pass credentials into each WebSocket subclass instance, and I can find out how to.

It doesn't seem to be possible to read anything useful from the request.wsgi_environ being passed I am not sure I understand why the request itself isn't being passed instead? self.environ isn't being used anywhere by the WebSocket itself as far as I can see, so there should be no problems with sending the request instead.

Either that, or is there a way to cut in and be the one that instantiates my web socket descendant?

Because it would seem as an unnecessary round trip to having to resend the credentials again.

nicklasb avatar May 07 '15 20:05 nicklasb

Ok, so I can read the cherrypy.request.cookie['sessionToken'].value, but if there are many requests, it might be the next request? I suppose?

nicklasb avatar May 07 '15 22:05 nicklasb

Hi,

Passing the request wouldn't be portable across server providers, the WSGI environ is. Mind you, I don't like it either (never did).

I think it would indeed be more useful to everyone if one could pass an instance rather than a class but that needs some thinking.

Lawouach avatar May 11 '15 07:05 Lawouach

But it is the cherrypyserver code I am talking about, running websockets within CherryPy? It doesn't have to be portable at all, and only needs to have anything with wsgi to do if the developer explicitly wants it to? Also, the .environ variable is not used at all inside websocket.py. And if run like that, sure, then the wsgi_environ should be used. That doesn't make it wrong to pass the request?

The correct way in my view should be to always only pass the request, and if the developer wishes to use it in a wsgi context, he/she is free to use request.wsgi_environ instead.

However, to maintain backwards compatilbility, I would propose passing the request as another parameter and then deprecating the environ-parameter and self.environ.

As it is now, no context can be pass from before the upgrade, and in my view, for no apparent reason.

nicklasb avatar May 11 '15 08:05 nicklasb

I agree with you that it is not used from within the WebSocket class, it was purely exposed for users to have access to it. If I passed the request on, it wouldn't be any more used than the environ dictionary (I mean from the ws4py code's point of view).

By portable, I meant that the WebSocket interface is shared among all backend servers so it felt appropriate to inject the WSGI environ.

With that said, several people have asked to get access to the request over the time, so I can appreciate we ought to do so.

In the meanwhile, do remember that cherrypy is thread-aware, so you can simple do:

request = cherrypy.request

from your websocket subclass. That will do to reach the current request safely.

Lawouach avatar May 11 '15 08:05 Lawouach

Sorry, I now I saw that the other server implementations uses self.environ. I would then recommend, to simply add a request-parameter. It doesn't look worse than the environ-parameter.

Well yes, I am doing that during development, but it is not safe enough for production, I am afraid. I never trust global scopes, especially thread scopes like that, have been burned far too many a time by changes in the underlying libraries, race conditions and other stuff.

nicklasb avatar May 11 '15 08:05 nicklasb

Fair enough.

Note that CherryPy is designed around global scopes :)

I will think about it.

Lawouach avatar May 11 '15 08:05 Lawouach

I know. And don't get me wrong, I like CherryPy a lot, but that is probably the worst aspect of it, it has caused problems before, makes code less clear and testing unnecessarily ugly.

I only use cherrypy.request when I am inside the actual response and it always irritates me a little. Have gotten around that by moving all handling of that into decorators, so I don't have to see it. :-)

nicklasb avatar May 11 '15 08:05 nicklasb

I can appreciate that :)

Lawouach avatar May 11 '15 08:05 Lawouach

Back to this one. I had forgotten about this but the websocket instance is available to your websocket page handler. You could therefore add any attributes you wish at that time:

@cherrypy.expose
def ws(self):
      cherrypy.log("Handler created: %s" % repr(cherrypy.request.ws_handler))

The ws_handler is your instance. Would that be good enough? Though, at that point, the opened() handler has been called on the websocket instance.

Lawouach avatar Jul 27 '15 19:07 Lawouach

Ok, that might make the code a bit cleaner. It is still thread-global though. Good to know.

nicklasb avatar Jul 27 '15 20:07 nicklasb

Well, the handler is actually detached from the request object after the page handler has returned. In other words, once that cherrypy handler has returned, the websocket handler is not associated to it any longer, instead it is registered to the ws4py manager. It's merely provided to you at that stage so that you can play around with the instance.

Lawouach avatar Jul 27 '15 20:07 Lawouach

Ok, thanks for the information.

nicklasb avatar Jul 27 '15 20:07 nicklasb