-
Notifications
You must be signed in to change notification settings - Fork 652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add server interceptors #419
Comments
Server interceptors aren't in our roadmap at the moment. |
@nicolasnoble Thanks for response. Would you accept PR if I implement them, since I need server interceptors any way to be able to use grpc for production. I saw that there is also no native C++ server interceptors, but I'm looking to implement them in js side. |
We would require this to go through a GRFC process in order to discuss the API, but otherwise, yes. |
@theogravity Thanks for a link. I rewrote my server in go since it has the best grpc implementation. |
any updates on server interceptors as of now? @nicolasnoble |
Hi, any updates? |
Any updates about server interceptors? |
Nobody has proposed an API design yet, so nothing has changed. |
Any updates here? Seems like interceptors would be pretty useful for things like auth and observability. Now that gRPC-web has hit 1.0, one could serve websites with gRPC and we'll need some sort of auth mechanism. It's not hard to roll your own interceptors, but it would be better if there was a standard way to do this. |
Any updates about server interceptors? |
Any updates on this? |
Also curious about this. Would be nice for rolling gRPC servers in Node to have some “official” support for interceptors |
In case someone is interested and wants to support this, there're some discussion about this here - https://groups.google.com/g/grpc-io/c/sF8rO9ltkpA/m/qWC8an4IAwAJ |
@Abhi347 thanks for pushing this moving forward, appreciate it! |
https://github.com/deeplay-io/nice-grpc/tree/master/packages/nice-grpc has implemented server side middleware for grpc-js. |
Any updates about server interceptors? |
@murgatroid99 Any plan to implement interceptors on grpc-node server side? |
We currently have no plans to implement server interceptors in the gRPC Node library. |
Hey @murgatroid99 - thanks for still being active on this thread Do you have the grpc-node roadmap documented? I'm surprised after ~4 years interceptors have still have not been prioritised Someone made a comment that you need a proposed API design - do you have a guide on contributing? |
No. We don't really have a roadmap. It's really just team-level quarterly objectives. For the past couple of years, the main thing I have been working on is xDS features.
The proposal process is described in the README in the https://github.com/grpc/proposal repository. Check out the Node client interceptors proposal for an example that is probably similar to what a server interceptors proposal might look like. |
@murgatroid99 and other memeber of grpc. Please keep on going. The interceptors on the node server side is very importent for users authentication. Is there workaround about authentication with jwt (json web token)? Thanks. |
You may have an idea how to do it with this code : const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const proxyHandler = {
get(target, propKey) {
if (propKey !== 'addService') {
return target[propKey];
}
return (service, implementation) => {
const newImplementation = {};
const lookup = lookupServiceMetadata(service, implementation);
for (const k in implementation) {
const name = k;
const fn = implementation[k];
newImplementation[name] = (call, callback) => {
const ctx = {
call,
service: lookup(name),
};
const newCallback = callback => {
return (...args) => {
ctx.status = {
code: 0,//grpc.status.OK,
};
const err = args[0];
if (err) {
ctx.status = {
code: 2,//grpc.status.UNKNOWN,
details: err,
};
}
callback(...args);
};
};
const interceptors = target.intercept();
const first = interceptors.next();
if (!first.value) { // if we don't have any interceptors
return new Promise(resolve => {
return resolve(fn(call, newCallback(callback)));
});
}
first.value(ctx, function next() {
return new Promise(resolve => {
const i = interceptors.next();
if (i.done) {
return resolve(fn(call, newCallback(callback)));
}
return resolve(i.value(ctx, next, callback));
});
}, callback);
};
}
return target.addService(service, newImplementation);
};
},
};
const proxyServer = (server) => {
server.interceptors = [];
server.use = fn => {
server.interceptors.push(fn);
};
server.intercept = function* intercept() {
let i = 0;
while (i < server.interceptors.length) {
yield server.interceptors[i];
i++;
}
};
return new Proxy(server, proxyHandler);
}
function startServer() {
const protoDefinition = protoLoader.loadSync("PATH_TO_PROTOFILE",
{
keepCase: true,
longs: String,
enums: String,
defaults: true,
oneofs: true,
});
const proto = grpc.loadPackageDefinition(protoDefinition);
const server = proxyServer(new grpc.Server());
async function login(call, callback) {
// login code where you generate a token for the session, etc. ...
}
server.addService( proto.myservice, login); // ... adaptation necessary
//middleware function that will be called before each grpc methods
const grpcInterceptor = async (ctx, next, callback) => {
function copyMetadata(call) {
const metadata = call.metadata.getMap();
const responseMetadata = new grpc.Metadata();
for (let key in metadata) {
responseMetadata.set(key, metadata[key]);
}
return responseMetadata;
}
//token passed by http metadata
const token = ctx.call.metadata.internalRepr.get("token")[0]
// ... block of code to validate token, etc.
let validated = true;
// if all is well, we call original grpc method
if (validated) {
await next();
} else {
error = new Error("Invalid token");
error.code = 16; //UNAUTHENTICATED
callback(error);
}
};
server.use(grpcInterceptor);
server.bindAsync(address, grpc.ServerCredentials.createInsecure(), (err, result) => !err ? server.start() : console.error(err));
}
startServer();
update : added syntax highlighting to the code example. Thanks to @richardpringle. |
@mfecteau42, use |
I have proposed a design for a server interceptors API: grpc/proposal#406. If you have any feedback on the design please comment there. |
@murgatroid99 do you plan to merge these changes soon as they are approved? thanks for proposing a design! 🙏 |
Our convention is to have a review period of at least two weeks before finalizing a proposal. I am working on the implementation in parallel to the proposal review, and even once the proposal is accepted it will still take me some time to finish the implementation. |
Update: the design proposal grpc/proposal#406 is going through final review next week, and the implementation PR is out at #2650. |
Hi,
I'm using grpc-node native package for building backend API. I noticed that there is not server interceptors (correct me if I'm wrong). I want to write server interceptors for logging, auth and so on. Without it grpc-node is pretty match useless for production. Could you share what is the status on this feature, because I'm thinking to implement it in my fork branch. Thanks.
The text was updated successfully, but these errors were encountered: