gRPC Node Js client: "Method not found" - python

I have a gRPC server implemented in python and I am calling an RPC from NodeJS but it gives an error "Method not found". When I call using the python client, the request is successful.
stream_csv.proto
syntax = "proto3";
package csv;
service Stream {
rpc csvToObject(CSVDataRequest) returns (stream CSVDataResponse) {};
rpc sayHello(HelloRequest) returns (HelloReply);
}
message CSVDataRequest{
string url = 1;
enum Protocol {
HTTP = 0;
HTTPS = 1;
FTP = 2;
SFTP = 3;
}
Protocol protocol = 2;
}
message CSVDataResponse{
repeated string row = 1;
}
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
client.js
var PROTO_PATH = '../stream_csv.proto';
var grpc = require('grpc');
var protoLoader = require('#grpc/proto-loader');
var packageDefinition = protoLoader.loadSync(
PROTO_PATH,
{keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true
});
var proto = grpc.loadPackageDefinition(packageDefinition).csv;
function main() {
var client = new proto.Stream('localhost:5000',
grpc.credentials.createInsecure());
var user;
if (process.argv.length >= 3) {
user = process.argv[2];
} else {
user = 'world';
}
console.log(user);
client.sayHello({name: user}, function(err, response) {
console.log(err);
});
}
main();
server.py
import grpc
import stream_csv_pb2
import urllib.request
from urllib.error import HTTPError, URLError
from concurrent import futures
class DataService:
def csv_to_object(self, request, context):
url = request.url
protocol = stream_csv_pb2.CSVDataRequest.Protocol.Name(
request.protocol)
fetch_url = protocol.lower() + "://"+url
try:
with urllib.request.urlopen(fetch_url) as data:
for line in data:
decoded_line = line.decode()
val = decoded_line.split(',')
print(val)
print("Data send")
yield stream_csv_pb2.CSVDataResponse(row=val)
print("Sending finished!")
except URLError as e:
context.abort(grpc.StatusCode.UNKNOWN,
'Randomly injected failure.')
# return stream_csv_pb2.CSVDataResponse(row=[], error=e.reason)
def SayHello(self, request, context):
name = request.name
print(name)
return stream_csv_pb2.HelloReply(message='Hello %s' % (name))
def add_DataServicer_to_server(servicer, server):
rpc_method_handlers = {
'CSVToObject': grpc.unary_stream_rpc_method_handler(
servicer.csv_to_object,
request_deserializer=stream_csv_pb2.CSVDataRequest.FromString,
response_serializer=stream_csv_pb2.CSVDataResponse.SerializeToString,
),
'SayHello': grpc.unary_unary_rpc_method_handler(
servicer.SayHello,
request_deserializer=stream_csv_pb2.HelloRequest.FromString,
response_serializer=stream_csv_pb2.HelloReply.SerializeToString,
)
}
generic_handler = grpc.method_handlers_generic_handler(
'stream_csv.Stream', rpc_method_handlers)
server.add_generic_rpc_handlers((generic_handler,))
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
add_DataServicer_to_server(DataService(), server)
server.add_insecure_port('[::]:5000')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
Error
Error: 12 UNIMPLEMENTED: Method not found!
at Object.exports.createStatusError (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/common.js:91:15)
at Object.onReceiveStatus (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:1209:28)
at InterceptingListener._callNext (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:568:42)
at InterceptingListener.onReceiveStatus (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:618:8)
at callback (/home/shantam/Documents/grepsr/client/node_modules/grpc/src/client_interceptors.js:847:24) {
code: 12,
metadata: Metadata { _internal_repr: {}, flags: 0 },
details: 'Method not found!'
}

