UNPKG

wechaty-grpc

Version:
117 lines 4.46 kB
"use strict"; 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