Improve user agent API
This commit is contained in:
parent
4a0e4f3709
commit
aa691b4d1f
|
@ -52,7 +52,7 @@ exports.version = {
|
||||||
remotePort: addrRecv.port,
|
remotePort: addrRecv.port,
|
||||||
port: addrFrom.port,
|
port: addrFrom.port,
|
||||||
nonce: nonce,
|
nonce: nonce,
|
||||||
software: decodedUa.software,
|
userAgent: decodedUa.str,
|
||||||
streamNumbers: decodedStreamNumbers.list,
|
streamNumbers: decodedStreamNumbers.list,
|
||||||
// NOTE(Kagami): Real data length. It may be some gap between end
|
// NOTE(Kagami): Real data length. It may be some gap between end
|
||||||
// of stream numbers list and end of payload:
|
// of stream numbers list and end of payload:
|
||||||
|
@ -74,7 +74,7 @@ exports.version = {
|
||||||
var time = opts.time || new Date();
|
var time = opts.time || new Date();
|
||||||
var nonce = opts.nonce || exports.version.NONCE;
|
var nonce = opts.nonce || exports.version.NONCE;
|
||||||
assert(nonce.length === 8, "Bad nonce");
|
assert(nonce.length === 8, "Bad nonce");
|
||||||
var software = opts.software || UserAgent.SELF;
|
var userAgent = opts.userAgent || UserAgent.SELF;
|
||||||
var streamNumbers = opts.streamNumbers || [1];
|
var streamNumbers = opts.streamNumbers || [1];
|
||||||
// Start encoding.
|
// Start encoding.
|
||||||
var protoVersion = new Buffer(4);
|
var protoVersion = new Buffer(4);
|
||||||
|
@ -98,7 +98,7 @@ exports.version = {
|
||||||
addrRecv,
|
addrRecv,
|
||||||
addrFrom,
|
addrFrom,
|
||||||
nonce,
|
nonce,
|
||||||
UserAgent.encode(software),
|
UserAgent.encode(userAgent),
|
||||||
structs.var_int_list.encode(streamNumbers),
|
structs.var_int_list.encode(streamNumbers),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,19 +14,24 @@ var BM_VERSION = require("../package.json").version;
|
||||||
var SELF = exports.SELF = [{name: BM_NAME, version: BM_VERSION}];
|
var SELF = exports.SELF = [{name: BM_NAME, version: BM_VERSION}];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decode user agent stack.
|
* Decode user agent `var_str`. Just an alias for
|
||||||
|
* {@link var_str.decode}
|
||||||
|
* @function
|
||||||
|
*/
|
||||||
|
exports.decode = var_str.decode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse raw user agent into software stack list. Most underlying
|
||||||
|
* software comes first.
|
||||||
* NOTE: Decoding is rather loose and non-strict, it won't fail on bad
|
* NOTE: Decoding is rather loose and non-strict, it won't fail on bad
|
||||||
* user agent format because it's not that important.
|
* user agent format because it's not that important.
|
||||||
* Also note that `rest` references input buffer.
|
* @param {string} str - Raw user agent string
|
||||||
* @param {Buffer} buf - A buffer that starts with encoded user agent
|
* @return {Object[]} Parsed user agent.
|
||||||
* @return {{software: Object[], length: number, rest: Buffer}}
|
|
||||||
* Decoded user agent structure.
|
|
||||||
*/
|
*/
|
||||||
exports.decode = function(buf) {
|
exports.parse = function(str) {
|
||||||
var decoded = var_str.decode(buf);
|
|
||||||
var software = [];
|
var software = [];
|
||||||
if (decoded.str) {
|
if (str.length > 2 && str[0] === "/" && str[str.length - 1] === "/") {
|
||||||
software = decoded.str.slice(1, -1).split("/");
|
software = str.slice(1, -1).split("/");
|
||||||
software = software.map(function(str) {
|
software = software.map(function(str) {
|
||||||
// That's more readable than /([^:]*)(?::([^(]*)(?:\(([^)]*))?)?/
|
// That's more readable than /([^:]*)(?::([^(]*)(?:\(([^)]*))?)?/
|
||||||
var soft = {name: str};
|
var soft = {name: str};
|
||||||
|
@ -47,31 +52,35 @@ exports.decode = function(buf) {
|
||||||
return soft;
|
return soft;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return {software: software, length: decoded.length, rest: decoded.rest};
|
return software;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode user agent. Most underlying software comes first.
|
* Encode user agent into `var_str` Buffer. Most underlying software
|
||||||
* @param {(Object[]|string[]|Object|string)} software - List of
|
* comes first.
|
||||||
* software to encode
|
* @param {(Object[]|string[]|string)} software - List of software to
|
||||||
|
* encode or raw user agent string
|
||||||
* @return {Buffer} Encoded user agent.
|
* @return {Buffer} Encoded user agent.
|
||||||
*/
|
*/
|
||||||
var encode = exports.encode = function(software) {
|
var encode = exports.encode = function(software) {
|
||||||
if (!Array.isArray(software)) {
|
var ua;
|
||||||
software = [software];
|
if (Array.isArray(software)) {
|
||||||
|
ua = software.map(function(soft) {
|
||||||
|
if (typeof soft === "string") {
|
||||||
|
return soft;
|
||||||
|
}
|
||||||
|
var version = soft.version || "0.0.0";
|
||||||
|
var str = soft.name + ":" + version;
|
||||||
|
if (soft.comments) {
|
||||||
|
str += "(" + soft.comments + ")";
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}).join("/");
|
||||||
|
ua = "/" + ua + "/";
|
||||||
|
} else {
|
||||||
|
ua = software;
|
||||||
}
|
}
|
||||||
var ua = software.map(function(soft) {
|
return var_str.encode(ua);
|
||||||
if (typeof soft === "string") {
|
|
||||||
return soft;
|
|
||||||
}
|
|
||||||
var version = soft.version || "0.0.0";
|
|
||||||
var str = soft.name + ":" + version;
|
|
||||||
if (soft.comments) {
|
|
||||||
str += "(" + soft.comments + ")";
|
|
||||||
}
|
|
||||||
return str;
|
|
||||||
}).join("/");
|
|
||||||
return var_str.encode("/" + ua + "/");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
47
test.js
47
test.js
|
@ -374,10 +374,20 @@ describe("Message types", function() {
|
||||||
expect(res.remotePort).to.equal(48444);
|
expect(res.remotePort).to.equal(48444);
|
||||||
expect(res.port).to.equal(8444);
|
expect(res.port).to.equal(8444);
|
||||||
expect(bufferEqual(res.nonce, version.NONCE)).to.be.true;
|
expect(bufferEqual(res.nonce, version.NONCE)).to.be.true;
|
||||||
expect(res.software).to.deep.equal(UserAgent.SELF);
|
expect(UserAgent.parse(res.userAgent)).to.deep.equal(UserAgent.SELF);
|
||||||
expect(res.streamNumbers).to.deep.equal([1]);
|
expect(res.streamNumbers).to.deep.equal([1]);
|
||||||
expect(res.length).to.equal(101);
|
expect(res.length).to.equal(101);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should accept raw user agent string", function() {
|
||||||
|
var res = version.decode(version.encode({
|
||||||
|
remoteHost: "1.2.3.4",
|
||||||
|
remotePort: 48444,
|
||||||
|
port: 8444,
|
||||||
|
userAgent: "/test:0.0.1/",
|
||||||
|
}));
|
||||||
|
expect(res.userAgent).to.equal("/test:0.0.1/");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("addr", function() {
|
describe("addr", function() {
|
||||||
|
@ -736,10 +746,10 @@ describe("High-level classes", function() {
|
||||||
var bnode = {name: "bitchan-node", version: "0.0.1"};
|
var bnode = {name: "bitchan-node", version: "0.0.1"};
|
||||||
var bweb = {name: "bitchan-web"};
|
var bweb = {name: "bitchan-web"};
|
||||||
|
|
||||||
it("should decode", function() {
|
it("should decode and parse", function() {
|
||||||
var ua = var_str.encode("/cBitmessage:0.2(iPad; U; CPU OS 3_2_1)/AndroidBuild:0.8/");
|
var ua = var_str.encode("/cBitmessage:0.2(iPad; U; CPU OS 3_2_1)/AndroidBuild:0.8/");
|
||||||
var res = UserAgent.decode(ua);
|
var res = UserAgent.decode(ua);
|
||||||
expect(res.software).to.deep.equal([
|
expect(UserAgent.parse(res.str)).to.deep.equal([
|
||||||
{name: "cBitmessage", version: "0.2", comments: "iPad; U; CPU OS 3_2_1"},
|
{name: "cBitmessage", version: "0.2", comments: "iPad; U; CPU OS 3_2_1"},
|
||||||
{name: "AndroidBuild", version: "0.8"},
|
{name: "AndroidBuild", version: "0.8"},
|
||||||
]);
|
]);
|
||||||
|
@ -749,40 +759,41 @@ describe("High-level classes", function() {
|
||||||
|
|
||||||
it("should encode", function() {
|
it("should encode", function() {
|
||||||
var ua = UserAgent.encode([pybm]);
|
var ua = UserAgent.encode([pybm]);
|
||||||
expect(var_str.decode(ua).str).to.equal("/PyBitmessage:0.4.4/");
|
|
||||||
var res = UserAgent.decode(ua);
|
var res = UserAgent.decode(ua);
|
||||||
expect(res.software).to.deep.equal([pybm]);
|
expect(res.str).to.equal("/PyBitmessage:0.4.4/");
|
||||||
|
expect(UserAgent.parse(res.str)).to.deep.equal([pybm]);
|
||||||
expect(res.length).to.equal(21);
|
expect(res.length).to.equal(21);
|
||||||
expect(res.rest.toString("hex")).to.equal("");
|
expect(res.rest.toString("hex")).to.equal("");
|
||||||
|
|
||||||
ua = UserAgent.encode([{name: "test", "comments": "linux"}]);
|
ua = UserAgent.encode([{name: "test", "comments": "linux"}]);
|
||||||
expect(var_str.decode(ua).str).to.equal("/test:0.0.0(linux)/");
|
expect(UserAgent.decode(ua).str).to.equal("/test:0.0.0(linux)/");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should encode bitmessage's user agent", function() {
|
it("should encode bitmessage's user agent", function() {
|
||||||
var res = UserAgent.decode(UserAgent.encodeSelf())
|
var res = UserAgent.decode(UserAgent.encodeSelf())
|
||||||
var software = res.software;
|
var software = UserAgent.parse(res.str);
|
||||||
expect(software[0].name).to.equal("bitmessage");
|
expect(software[0].name).to.equal("bitmessage");
|
||||||
expect(software[0]).to.have.property("version");
|
expect(software[0]).to.have.property("version");
|
||||||
|
|
||||||
res = UserAgent.decode(UserAgent.encodeSelfWith([bnode, bweb]));
|
res = UserAgent.decode(UserAgent.encodeSelfWith([bnode, bweb]));
|
||||||
software = res.software;
|
software = UserAgent.parse(res.str);
|
||||||
expect(software[0].name).to.equal("bitmessage");
|
expect(software[0].name).to.equal("bitmessage");
|
||||||
expect(software[1]).to.deep.equal(bnode);
|
expect(software[1]).to.deep.equal(bnode);
|
||||||
expect(software[2].name).to.equal(bweb.name);
|
expect(software[2].name).to.equal(bweb.name);
|
||||||
expect(software[2].version).to.equal("0.0.0");
|
expect(software[2].version).to.equal("0.0.0");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should accept just object or string(s) on encode", function() {
|
it("should accept raw user agent string on encode", function() {
|
||||||
var enc1 = UserAgent.encode({name: "test", version: "0.0.1"});
|
var enc = UserAgent.encode("/test:0.0.1/");
|
||||||
var enc2 = UserAgent.encode("test:0.0.1");
|
var software = UserAgent.parse(UserAgent.decode(enc).str);
|
||||||
var res = [{name: "test", version: "0.0.1"}];
|
expect(software).to.deep.equal([{name: "test", version: "0.0.1"}]);
|
||||||
expect(UserAgent.decode(enc1).software).to.deep.equal(res);
|
});
|
||||||
expect(UserAgent.decode(enc2).software).to.deep.equal(res);
|
|
||||||
var enc3 = UserAgent.encodeSelfWith("test:0.0.1");
|
it("should parse empty/incorrect user agent into empty list", function() {
|
||||||
var software = UserAgent.decode(enc3).software;
|
expect(UserAgent.parse("").length).to.equal(0);
|
||||||
expect(software[0].name).to.equal("bitmessage");
|
expect(UserAgent.parse("test").length).to.equal(0);
|
||||||
expect(software[1]).to.deep.equal(res[0]);
|
expect(UserAgent.parse("/test").length).to.equal(0);
|
||||||
|
expect(UserAgent.parse("test/").length).to.equal(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user