From 192f5f12d071fa534ac625290d4666c839a46a9e Mon Sep 17 00:00:00 2001 From: Nick Pestov Date: Sat, 30 May 2020 08:28:54 +1000 Subject: [PATCH] fix: google.protobuf.Any type_url fixes (#1068) * google.protobuf.Any fixes In `fromObject`, only use type name after the last '/' when doing a lookup and make sure the `type_url` prefix is preserved. In `toObject`, use `type.googleapis.com` default prefix if no `type_url` prefix is used. * fix: lint * fix: more lint Co-authored-by: Michael Lumish Co-authored-by: Alexander Fenster --- src/wrappers.js | 27 +++++++++++++++++++++++---- tests/comp_google_protobuf_any.js | 4 ++-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/wrappers.js b/src/wrappers.js index 710aab0d2..097b8ff0b 100644 --- a/src/wrappers.js +++ b/src/wrappers.js @@ -42,15 +42,20 @@ wrappers[".google.protobuf.Any"] = { // unwrap value type if mapped if (object && object["@type"]) { - var type = this.lookup(object["@type"]); + // Only use fully qualified type name after the last '/' + var name = object["@type"].substring(object["@type"].lastIndexOf("/") + 1); + var type = this.lookup(name); /* istanbul ignore else */ if (type) { // type_url does not accept leading "." var type_url = object["@type"].charAt(0) === "." ? object["@type"].substr(1) : object["@type"]; // type_url prefix is optional, but path seperator is required + if (type_url.indexOf("/") === -1) { + type_url = "/" + type_url; + } return this.create({ - type_url: "/" + type_url, + type_url: type_url, value: type.encode(type.fromObject(object)).finish() }); } @@ -61,10 +66,17 @@ wrappers[".google.protobuf.Any"] = { toObject: function(message, options) { + // Default prefix + var googleApi = "type.googleapis.com/"; + var prefix = ""; + var name = ""; + // decode value if requested and unmapped if (options && options.json && message.type_url && message.value) { // Only use fully qualified type name after the last '/' - var name = message.type_url.substring(message.type_url.lastIndexOf("/") + 1); + name = message.type_url.substring(message.type_url.lastIndexOf("/") + 1); + // Separate the prefix used + prefix = message.type_url.substring(0, message.type_url.lastIndexOf("/") + 1); var type = this.lookup(name); /* istanbul ignore else */ if (type) @@ -74,7 +86,14 @@ wrappers[".google.protobuf.Any"] = { // wrap value if unmapped if (!(message instanceof this.ctor) && message instanceof Message) { var object = message.$type.toObject(message, options); - object["@type"] = message.$type.fullName; + var messageName = message.$type.fullName[0] === "." ? + message.$type.fullName.substr(1) : message.$type.fullName; + // Default to type.googleapis.com prefix if no prefix is used + if (prefix === "") { + prefix = googleApi; + } + name = prefix + messageName; + object["@type"] = name; return object; } diff --git a/tests/comp_google_protobuf_any.js b/tests/comp_google_protobuf_any.js index 9027754af..342dcfb08 100644 --- a/tests/comp_google_protobuf_any.js +++ b/tests/comp_google_protobuf_any.js @@ -42,7 +42,7 @@ tape.test("google.protobuf.Any", function(test) { test.same(obj.foo, { type_url: "Bar", value: [10, 1, 97] }, "should keep explicit Any in toObject properly"); obj = Foo.toObject(foo, { json: true }); - test.same(obj.foo, { "@type": ".Bar", bar: "a" }, "should decode explicitly Any in toObject if requested"); + test.same(obj.foo, { "@type": "type.googleapis.com/Bar", bar: "a" }, "should decode explicitly Any in toObject if requested"); foo = Foo.fromObject({ foo: { @@ -60,7 +60,7 @@ tape.test("google.protobuf.Any", function(test) { } }); obj = Foo.toObject(baz, { json: true }); - test.same(obj.foo, { "@type": ".Bar", bar: "a" }, "should not care about prefix in type url"); + test.same(obj.foo, { "@type": "type.someurl.com/Bar", bar: "a" }, "should keep prefix in type url"); test.end(); });