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


#1

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"></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"}}


#2

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]

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

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"></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"}}


#3

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>> 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"></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>.
To post to this group, send email to 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?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.


#4

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"></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+...@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?utm_medium=email&utm_source=footer>
.
For more options, visit https://groups.google.com/d/optout.


#5

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
]

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

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
"></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"}}


#6

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
]

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

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
"></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"}}