I wrote a simpler variant of your Python (and Golang) server implementations.
Both work with your Node.JS client as-is.
I think perhaps your issue is as simple as needing to name the rpc sayHello (rather than SayHello).
from concurrent import futures
import logging
import grpc
import stream_csv_pb2
import stream_csv_pb2_grpc
class Stream(stream_csv_pb2_grpc.StreamServicer):
def sayHello(self, request, context):
logging.info("[sayHello]")
return stream_csv_pb2.HelloReply(message='Hello, %s!' % request.name)
def serve():
logging.info("[serve]")
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
stream_csv_pb2_grpc.add_StreamServicer_to_server(Stream(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
And:
node client.js
Greeting: Hello, Freddie!
null
Conventionally (!) gRPC follows Protobufs style guide of CamelCasing service, rpc and message names and using underscores elsewhere see Style Guide. When protoc compiles, the results don't always match perfectly (e.g. Python's CamelCased functions rather than lowercased with underscores).
Conventionally, your proto would be:
service Stream {
rpc CsvToObject(CSVDataRequest) returns (stream CSVDataResponse) {};
rpc SayHello(HelloRequest) returns (HelloReply);
}
...and then the Python generated function would be (!) SayHello too.

Related

Unity3D UnityWebRequest.Put Method Slow Response

Let me preface this by saying I have seen similar posts like this on this site as well as other sites, but have not seen a clear solution to the problem yet. I have created a simple python server with do_GET and do_PUT methods, and corresponding Unity C# code with GetRequest() and PutRequest() methods. I have already tested the Get methods and they run smoothly. On the other hand, the client-side (Unity C#) PutRequest() method only yields once every second or so (which seems unreasonably slow). My frame rate is sitting around 150-160 fps. I thought it would be considerably faster considering I copied the very simple Upload() method from the Unity documentation at https://docs.unity3d.com/ScriptReference/Networking.UnityWebRequest.Put.html
Below is the client-side Unity C# code I am currently using:
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
public class WebRequest0 : MonoBehaviour
{
public Transform client;
private string[] pos;
void Start()
{
StartCoroutine(GetRequest());
StartCoroutine(PutRequest());
}
private IEnumerator GetRequest()
{
while (true)
{
UnityWebRequest www = UnityWebRequest.Get("http://localhost");
yield return www.SendWebRequest();
string coordinates = www.downloadHandler.text;
pos = coordinates.Split(',');
if (client && pos.Length > 0)
{
client.position = new Vector3(client.position.x, float.Parse(pos[0]), client.position.z);
}
Debug.Log("Get Request happening");
}
}
private IEnumerator PutRequest()
{
while (true)
{
//What data is being sent
byte[] data = System.Text.Encoding.UTF8.GetBytes("This data is being sent to the server");
using (UnityWebRequest www = UnityWebRequest.Put("http://localhost", data))
{
yield return www.SendWebRequest();
//yield return new WaitForSeconds(0);
if (www.result != UnityWebRequest.Result.Success)
{
Debug.Log("Error sending data to server --- " + www.error);
}
else
{
Debug.Log("Information was successfully sent to server");
}
}
Debug.Log("Put Request happening");
}
}
}
And below is my python server code:
from http.server import BaseHTTPRequestHandler, HTTPServer
hostName = "localhost"
serverPort = 80
positionY = 0.0
deltaPosition = 0.1
class MyServer(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def do_GET(self):
self._set_headers()
global positionY
global deltaPosition
positionYStr = str(positionY)
self.wfile.write(bytes(positionYStr, "utf-8"))
print("sending " + positionYStr + "\n")
positionY += deltaPosition
if positionY > 4 or positionY < -4:
deltaPosition *= -1.0
def do_PUT(self):
self._set_headers()
content_len = int(self.headers.get('content-length'))
put_body = self.rfile.read(content_len)
print(put_body.decode(encoding="ascii", errors="ignore"))
self.wfile.write(bytes("received post request:<br>{}".format(put_body), "utf-8"))
if __name__ == "__main__":
webServer = HTTPServer((hostName, serverPort), MyServer)
print("Server started http://%s:%s" % (hostName, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server stopped.")
To be clear, I am currently not receiving any errors. However, whenever I use yield return new WaitForSeconds(0); instead of yield return www.SendWebRequest(); in the PutRequest() method, the program runs smoothly, making me believe there is something wrong with the yield return www.SendWebRequest();
Hopefully I have clarified my problem well enough. I appreciate any and all help!

Apple Watch stops transmitting gyroscope/accelometer data after a few minutes for unknown reason

I have created a watchOS app that fetches data from the accelerometer and gyroscope and sends it to a socket server. The server just prints the data on the console. The socket server is made in python. My app works fine for a few minutes but then stops working.
I tested by creating an iPhone app and it's working fine. The problem is with the apple watch app.
Can someone help me with this? I don't understand what's going on.
server.py
import socket
localIP = ""
localPort = 20001
bufferSize = 10240
msgFromServer = "Hello UDP Client"
bytesToSend = str.encode(msgFromServer)
# Create a datagram socket
UDPServerSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
# Bind to address and ip
UDPServerSocket.bind((localIP, localPort))
print("UDP server up and listening")
# Listen for incoming datagrams
while(True):
bytesAddressPair = UDPServerSocket.recvfrom(bufferSize)
message = bytesAddressPair[0]
address = bytesAddressPair[1]
clientMsg = "Message from Client:{}".format(message)
clientIP = "Client IP Address:{}".format(address)
print(clientMsg)
print(clientIP)
# Sending a reply to client
UDPServerSocket.sendto(bytesToSend, address)
InterfaceController.swift
#IBOutlet weak var stopButton: WKInterfaceButton!
#IBOutlet weak var startButton: WKInterfaceButton!
var session = WKExtendedRuntimeSession()
private var host: NWEndpoint.Host = "172.16.105.162"
private var port: NWEndpoint.Port = 20001
private var updateTimeInterval: Double = 1/60
override func awake(withContext context: Any?) {
// Configure interface objects here.
// startButton.setHidden(false)
startButton.setEnabled(true) // // stopButton.setHidden(true)
stopButton.setEnabled(false)
setUPSession()
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
print("ACTIVATE")
}
override func didDeactivate() {
// This method is called when watch view controller is no longer visible
print("DEACTIVATE")
}
#IBAction func actionStop() { // startButton.setHidden(false)
startButton.setEnabled(true) // // stopButton.setHidden(true)
stopButton.setEnabled(false)
self.stopSession()
// MotionDatafetcher.shared.startSession() //stopWorkoutSEssion() //stopFetch()
}
#IBAction func actionStart() { // startButton.setHidden(true)
startButton.setEnabled(false) // // stopButton.setHidden(false)
stopButton.setEnabled(true)
self.startSession()
// MotionDatafetcher.shared.startFetch()
//MotionDatafetcher.shared.stopSession() //startWorkoutSession() //startDeviceMotionFetch()
}
}
extension InterfaceController : WKExtendedRuntimeSessionDelegate{
func setUPSession() {
// Create the session object.
session = WKExtendedRuntimeSession()
// Assign the delegate.
session.delegate = self
MySocketManager.shared.setUpConn()
}
func startSession() {
session.start()
MySocketManager.shared.connectToUDP(host, port)
MotionDatafetcher.shared.startDeviceMotionFetch(updateTimeInterval)
}
func stopSession() {
session.invalidate()
MotionDatafetcher.shared.stopFetch()
MySocketManager.shared.cancelConnToUDP()
}
func extendedRuntimeSession(_ extendedRuntimeSession: WKExtendedRuntimeSession, didInvalidateWith reason: WKExtendedRuntimeSessionInvalidationReason, error: Error?) {
}
func extendedRuntimeSessionDidStart(_ extendedRuntimeSession: WKExtendedRuntimeSession) {
}
func extendedRuntimeSessionWillExpire(_ extendedRuntimeSession: WKExtendedRuntimeSession) {
self.stopSession()
}
}

Transfer data from python to nodejs using requests and socket

I try to send data from a simple python programm to a node server. But no success. That's why I ask some help.
My simple python :
import requests
SIGNUP_URL = 'http://localhost:8000/timer'
def submit_form():
obj = {name:'whateever'}
resp = requests.post(SIGNUP_URL, data = obj)
if __name__ == '__main__':
submit_form()
my nodejs (light, I remove not concern lines) :
var http = require('http');
var express = require('express');
var app = express();
app.get('/', function (request, response) {
response.sendFile(__dirname + '/public/index.html');
});
var server = http.createServer(app);
var io = require('socket.io')(server);
const bodyParser = require('body-parser');
const path = require('path');
const {execFile, exec, spawn} = require ('child_process');
app.use(express.static('public'));
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/timer', function(req, res){
res.sendFile(__dirname + '/public/status.html');
var test = "test";
var data = req.body;
var info = data.name;
io.emit('messageFromServer', { info });
console.log('info')
});
server.listen(8000, console.log("listening to port 8000"));
So, when I execute my python I want transfering to the server the data "name : whatever", then I want the server write the data into the console (to be sure the data is well sent), and I all is ok, I want to emit this data to my html page...
Thanks for helping me.
The answer :
python code :
import requests
SIGNUP_URL = 'http://localhost:8000/timer'
def submit_form():
obj = {'name':'whateever'}
resp = requests.post(SIGNUP_URL, data = obj)
if __name__ == '__main__':
submit_form()
nodejs code :
app.post('/timer', function(req, res){
res.sendFile(__dirname + '/public/status.html');
var info= req.body;
io.emit('messageFromServer', info);
console.log(info)
});
It works.

