# WebServer can be subclassed, but is not work for me.

**URL:** <https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266>\
**Category:** googlegroup\
**Created:** [July 29, 2018, 2:02pm UTC](https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266 "2018-07-29T14:02:17Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Bright\_Pan](https://avatars.discourse-cdn.com/v4/letter/b/898d66/32.png) [@Bright\_Pan](https://discourse.nameko.io/u/Bright_Pan)\
**Post date:** [July 29, 2018, 2:02pm UTC](https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266/1 "2018-07-29T14:02:17Z")

</div>

hi,  
i subclass WebServer for my socket server, but Error for me.

#!/usr/bin/env python  
# -\*- coding: utf-8 -\*-  
# Created by jason at 15/12/2017

from jinja2 import Template  
from nameko.extensions import DependencyProvider  
from nameko.timer import timer  
from nameko.web.server import WebServer as BaseWebServer  
from nameko.web.handlers import HttpRequestHandler as BaseHttpRequestHandler  
from nameko.web.websocket import WebSocketHubProvider, rpc  
from werkzeug.wrappers import Response

TEMPLATE = """  
\<!DOCTYPE html\>  
\<html\>  
\<head\>  
\<script  
src="[http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js](http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js)"\>\</script\>  
\<style\>  
#console{  
padding:5px;  
border:1px solid black;  
}  
#console p {  
margin:0;  
}  
.event {  
color:#999;  
}  
.warning{  
color: orange;  
}  
\</style\>  
\<title\>Nameko Websocket Test\</title\>  
\</head\>  
\<body\>  
\<div id="wrapper"\>  
\<h1\>Nameko Websocket Test\</h1\>  
\<button id="disconnect"\>Disconnect\</button\>  
\<div id="container"\>  
\<div id="console"\>  
\</div\>  
\</div\>  
\<script type="text/javascript"\>  
function connect(){  
var socket;  
var host = "ws://{{host}}:{{port}}/ws";  
try{  
var socket = new WebSocket(host);  
message('\<p class="event"\>Socket Status: '+socket.readyState);  
socket.onopen = function(){  
message('\<p class="event"\>Socket Status: '+socket.readyState+' (open)');  
subscribe();  
}  
socket.onmessage = function(msg){  
message('\<p class="message"\>Received: '+msg.data);  
}  
socket.onclose = function(){  
message('\<p class="event"\>Socket Status: '+socket.readyState+' (Closed)');  
}  
} catch(exception){  
message('\<p\>Error'+exception);  
}  
function subscribe() {  
try{  
var json\_msg = `{  
"method": "subscribe",  
"data": { "a": "1"}  
}`;  
socket.send(json\_msg);  
message('\<p class="event"\>Sent: '+text)  
} catch(exception){  
message('\<p class="warning"\>');  
}  
}  
function message(msg){  
$('#console').append(msg+'\</p\>');  
}  
$('#disconnect').click(function(){  
socket.close();  
});  
}  
$(document).ready(function() {  
if(!("WebSocket" in window)){  
$('\<p\>This demo requires browser websocket  
support\</p\>').appendTo('#container');  
return  
}  
connect();  
});  
\</script\>  
\</body\>  
\</html\>  
"""

class Config(DependencyProvider):  
def get\_dependency(self, worker\_ctx):  
return self.container.config

class ContainerIdentifier(DependencyProvider):  
def get\_dependency(self, worker\_ctx):  
return id(self.container)

class WebServer(BaseWebServer):

def context\_data\_from\_headers(self, request):  
context\_data = super().context\_data\_from\_headers(request)  
return context\_data

class HttpRequestHandler(BaseHttpRequestHandler):  
server = WebServer()

http = HttpRequestHandler.decorator

class WebsocketService(object):  
name = "websockets"

container\_id = ContainerIdentifier()  
websocket\_hub = WebSocketHubProvider()  
config = Config()

@http('GET', '/')  
def home(self, request):  
host = self.config.get('PUBLIC\_HOST', 'localhost')  
port = self.config.get('PUBLIC\_PORT', '8000')

payload = Template(TEMPLATE).render({'host': host, 'port': port})  
return Response(payload, content\_type="text/html")

@rpc  
def subscribe(self, socket\_id, a):  
self.websocket\_hub.subscribe(socket\_id, 'test\_channel')  
print(type(a))  
return 'subscribed to test\_channel' + a

@timer(10)  
def ping(self):  
self.websocket\_hub.broadcast('test\_channel', 'ping', {  
'value': "ping from {}".format(self.container\_id),  
})

the response is  
Not Found

The requested URL was not found on the server. If you entered the URL  
manually please check your spelling and try again.

if i use the base Webserver ,it work for me, Why?

modify

http = HttpRequestHandler.decorator

to

http = BaseHttpRequestHandler.decorator

the response is fine.  
Socket Status: 0

Socket Status: 1 (open)

Received: {"type": "event", "event": "connected", "data": {"socket\_id":  
"2cc07cde-d15e-487d-bd98-0cca1d254e8d"}}

Received: {"type": "result", "success": true, "data": "subscribed to  
test\_channel1", "correlation\_id": null}

Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
4380437064"}}

Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
4380437064"}}

Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
4380437064"}}

Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
4380437064"}}

---

<div class="post-metadata">

**Author:** ![David\_Szotten](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/david_szotten/32/6_2.png) [@David\_Szotten](https://discourse.nameko.io/u/David_Szotten)\
**Post date:** [July 29, 2018, 5:32pm UTC](https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266/2 "2018-07-29T17:32:02Z")

</div>

Hi,

The issue is that the `WebServer` is a `SharedExtension` (shared by eg http  
and websocket decorators). Unfortunately the docs are lacking in this area,  
but the way sharing is tracked at the moment is using the type of the  
shared extension (your issue is making me wondering if we need a new  
approach.  
[see [https://github.com/davidszotten/nameko/blob/d8dfdcb5d821403fcc8f3d1a2fd4eab6ceb2b99e/nameko/extensions.py#L120\](https://github.com/davidszotten/nameko/blob/d8dfdcb5d821403fcc8f3d1a2fd4eab6ceb2b99e/nameko/extensions.py#L120%5C)]

To make this work you need to override the sharing key on your subclass:

```auto
class WebServer(BaseWebServer):
    @property
    def sharing_key(self):
        return BaseWebServer

    def context_data_from_headers(self, request):
        ...

```

Best,  
David

> **···**
>
> On Sunday, 29 July 2018 15:02:17 UTC+1, Bright Pan wrote:
> 
> > hi,  
> > i subclass WebServer for my socket server, but Error for me.
> > 
> > #!/usr/bin/env python  
> > # -\*- coding: utf-8 -\*-  
> > # Created by jason at 15/12/2017
> > 
> > from jinja2 import Template  
> > from nameko.extensions import DependencyProvider  
> > from nameko.timer import timer  
> > from nameko.web.server import WebServer as BaseWebServer  
> > from nameko.web.handlers import HttpRequestHandler as  
> > BaseHttpRequestHandler  
> > from nameko.web.websocket import WebSocketHubProvider, rpc  
> > from werkzeug.wrappers import Response
> > 
> > TEMPLATE = """  
> > \<!DOCTYPE html\>  
> > \<html\>  
> > \<head\>  
> > \<script src="  
> > [http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt](http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt);  
> > \<style\>  
> > #console{  
> > padding:5px;  
> > border:1px solid black;  
> > }  
> > #console p {  
> > margin:0;  
> > }  
> > .event {  
> > color:#999;  
> > }  
> > .warning{  
> > color: orange;  
> > }  
> > \</style\>  
> > \<title\>Nameko Websocket Test\</title\>  
> > \</head\>  
> > \<body\>  
> > \<div id="wrapper"\>  
> > \<h1\>Nameko Websocket Test\</h1\>  
> > \<button id="disconnect"\>Disconnect\</button\>  
> > \<div id="container"\>  
> > \<div id="console"\>  
> > \</div\>  
> > \</div\>  
> > \<script type="text/javascript"\>  
> > function connect(){  
> > var socket;  
> > var host = "ws://{{host}}:{{port}}/ws";  
> > try{  
> > var socket = new WebSocket(host);  
> > message('\<p class="event"\>Socket Status: '+socket.readyState);  
> > socket.onopen = function(){  
> > message('\<p class="event"\>Socket Status: '+socket.readyState+' (open)');  
> > subscribe();  
> > }  
> > socket.onmessage = function(msg){  
> > message('\<p class="message"\>Received: '+msg.data);  
> > }  
> > socket.onclose = function(){  
> > message('\<p class="event"\>Socket Status: '+socket.readyState+' (Closed)');  
> > }  
> > } catch(exception){  
> > message('\<p\>Error'+exception);  
> > }  
> > function subscribe() {  
> > try{  
> > var json\_msg = `{  
> > "method": "subscribe",  
> > "data": { "a": "1"}  
> > }`;  
> > socket.send(json\_msg);  
> > message('\<p class="event"\>Sent: '+text)  
> > } catch(exception){  
> > message('\<p class="warning"\>');  
> > }  
> > }  
> > function message(msg){  
> > $('#console').append(msg+'\</p\>');  
> > }  
> > $('#disconnect').click(function(){  
> > socket.close();  
> > });  
> > }  
> > $(document).ready(function() {  
> > if(!("WebSocket" in window)){  
> > $('\<p\>This demo requires browser websocket  
> > support\</p\>').appendTo('#container');  
> > return  
> > }  
> > connect();  
> > });  
> > \</script\>  
> > \</body\>  
> > \</html\>  
> > """
> > 
> > class Config(DependencyProvider):  
> > def get\_dependency(self, worker\_ctx):  
> > return self.container.config
> > 
> > class ContainerIdentifier(DependencyProvider):  
> > def get\_dependency(self, worker\_ctx):  
> > return id(self.container)
> > 
> > class WebServer(BaseWebServer):
> > 
> > def context\_data\_from\_headers(self, request):  
> > context\_data = super().context\_data\_from\_headers(request)  
> > return context\_data
> > 
> > class HttpRequestHandler(BaseHttpRequestHandler):  
> > server = WebServer()
> > 
> > http = HttpRequestHandler.decorator
> > 
> > class WebsocketService(object):  
> > name = "websockets"
> > 
> > container\_id = ContainerIdentifier()  
> > websocket\_hub = WebSocketHubProvider()  
> > config = Config()
> > 
> > @http('GET', '/')  
> > def home(self, request):  
> > host = self.config.get('PUBLIC\_HOST', 'localhost')  
> > port = self.config.get('PUBLIC\_PORT', '8000')
> > 
> > payload = Template(TEMPLATE).render({'host': host, 'port': port})  
> > return Response(payload, content\_type="text/html")
> > 
> > @rpc  
> > def subscribe(self, socket\_id, a):  
> > self.websocket\_hub.subscribe(socket\_id, 'test\_channel')  
> > print(type(a))  
> > return 'subscribed to test\_channel' + a
> > 
> > @timer(10)  
> > def ping(self):  
> > self.websocket\_hub.broadcast('test\_channel', 'ping', {  
> > 'value': "ping from {}".format(self.container\_id),  
> > })
> > 
> > the response is  
> > Not Found
> > 
> > The requested URL was not found on the server. If you entered the URL  
> > manually please check your spelling and try again.
> > 
> > if i use the base Webserver ,it work for me, Why?
> > 
> > modify
> > 
> > http = HttpRequestHandler.decorator
> > 
> > to
> > 
> > http = BaseHttpRequestHandler.decorator
> > 
> > the response is fine.  
> > Socket Status: 0
> > 
> > Socket Status: 1 (open)
> > 
> > Received: {"type": "event", "event": "connected", "data": {"socket\_id":  
> > "2cc07cde-d15e-487d-bd98-0cca1d254e8d"}}
> > 
> > Received: {"type": "result", "success": true, "data": "subscribed to  
> > test\_channel1", "correlation\_id": null}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}

---

<div class="post-metadata">

**Author:** ![HADDLETON\_Robert\_W\_B](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/haddleton_robert_w_b/32/20_2.png) [@HADDLETON\_Robert\_W\_B](https://discourse.nameko.io/u/HADDLETON_Robert_W_B)\
**Post date:** [July 29, 2018, 2:06pm UTC](https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266/3 "2018-07-29T14:06:33Z")

</div>

Have you tried adding an \_\_init\_\_ method to your WebServer class and call the super().\_\_init\_\_() method for the superclass?

Bob

> **···**
>
> On Jul 29, 2018, at 09:02, Bright Pan \<[loststriker@gmail.com](mailto:loststriker@gmail.com)\<[mailto:loststriker@gmail.com](mailto:loststriker@gmail.com)\>\> wrote:
> 
> hi,  
> i subclass WebServer for my socket server, but Error for me.
> 
> #!/usr/bin/env python  
> # -\*- coding: utf-8 -\*-  
> # Created by jason at 15/12/2017
> 
> from jinja2 import Template  
> from nameko.extensions import DependencyProvider  
> from nameko.timer import timer  
> from nameko.web.server import WebServer as BaseWebServer  
> from nameko.web.handlers import HttpRequestHandler as BaseHttpRequestHandler  
> from nameko.web.websocket import WebSocketHubProvider, rpc  
> from werkzeug.wrappers import Response
> 
> TEMPLATE = """  
> \<!DOCTYPE html\>  
> \<html\>  
> \<head\>  
> \<script src="[http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js](http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js)"\>\</script\>  
> \<style\>  
> #console{  
> padding:5px;  
> border:1px solid black;  
> }  
> #console p {  
> margin:0;  
> }  
> .event {  
> color:#999;  
> }  
> .warning{  
> color: orange;  
> }  
> \</style\>  
> \<title\>Nameko Websocket Test\</title\>  
> \</head\>  
> \<body\>  
> \<div id="wrapper"\>  
> \<h1\>Nameko Websocket Test\</h1\>  
> \<button id="disconnect"\>Disconnect\</button\>  
> \<div id="container"\>  
> \<div id="console"\>  
> \</div\>  
> \</div\>  
> \<script type="text/javascript"\>  
> function connect(){  
> var socket;  
> var host = "ws://{{host}}:{{port}}/ws";  
> try{  
> var socket = new WebSocket(host);  
> message('\<p class="event"\>Socket Status: '+socket.readyState);  
> socket.onopen = function(){  
> message('\<p class="event"\>Socket Status: '+socket.readyState+' (open)');  
> subscribe();  
> }  
> socket.onmessage = function(msg){  
> message('\<p class="message"\>Received: '+msg.data);  
> }  
> socket.onclose = function(){  
> message('\<p class="event"\>Socket Status: '+socket.readyState+' (Closed)');  
> }  
> } catch(exception){  
> message('\<p\>Error'+exception);  
> }  
> function subscribe() {  
> try{  
> var json\_msg = `{  
> "method": "subscribe",  
> "data": { "a": "1"}  
> }`;  
> socket.send(json\_msg);  
> message('\<p class="event"\>Sent: '+text)  
> } catch(exception){  
> message('\<p class="warning"\>');  
> }  
> }  
> function message(msg){  
> $('#console').append(msg+'\</p\>');  
> }  
> $('#disconnect').click(function(){  
> socket.close();  
> });  
> }  
> $(document).ready(function() {  
> if(!("WebSocket" in window)){  
> $('\<p\>This demo requires browser websocket support\</p\>').appendTo('#container');  
> return  
> }  
> connect();  
> });  
> \</script\>  
> \</body\>  
> \</html\>  
> """
> 
> class Config(DependencyProvider):  
> def get\_dependency(self, worker\_ctx):  
> return self.container.config
> 
> class ContainerIdentifier(DependencyProvider):  
> def get\_dependency(self, worker\_ctx):  
> return id(self.container)
> 
> class WebServer(BaseWebServer):
> 
> def context\_data\_from\_headers(self, request):  
> context\_data = super().context\_data\_from\_headers(request)  
> return context\_data
> 
> class HttpRequestHandler(BaseHttpRequestHandler):  
> server = WebServer()
> 
> http = HttpRequestHandler.decorator
> 
> class WebsocketService(object):  
> name = "websockets"
> 
> container\_id = ContainerIdentifier()  
> websocket\_hub = WebSocketHubProvider()  
> config = Config()
> 
> @http('GET', '/')  
> def home(self, request):  
> host = self.config.get('PUBLIC\_HOST', 'localhost')  
> port = self.config.get('PUBLIC\_PORT', '8000')
> 
> payload = Template(TEMPLATE).render({'host': host, 'port': port})  
> return Response(payload, content\_type="text/html")
> 
> @rpc  
> def subscribe(self, socket\_id, a):  
> self.websocket\_hub.subscribe(socket\_id, 'test\_channel')  
> print(type(a))  
> return 'subscribed to test\_channel' + a
> 
> @timer(10)  
> def ping(self):  
> self.websocket\_hub.broadcast('test\_channel', 'ping', {  
> 'value': "ping from {}".format(self.container\_id),  
> })
> 
> the response is  
> Not Found
> 
> The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
> 
> if i use the base Webserver ,it work for me, Why?
> 
> modify
> 
> http = HttpRequestHandler.decorator
> 
> to
> 
> http = BaseHttpRequestHandler.decorator
> 
> the response is fine.
> 
> Socket Status: 0
> 
> Socket Status: 1 (open)
> 
> Received: {"type": "event", "event": "connected", "data": {"socket\_id": "2cc07cde-d15e-487d-bd98-0cca1d254e8d"}}
> 
> Received: {"type": "result", "success": true, "data": "subscribed to test\_channel1", "correlation\_id": null}
> 
> Received: {"type": "event", "event": "ping", "data": {"value": "ping from 4380437064"}}
> 
> Received: {"type": "event", "event": "ping", "data": {"value": "ping from 4380437064"}}
> 
> Received: {"type": "event", "event": "ping", "data": {"value": "ping from 4380437064"}}
> 
> Received: {"type": "event", "event": "ping", "data": {"value": "ping from 4380437064"}}
> 
> --  
> You received this message because you are subscribed to the Google Groups "nameko-dev" group.  
> To unsubscribe from this group and stop receiving emails from it, send an email to [nameko-dev+unsubscribe@googlegroups.com](mailto:nameko-dev+unsubscribe@googlegroups.com)\<[mailto:nameko-dev+unsubscribe@googlegroups.com](mailto:nameko-dev+unsubscribe@googlegroups.com)\>.  
> To post to this group, send email to [nameko-dev@googlegroups.com](mailto:nameko-dev@googlegroups.com)\<[mailto:nameko-dev@googlegroups.com](mailto:nameko-dev@googlegroups.com)\>.  
> To view this discussion on the web, visit [https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com](https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com)\<[https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com?utm\_medium=email&utm\_source=footer](https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com?utm_medium=email&utm_source=footer)\>.  
> For more options, visit [https://groups.google.com/d/optout](https://groups.google.com/d/optout).

---

<div class="post-metadata">

**Author:** ![Bright\_Pan](https://avatars.discourse-cdn.com/v4/letter/b/898d66/32.png) [@Bright\_Pan](https://discourse.nameko.io/u/Bright_Pan)\
**Post date:** [July 29, 2018, 2:47pm UTC](https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266/4 "2018-07-29T14:47:31Z")

</div>

hi, i try call super().\_\_init\_\_()

class WebServer(BaseWebServer):

def context\_data\_from\_headers(self, request):  
context\_data = super().context\_data\_from\_headers(request)  
return context\_data

def \_\_init\_\_(self):  
super().\_\_init\_\_()

class HttpRequestHandler(BaseHttpRequestHandler):  
server = WebServer()

def \_\_init\_\_(self, method, url, \*\*kwargs):  
super().\_\_init\_\_(method, url, \*\*kwargs)

but is doesn't work, the response is 404 Not Found.

在 2018年7月29日星期日 UTC+8下午10:06:38，Haddleton, Bob (Nokia - US/Naperville)写道：

> **···**
>
> > Have you tried adding an \_\_init\_\_ method to your WebServer class and call  
> > the super().\_\_init\_\_() method for the superclass?
> > 
> > Bob
> > 
> > On Jul 29, 2018, at 09:02, Bright Pan \<losts...@gmail.com \<javascript:\>\> \> wrote:
> > 
> > hi,  
> > i subclass WebServer for my socket server, but Error for me.
> > 
> > #!/usr/bin/env python  
> > # -\*- coding: utf-8 -\*-  
> > # Created by jason at 15/12/2017
> > 
> > from jinja2 import Template  
> > from nameko.extensions import DependencyProvider  
> > from nameko.timer import timer  
> > from nameko.web.server import WebServer as BaseWebServer  
> > from nameko.web.handlers import HttpRequestHandler as  
> > BaseHttpRequestHandler  
> > from nameko.web.websocket import WebSocketHubProvider, rpc  
> > from werkzeug.wrappers import Response
> > 
> > TEMPLATE = """  
> > \<!DOCTYPE html\>  
> > \<html\>  
> > \<head\>  
> > \<script src="  
> > [http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt](http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js&quot;&gt;&lt;/script&gt);  
> > \<style\>  
> > #console{  
> > padding:5px;  
> > border:1px solid black;  
> > }  
> > #console p {  
> > margin:0;  
> > }  
> > .event {  
> > color:#999;  
> > }  
> > .warning{  
> > color: orange;  
> > }  
> > \</style\>  
> > \<title\>Nameko Websocket Test\</title\>  
> > \</head\>  
> > \<body\>  
> > \<div id="wrapper"\>  
> > \<h1\>Nameko Websocket Test\</h1\>  
> > \<button id="disconnect"\>Disconnect\</button\>  
> > \<div id="container"\>  
> > \<div id="console"\>  
> > \</div\>  
> > \</div\>  
> > \<script type="text/javascript"\>  
> > function connect(){  
> > var socket;  
> > var host = "ws://{{host}}:{{port}}/ws";  
> > try{  
> > var socket = new WebSocket(host);  
> > message('\<p class="event"\>Socket Status: '+socket.readyState);  
> > socket.onopen = function(){  
> > message('\<p class="event"\>Socket Status: '+socket.readyState+' (open)');  
> > subscribe();  
> > }  
> > socket.onmessage = function(msg){  
> > message('\<p class="message"\>Received: '+msg.data);  
> > }  
> > socket.onclose = function(){  
> > message('\<p class="event"\>Socket Status: '+socket.readyState+' (Closed)');  
> > }  
> > } catch(exception){  
> > message('\<p\>Error'+exception);  
> > }  
> > function subscribe() {  
> > try{  
> > var json\_msg = `{  
> > "method": "subscribe",  
> > "data": { "a": "1"}  
> > }`;  
> > socket.send(json\_msg);  
> > message('\<p class="event"\>Sent: '+text)  
> > } catch(exception){  
> > message('\<p class="warning"\>');  
> > }  
> > }  
> > function message(msg){  
> > $('#console').append(msg+'\</p\>');  
> > }  
> > $('#disconnect').click(function(){  
> > socket.close();  
> > });  
> > }  
> > $(document).ready(function() {  
> > if(!("WebSocket" in window)){  
> > $('\<p\>This demo requires browser websocket  
> > support\</p\>').appendTo('#container');  
> > return  
> > }  
> > connect();  
> > });  
> > \</script\>  
> > \</body\>  
> > \</html\>  
> > """
> > 
> > class Config(DependencyProvider):  
> > def get\_dependency(self, worker\_ctx):  
> > return self.container.config
> > 
> > class ContainerIdentifier(DependencyProvider):  
> > def get\_dependency(self, worker\_ctx):  
> > return id(self.container)
> > 
> > class WebServer(BaseWebServer):
> > 
> > def context\_data\_from\_headers(self, request):  
> > context\_data = super().context\_data\_from\_headers(request)  
> > return context\_data
> > 
> > class HttpRequestHandler(BaseHttpRequestHandler):  
> > server = WebServer()
> > 
> > http = HttpRequestHandler.decorator
> > 
> > class WebsocketService(object):  
> > name = "websockets"
> > 
> > container\_id = ContainerIdentifier()  
> > websocket\_hub = WebSocketHubProvider()  
> > config = Config()
> > 
> > @http('GET', '/')  
> > def home(self, request):  
> > host = self.config.get('PUBLIC\_HOST', 'localhost')  
> > port = self.config.get('PUBLIC\_PORT', '8000')
> > 
> > payload = Template(TEMPLATE).render({'host': host, 'port': port})  
> > return Response(payload, content\_type="text/html")
> > 
> > @rpc  
> > def subscribe(self, socket\_id, a):  
> > self.websocket\_hub.subscribe(socket\_id, 'test\_channel')  
> > print(type(a))  
> > return 'subscribed to test\_channel' + a
> > 
> > @timer(10)  
> > def ping(self):  
> > self.websocket\_hub.broadcast('test\_channel', 'ping', {  
> > 'value': "ping from {}".format(self.container\_id),  
> > })
> > 
> > the response is  
> > Not Found
> > 
> > The requested URL was not found on the server. If you entered the URL  
> > manually please check your spelling and try again.
> > 
> > if i use the base Webserver ,it work for me, Why?
> > 
> > modify
> > 
> > http = HttpRequestHandler.decorator
> > 
> > to
> > 
> > http = BaseHttpRequestHandler.decorator
> > 
> > the response is fine.  
> > Socket Status: 0
> > 
> > Socket Status: 1 (open)
> > 
> > Received: {"type": "event", "event": "connected", "data": {"socket\_id":  
> > "2cc07cde-d15e-487d-bd98-0cca1d254e8d"}}
> > 
> > Received: {"type": "result", "success": true, "data": "subscribed to  
> > test\_channel1", "correlation\_id": null}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}
> > 
> > Received: {"type": "event", "event": "ping", "data": {"value": "ping from  
> > 4380437064"}}
> > 
> > --  
> > You received this message because you are subscribed to the Google Groups  
> > "nameko-dev" group.  
> > To unsubscribe from this group and stop receiving emails from it, send an  
> > email to nameko-dev+...@googlegroups.com \<javascript:\>.  
> > To post to this group, send email to name...@googlegroups.com  
> > \<javascript:\>.  
> > To view this discussion on the web, visit  
> > [https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com](https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com)  
> > \<[https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com?utm\_medium=email&utm\_source=footer&gt](https://groups.google.com/d/msgid/nameko-dev/30d1cfff-458b-4401-bb05-8617662d16ab%40googlegroups.com?utm_medium=email&utm_source=footer&gt);  
> > .  
> > For more options, visit [https://groups.google.com/d/optout\](https://groups.google.com/d/optout%5C).

---

<div class="post-metadata">

**Author:** ![David\_Szotten](https://yyz1.discourse-cdn.com/flex031/user_avatar/discourse.nameko.io/david_szotten/32/6_2.png) [@David\_Szotten](https://discourse.nameko.io/u/David_Szotten)\
**Post date:** [July 29, 2018, 7:03pm UTC](https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266/5 "2018-07-29T19:03:27Z")

</div>

to expand a little: what was happening was that your http and websocket rpc  
entrypoints were using different web servers. they were both bound to the  
same address but one would arbitrarily win and not know hot to route calls  
to entrypoints on the other server

we don't get a conflict when the second server binds to the same address  
because we (eventlet's default) set SO\_REUSEPORT. Not sure yet if that's a  
correct choice or not, but it's unfortunate in this case since there's no  
error

best,  
david

> **···**
>
> On Sunday, 29 July 2018 18:32:02 UTC+1, David Szotten wrote:
> 
> > Hi,
> > 
> > The issue is that the `WebServer` is a `SharedExtension` (shared by eg  
> > http and websocket decorators). Unfortunately the docs are lacking in this  
> > area, but the way sharing is tracked at the moment is using the type of the  
> > shared extension (your issue is making me wondering if we need a new  
> > approach.  
> > [see  
> > [https://github.com/davidszotten/nameko/blob/d8dfdcb5d821403fcc8f3d1a2fd4eab6ceb2b99e/nameko/extensions.py#L120](https://github.com/davidszotten/nameko/blob/d8dfdcb5d821403fcc8f3d1a2fd4eab6ceb2b99e/nameko/extensions.py#L120)  
> > ]
> > 
> > To make this work you need to override the sharing key on your subclass:
> > 
> > ```auto
> > class WebServer(BaseWebServer):
> > @property
> > def sharing_key(self):
> > return BaseWebServer
> > 
> > def context_data_from_headers(self, request):
> > ...
> > 
> > ```
> > 
> > Best,  
> > David
> > 
> > On Sunday, 29 July 2018 15:02:17 UTC+1, Bright Pan wrote:
> > 
> > > hi,  
> > > i subclass WebServer for my socket server, but Error for me.
> > > 
> > > #!/usr/bin/env python  
> > > # -\*- coding: utf-8 -\*-  
> > > # Created by jason at 15/12/2017
> > > 
> > > from jinja2 import Template  
> > > from nameko.extensions import DependencyProvider  
> > > from nameko.timer import timer  
> > > from nameko.web.server import WebServer as BaseWebServer  
> > > from nameko.web.handlers import HttpRequestHandler as  
> > > BaseHttpRequestHandler  
> > > from nameko.web.websocket import WebSocketHubProvider, rpc  
> > > from werkzeug.wrappers import Response
> > > 
> > > TEMPLATE = """  
> > > \<!DOCTYPE html\>  
> > > \<html\>  
> > > \<head\>  
> > > \<script src="  
> > > [http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js](http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js)  
> > > "\>\</script\>  
> > > \<style\>  
> > > #console{  
> > > padding:5px;  
> > > border:1px solid black;  
> > > }  
> > > #console p {  
> > > margin:0;  
> > > }  
> > > .event {  
> > > color:#999;  
> > > }  
> > > .warning{  
> > > color: orange;  
> > > }  
> > > \</style\>  
> > > \<title\>Nameko Websocket Test\</title\>  
> > > \</head\>  
> > > \<body\>  
> > > \<div id="wrapper"\>  
> > > \<h1\>Nameko Websocket Test\</h1\>  
> > > \<button id="disconnect"\>Disconnect\</button\>  
> > > \<div id="container"\>  
> > > \<div id="console"\>  
> > > \</div\>  
> > > \</div\>  
> > > \<script type="text/javascript"\>  
> > > function connect(){  
> > > var socket;  
> > > var host = "ws://{{host}}:{{port}}/ws";  
> > > try{  
> > > var socket = new WebSocket(host);  
> > > message('\<p class="event"\>Socket Status: '+socket.readyState);  
> > > socket.onopen = function(){  
> > > message('\<p class="event"\>Socket Status: '+socket.readyState+' (open)');  
> > > subscribe();  
> > > }  
> > > socket.onmessage = function(msg){  
> > > message('\<p class="message"\>Received: '+msg.data);  
> > > }  
> > > socket.onclose = function(){  
> > > message('\<p class="event"\>Socket Status: '+socket.readyState+' (Closed)');  
> > > }  
> > > } catch(exception){  
> > > message('\<p\>Error'+exception);  
> > > }  
> > > function subscribe() {  
> > > try{  
> > > var json\_msg = `{  
> > > "method": "subscribe",  
> > > "data": { "a": "1"}  
> > > }`;  
> > > socket.send(json\_msg);  
> > > message('\<p class="event"\>Sent: '+text)  
> > > } catch(exception){  
> > > message('\<p class="warning"\>');  
> > > }  
> > > }  
> > > function message(msg){  
> > > $('#console').append(msg+'\</p\>');  
> > > }  
> > > $('#disconnect').click(function(){  
> > > socket.close();  
> > > });  
> > > }  
> > > $(document).ready(function() {  
> > > if(!("WebSocket" in window)){  
> > > $('\<p\>This demo requires browser websocket  
> > > support\</p\>').appendTo('#container');  
> > > return  
> > > }  
> > > connect();  
> > > });  
> > > \</script\>  
> > > \</body\>  
> > > \</html\>  
> > > """
> > > 
> > > class Config(DependencyProvider):  
> > > def get\_dependency(self, worker\_ctx):  
> > > return self.container.config
> > > 
> > > class ContainerIdentifier(DependencyProvider):  
> > > def get\_dependency(self, worker\_ctx):  
> > > return id(self.container)
> > > 
> > > class WebServer(BaseWebServer):
> > > 
> > > def context\_data\_from\_headers(self, request):  
> > > context\_data = super().context\_data\_from\_headers(request)  
> > > return context\_data
> > > 
> > > class HttpRequestHandler(BaseHttpRequestHandler):  
> > > server = WebServer()
> > > 
> > > http = HttpRequestHandler.decorator
> > > 
> > > class WebsocketService(object):  
> > > name = "websockets"
> > > 
> > > container\_id = ContainerIdentifier()  
> > > websocket\_hub = WebSocketHubProvider()  
> > > config = Config()
> > > 
> > > @http('GET', '/')  
> > > def home(self, request):  
> > > host = self.config.get('PUBLIC\_HOST', 'localhost')  
> > > port = self.config.get('PUBLIC\_PORT', '8000')
> > > 
> > > payload = Template(TEMPLATE).render({'host': host, 'port': port})  
> > > return Response(payload, content\_type="text/html")
> > > 
> > > @rpc  
> > > def subscribe(self, socket\_id, a):  
> > > self.websocket\_hub.subscribe(socket\_id, 'test\_channel')  
> > > print(type(a))  
> > > return 'subscribed to test\_channel' + a
> > > 
> > > @timer(10)  
> > > def ping(self):  
> > > self.websocket\_hub.broadcast('test\_channel', 'ping', {  
> > > 'value': "ping from {}".format(self.container\_id),  
> > > })
> > > 
> > > the response is  
> > > Not Found
> > > 
> > > The requested URL was not found on the server. If you entered the URL  
> > > manually please check your spelling and try again.
> > > 
> > > if i use the base Webserver ,it work for me, Why?
> > > 
> > > modify
> > > 
> > > http = HttpRequestHandler.decorator
> > > 
> > > to
> > > 
> > > http = BaseHttpRequestHandler.decorator
> > > 
> > > the response is fine.  
> > > Socket Status: 0
> > > 
> > > Socket Status: 1 (open)
> > > 
> > > Received: {"type": "event", "event": "connected", "data": {"socket\_id":  
> > > "2cc07cde-d15e-487d-bd98-0cca1d254e8d"}}
> > > 
> > > Received: {"type": "result", "success": true, "data": "subscribed to  
> > > test\_channel1", "correlation\_id": null}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}

---

<div class="post-metadata">

**Author:** ![Bright\_Pan](https://avatars.discourse-cdn.com/v4/letter/b/898d66/32.png) [@Bright\_Pan](https://discourse.nameko.io/u/Bright_Pan)\
**Post date:** [July 30, 2018, 3:37am UTC](https://discourse.nameko.io/t/webserver-can-be-subclassed-but-is-not-work-for-me/266/6 "2018-07-30T03:37:40Z")

</div>

thanks, david

now, it works for me.

i agree with you advice, so i use http and websocket rpc entrypoints in  
different web server

best,  
bright

在 2018年7月30日星期一 UTC+8上午1:32:02，David Szotten写道：

> **···**
>
> > Hi,
> > 
> > The issue is that the `WebServer` is a `SharedExtension` (shared by eg  
> > http and websocket decorators). Unfortunately the docs are lacking in this  
> > area, but the way sharing is tracked at the moment is using the type of the  
> > shared extension (your issue is making me wondering if we need a new  
> > approach.  
> > [see  
> > [https://github.com/davidszotten/nameko/blob/d8dfdcb5d821403fcc8f3d1a2fd4eab6ceb2b99e/nameko/extensions.py#L120](https://github.com/davidszotten/nameko/blob/d8dfdcb5d821403fcc8f3d1a2fd4eab6ceb2b99e/nameko/extensions.py#L120)  
> > ]
> > 
> > To make this work you need to override the sharing key on your subclass:
> > 
> > ```auto
> > class WebServer(BaseWebServer):
> > @property
> > def sharing_key(self):
> > return BaseWebServer
> > 
> > def context_data_from_headers(self, request):
> > ...
> > 
> > ```
> > 
> > Best,  
> > David
> > 
> > On Sunday, 29 July 2018 15:02:17 UTC+1, Bright Pan wrote:
> > 
> > > hi,  
> > > i subclass WebServer for my socket server, but Error for me.
> > > 
> > > #!/usr/bin/env python  
> > > # -\*- coding: utf-8 -\*-  
> > > # Created by jason at 15/12/2017
> > > 
> > > from jinja2 import Template  
> > > from nameko.extensions import DependencyProvider  
> > > from nameko.timer import timer  
> > > from nameko.web.server import WebServer as BaseWebServer  
> > > from nameko.web.handlers import HttpRequestHandler as  
> > > BaseHttpRequestHandler  
> > > from nameko.web.websocket import WebSocketHubProvider, rpc  
> > > from werkzeug.wrappers import Response
> > > 
> > > TEMPLATE = """  
> > > \<!DOCTYPE html\>  
> > > \<html\>  
> > > \<head\>  
> > > \<script src="  
> > > [http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js](http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js)  
> > > "\>\</script\>  
> > > \<style\>  
> > > #console{  
> > > padding:5px;  
> > > border:1px solid black;  
> > > }  
> > > #console p {  
> > > margin:0;  
> > > }  
> > > .event {  
> > > color:#999;  
> > > }  
> > > .warning{  
> > > color: orange;  
> > > }  
> > > \</style\>  
> > > \<title\>Nameko Websocket Test\</title\>  
> > > \</head\>  
> > > \<body\>  
> > > \<div id="wrapper"\>  
> > > \<h1\>Nameko Websocket Test\</h1\>  
> > > \<button id="disconnect"\>Disconnect\</button\>  
> > > \<div id="container"\>  
> > > \<div id="console"\>  
> > > \</div\>  
> > > \</div\>  
> > > \<script type="text/javascript"\>  
> > > function connect(){  
> > > var socket;  
> > > var host = "ws://{{host}}:{{port}}/ws";  
> > > try{  
> > > var socket = new WebSocket(host);  
> > > message('\<p class="event"\>Socket Status: '+socket.readyState);  
> > > socket.onopen = function(){  
> > > message('\<p class="event"\>Socket Status: '+socket.readyState+' (open)');  
> > > subscribe();  
> > > }  
> > > socket.onmessage = function(msg){  
> > > message('\<p class="message"\>Received: '+msg.data);  
> > > }  
> > > socket.onclose = function(){  
> > > message('\<p class="event"\>Socket Status: '+socket.readyState+' (Closed)');  
> > > }  
> > > } catch(exception){  
> > > message('\<p\>Error'+exception);  
> > > }  
> > > function subscribe() {  
> > > try{  
> > > var json\_msg = `{  
> > > "method": "subscribe",  
> > > "data": { "a": "1"}  
> > > }`;  
> > > socket.send(json\_msg);  
> > > message('\<p class="event"\>Sent: '+text)  
> > > } catch(exception){  
> > > message('\<p class="warning"\>');  
> > > }  
> > > }  
> > > function message(msg){  
> > > $('#console').append(msg+'\</p\>');  
> > > }  
> > > $('#disconnect').click(function(){  
> > > socket.close();  
> > > });  
> > > }  
> > > $(document).ready(function() {  
> > > if(!("WebSocket" in window)){  
> > > $('\<p\>This demo requires browser websocket  
> > > support\</p\>').appendTo('#container');  
> > > return  
> > > }  
> > > connect();  
> > > });  
> > > \</script\>  
> > > \</body\>  
> > > \</html\>  
> > > """
> > > 
> > > class Config(DependencyProvider):  
> > > def get\_dependency(self, worker\_ctx):  
> > > return self.container.config
> > > 
> > > class ContainerIdentifier(DependencyProvider):  
> > > def get\_dependency(self, worker\_ctx):  
> > > return id(self.container)
> > > 
> > > class WebServer(BaseWebServer):
> > > 
> > > def context\_data\_from\_headers(self, request):  
> > > context\_data = super().context\_data\_from\_headers(request)  
> > > return context\_data
> > > 
> > > class HttpRequestHandler(BaseHttpRequestHandler):  
> > > server = WebServer()
> > > 
> > > http = HttpRequestHandler.decorator
> > > 
> > > class WebsocketService(object):  
> > > name = "websockets"
> > > 
> > > container\_id = ContainerIdentifier()  
> > > websocket\_hub = WebSocketHubProvider()  
> > > config = Config()
> > > 
> > > @http('GET', '/')  
> > > def home(self, request):  
> > > host = self.config.get('PUBLIC\_HOST', 'localhost')  
> > > port = self.config.get('PUBLIC\_PORT', '8000')
> > > 
> > > payload = Template(TEMPLATE).render({'host': host, 'port': port})  
> > > return Response(payload, content\_type="text/html")
> > > 
> > > @rpc  
> > > def subscribe(self, socket\_id, a):  
> > > self.websocket\_hub.subscribe(socket\_id, 'test\_channel')  
> > > print(type(a))  
> > > return 'subscribed to test\_channel' + a
> > > 
> > > @timer(10)  
> > > def ping(self):  
> > > self.websocket\_hub.broadcast('test\_channel', 'ping', {  
> > > 'value': "ping from {}".format(self.container\_id),  
> > > })
> > > 
> > > the response is  
> > > Not Found
> > > 
> > > The requested URL was not found on the server. If you entered the URL  
> > > manually please check your spelling and try again.
> > > 
> > > if i use the base Webserver ,it work for me, Why?
> > > 
> > > modify
> > > 
> > > http = HttpRequestHandler.decorator
> > > 
> > > to
> > > 
> > > http = BaseHttpRequestHandler.decorator
> > > 
> > > the response is fine.  
> > > Socket Status: 0
> > > 
> > > Socket Status: 1 (open)
> > > 
> > > Received: {"type": "event", "event": "connected", "data": {"socket\_id":  
> > > "2cc07cde-d15e-487d-bd98-0cca1d254e8d"}}
> > > 
> > > Received: {"type": "result", "success": true, "data": "subscribed to  
> > > test\_channel1", "correlation\_id": null}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}
> > > 
> > > Received: {"type": "event", "event": "ping", "data": {"value": "ping  
> > > from 4380437064"}}
