wechaty-grpc
Version:
gRPC for Wechaty
117 lines • 4.46 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const util_1 = __importDefault(require("util"));
const fs_1 = __importDefault(require("fs"));
const constants_1 = require("@grpc/grpc-js/build/src/constants");
const mod_1 = require("../../src/mod");
const puppet_server_impl_js_1 = require("../../tests/puppet-server-impl.js");
const grpc_js_1 = require("@grpc/grpc-js");
function monkeyPatchMetadataFromHttp2Headers(MetadataClass) {
const fromHttp2Headers = MetadataClass.fromHttp2Headers;
MetadataClass.fromHttp2Headers = function (headers) {
const metadata = fromHttp2Headers.call(MetadataClass, headers);
if (metadata.get('authorization').length <= 0) {
const authority = headers[':authority'];
const authorization = `Wechaty ${authority}`;
metadata.set('authorization', authorization);
}
return metadata;
};
}
/**
* Huan(202108): wrap the following handle calls with authorization:
* - handleUnaryCall
* - handleClientStreamingCall
* - handleServerStreamingCall
* - handleBidiStreamingCall
*
* See:
* https://grpc.io/docs/guides/auth/#with-server-authentication-ssltls-and-a-custom-header-with-token
*/
function authHandler(validToken, handler) {
console.info('wrapAuthHandler', handler.name);
return function (call, cb) {
// console.info('wrapAuthHandler internal')
const authorization = call.metadata.get('authorization')[0];
// console.info('authorization', authorization)
let errMsg = '';
if (typeof authorization === 'string') {
if (authorization.startsWith('Wechaty ')) {
const token = authorization.substring(8 /* 'Wechaty '.length */);
if (token === validToken) {
return handler(call, cb);
}
else {
errMsg = `Invalid Wechaty TOKEN "${token}"`;
}
}
else {
const type = authorization.split(/\s+/)[0];
errMsg = `Invalid authorization type: "${type}"`;
}
}
else {
errMsg = 'No Authorization found.';
}
/**
* Not authorized
*/
const error = new grpc_js_1.StatusBuilder()
.withCode(constants_1.Status.UNAUTHENTICATED)
.withDetails(errMsg)
.withMetadata(call.metadata)
.build();
if (cb) {
cb(error);
}
else if ('emit' in call) {
call.emit('error', error);
}
else {
throw new Error('no callback and call is not emit-able');
}
};
}
const wechatyAuthToken = (validToken) => (puppetServer) => {
for (const [key, val] of Object.entries(puppetServer)) {
puppetServer[key] = authHandler(validToken, val);
}
return puppetServer;
};
monkeyPatchMetadataFromHttp2Headers(grpc_js_1.Metadata);
const puppetServerExample = {
...puppet_server_impl_js_1.puppetServerImpl,
ding: (call, callback) => {
const data = call.request.getData();
console.info(`ding(${data})`);
console.info('authorization:', call.metadata.getMap()['authorization']);
callback(null, new mod_1.puppet.DingResponse());
},
};
async function main() {
const puppetServerExampleWithAuth = wechatyAuthToken('__token__')(puppetServerExample);
const server = new mod_1.grpc.Server();
server.addService(mod_1.puppet.PuppetService, puppetServerExampleWithAuth);
const serverBindPromise = util_1.default.promisify(server.bindAsync.bind(server));
void fs_1.default;
const rootCerts = fs_1.default.readFileSync('root-ca.crt');
void rootCerts;
const keyCertPairs = [{
cert_chain: fs_1.default.readFileSync('server.crt'),
private_key: fs_1.default.readFileSync('server.key'),
}];
// const checkClientCertificate = false
const port = await serverBindPromise('0.0.0.0:8788',
// grpc.ServerCredentials.createInsecure(),
mod_1.grpc.ServerCredentials.createSsl(null, keyCertPairs) //, checkClientCertificate),
);
console.info('Listen on port:', port);
server.start();
return 0;
}
main()
.catch(console.error);
//# sourceMappingURL=server.js.map