How can i rewrite the subscriber in RXJS with rxpy

I don't know how to change the Subscriber of RXJS to the form of Python, which is not effective.
Typescript USES the GRPC stream form and plugs in the RXJS Subscriber. Python doesn't know how to write it.
RXJS code
import * as grpc from 'grpc';
import { Observable, Subscriber } from 'rxjs';
export function subscribeToWorkspace(
input: WorkspaceSubscriptionInput,
): Observable<EventPayload> {
return new Observable<EventPayload>((observer: Subscriber<EventPayload>) => {
log(`opening stream for subscription ${input.toString()}`);
const stream: grpc.ClientReadableStream<EventPayload> =
client.subscribeToWorkspace(input, metadata);
stream.on('data', (eventPayload: EventPayload) => {
if (observer.closed) {
return;
}
observer.next(eventPayload);
});
stream.on('error', (err) => observer.error(err));
stream.on('end', () => observer.complete());
return () => {
log(`closing stream for subscription ${input.toString()}`);
stream.cancel();
};
});
}
Python code
from rx import of
def subscribe_to_workspace(cls, subsinput: WorkspaceSubscriptionInput) -> Observable:
return of(cls.client.SubscribeToWorkspace(subsinput))
Rxpy does not work. What should Python do
# pip install rx
from rx import Observable, Observer
def get_strings(observer):
observer.on_next("Ram")
observer.on_next("Mohan")
observer.on_next("Shyam")
observer.on_completed()
class PrintObserver(Observer):
def on_next(self, value):
print("Received {0}".format(value))
def on_completed(self):
print("Finished")
def on_error(self, error):
print("Error: {0}".format(error))
source = Observable.create(get_strings)
source.subscribe(PrintObserver())

Tchannel server code not working. (Python and nodejs)

I have just started learning Uber's Tchannel. I'm trying to run the code from tchannel documentation in python and nodejs. In both the cases I am not able to connect the client to the server.
This is how my code looks like in nodejs, which i followed from http://tchannel-node.readthedocs.org/en/latest/GUIDE/:
var TChannel = require('tchannel');
var myLocalIp = require('my-local-ip');
var rootChannel = TChannel();
rootChannel.listen(0,myLocalIp());
rootChannel.on('listening', function onListen() {
console.log('got a server', rootChannel.address());
});
var TChannelThrift = rootChannel.TChannelAsThrift;
var keyChan = rootChannel.makeSubChannel({
serviceName: process.env.USER || 'keyvalue'
});
var fs = require('fs');
var keyThrift = TChannelThrift({
source: fs.readFileSync('./keyvalue.thrift', 'utf8')
});
var ctx = {
store: {}
};
keyThrift.register(keyChan, 'KeyValue::get_v1', ctx, get);
keyThrift.register(keyChan, 'KeyValue::put_v1', ctx, put);
function get(context, req, head, body, cb) {
cb(null, {
ok: true,
body: {
value: context.store[body.key]
}
});
}
function put(context, req, head, body, cb) {
context.store[body.key] = body.value;
cb(null, {
ok: true,
body: null
});
}
When i run this code i get this error:
node sever.js
assert.js:93
throw new assert.AssertionError({
^
AssertionError: every field must be marked optional, required, or have a default value on GetResult including "value" in strict mode
at ThriftStruct.link (/home/bhaskar/node_modules/thriftrw/struct.js:154:13)
at Thrift.link (/home/bhaskar/node_modules/thriftrw/thrift.js:199:32)
at new Thrift (/home/bhaskar/node_modules/thriftrw/thrift.js:69:10)
at new TChannelAsThrift (/home/bhaskar/node_modules/tchannel/as/thrift.js:46:17)
at TChannelAsThrift (/home/bhaskar/node_modules/tchannel/as/thrift.js:38:16)
at Object.<anonymous> (/home/bhaskar/uber/tchannel/thrift/sever.js:16:17)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
Similar, I have also tried the same thing in python by following http://tchannel.readthedocs.org/projects/tchannel-python/en/latest/guide.html link.
code in python looks like this:
from __future__ import absolute_import
from tornado import ioloop
from tornado import gen
from service import KeyValue
from tchannel import TChannel
tchannel = TChannel('keyvalue-server')
values={}
#tchannel.thrift.register(KeyValue)
def getValue(request):
key = request.body.key
value = values.get(key)
if value is None:
raise KeyValue.NotFoundError(key)
return value
#tchannel.thrift.register(KeyValue)
def setValue(request):
key = request.body.key
value = request.body.value
values[key] = value
def run():
tchannel.listen()
print('Listening on %s' % tchannel.hostport)
if __name__ == '__main__':
run()
ioloop.IOLoop.current().start()
when i run this with python server.py command i get ` Listening on my-local-ip:58092
`
but when i try to connect it with the client using tcurl as:
tcurl -p localhost:58092 -t ~/keyvalue/thrift/service.thrift service KeyValue::setValue -3 '{"key": "hello", "value": "world"}'
I get this:
assert.js:93
throw new assert.AssertionError({
^
AssertionError: every field must be marked optional, required, or have a default value on NotFoundError including "key" in strict mode
at ThriftException.link (/usr/lib/node_modules/tcurl/node_modules/thriftrw/struct.js:154:13)
at Thrift.link (/usr/lib/node_modules/tcurl/node_modules/thriftrw/thrift.js:199:32)
at new Thrift (/usr/lib/node_modules/tcurl/node_modules/thriftrw/thrift.js:69:10)
at new TChannelAsThrift (/usr/lib/node_modules/tcurl/node_modules/tchannel/as/thrift.js:46:17)
at asThrift (/usr/lib/node_modules/tcurl/index.js:324:18)
at onIdentified (/usr/lib/node_modules/tcurl/index.js:278:13)
at finish (/usr/lib/node_modules/tcurl/node_modules/tchannel/peer.js:266:9)
at Array.onIdentified [as 1] (/usr/lib/node_modules/tcurl/node_modules/tchannel/peer.js:257:9)
at DefinedEvent.emit (/usr/lib/node_modules/tcurl/node_modules/tchannel/lib/event_emitter.js:90:25)
at TChannelConnection.onOutIdentified (/usr/lib/node_modules/tcurl/node_modules/tchannel/connection.js:383:26)
Can anyone tell me what is the mistake?
for the node example, the thrift file in the guide needs to be updated. try to use the following (i just added a required keyword for every field):
struct GetResult {
1: required string value
}
service KeyValue {
GetResult get_v1(
1: required string key
)
void put_v1(
1: required string key,
2: required string value
)
}

Categories