Improve user agent API
This commit is contained in:
parent
4a0e4f3709
commit
aa691b4d1f
|
@ -52,7 +52,7 @@ exports.version = {
|
|||
remotePort: addrRecv.port,
|
||||
port: addrFrom.port,
|
||||
nonce: nonce,
|
||||
software: decodedUa.software,
|
||||
userAgent: decodedUa.str,
|
||||
streamNumbers: decodedStreamNumbers.list,
|
||||
// NOTE(Kagami): Real data length. It may be some gap between end
|
||||
// of stream numbers list and end of payload:
|
||||
|
@ -74,7 +74,7 @@ exports.version = {
|
|||
var time = opts.time || new Date();
|
||||
var nonce = opts.nonce || exports.version.NONCE;
|
||||
assert(nonce.length === 8, "Bad nonce");
|
||||
var software = opts.software || UserAgent.SELF;
|
||||
var userAgent = opts.userAgent || UserAgent.SELF;
|
||||
var streamNumbers = opts.streamNumbers || [1];
|
||||
// Start encoding.
|
||||
var protoVersion = new Buffer(4);
|
||||
|
@ -98,7 +98,7 @@ exports.version = {
|
|||
addrRecv,
|
||||
addrFrom,
|
||||
nonce,
|
||||
UserAgent.encode(software),
|
||||
UserAgent.encode(userAgent),
|
||||
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}];
|
||||
|
||||
/**
|
||||
* 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
|
||||
* user agent format because it's not that important.
|
||||
* Also note that `rest` references input buffer.
|
||||
* @param {Buffer} buf - A buffer that starts with encoded user agent
|
||||
* @return {{software: Object[], length: number, rest: Buffer}}
|
||||
* Decoded user agent structure.
|
||||
* @param {string} str - Raw user agent string
|
||||
* @return {Object[]} Parsed user agent.
|
||||
*/
|
||||
exports.decode = function(buf) {
|
||||
var decoded = var_str.decode(buf);
|
||||
exports.parse = function(str) {
|
||||
var software = [];
|
||||
if (decoded.str) {
|
||||
software = decoded.str.slice(1, -1).split("/");
|
||||
if (str.length > 2 && str[0] === "/" && str[str.length - 1] === "/") {
|
||||
software = str.slice(1, -1).split("/");
|
||||
software = software.map(function(str) {
|
||||
// That's more readable than /([^:]*)(?::([^(]*)(?:\(([^)]*))?)?/
|
||||
var soft = {name: str};
|
||||
|
@ -47,31 +52,35 @@ exports.decode = function(buf) {
|
|||
return soft;
|
||||
});
|
||||
}
|
||||
return {software: software, length: decoded.length, rest: decoded.rest};
|
||||
return software;
|
||||
};
|
||||
|
||||
/**
|
||||
* Encode user agent. Most underlying software comes first.
|
||||
* @param {(Object[]|string[]|Object|string)} software - List of
|
||||
* software to encode
|
||||
* Encode user agent into `var_str` Buffer. Most underlying software
|
||||
* comes first.
|
||||
* @param {(Object[]|string[]|string)} software - List of software to
|
||||
* encode or raw user agent string
|
||||
* @return {Buffer} Encoded user agent.
|
||||
*/
|
||||
var encode = exports.encode = function(software) {
|
||||
if (!Array.isArray(software)) {
|
||||
software = [software];
|
||||
var ua;
|
||||
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) {
|
||||
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 + "/");
|
||||
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.port).to.equal(8444);
|
||||
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.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() {
|
||||
|
@ -736,10 +746,10 @@ describe("High-level classes", function() {
|
|||
var bnode = {name: "bitchan-node", version: "0.0.1"};
|
||||
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 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: "AndroidBuild", version: "0.8"},
|
||||
]);
|
||||
|
@ -749,40 +759,41 @@ describe("High-level classes", function() {
|
|||
|
||||
it("should encode", function() {
|
||||
var ua = UserAgent.encode([pybm]);
|
||||
expect(var_str.decode(ua).str).to.equal("/PyBitmessage:0.4.4/");
|
||||
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.rest.toString("hex")).to.equal("");
|
||||
|
||||
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() {
|
||||
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]).to.have.property("version");
|
||||
|
||||
res = UserAgent.decode(UserAgent.encodeSelfWith([bnode, bweb]));
|
||||
software = res.software;
|
||||
software = UserAgent.parse(res.str);
|
||||
expect(software[0].name).to.equal("bitmessage");
|
||||
expect(software[1]).to.deep.equal(bnode);
|
||||
expect(software[2].name).to.equal(bweb.name);
|
||||
expect(software[2].version).to.equal("0.0.0");
|
||||
});
|
||||
|
||||
it("should accept just object or string(s) on encode", function() {
|
||||
var enc1 = UserAgent.encode({name: "test", version: "0.0.1"});
|
||||
var enc2 = UserAgent.encode("test:0.0.1");
|
||||
var res = [{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");
|
||||
var software = UserAgent.decode(enc3).software;
|
||||
expect(software[0].name).to.equal("bitmessage");
|
||||
expect(software[1]).to.deep.equal(res[0]);
|
||||
it("should accept raw user agent string on encode", function() {
|
||||
var enc = UserAgent.encode("/test:0.0.1/");
|
||||
var software = UserAgent.parse(UserAgent.decode(enc).str);
|
||||
expect(software).to.deep.equal([{name: "test", version: "0.0.1"}]);
|
||||
});
|
||||
|
||||
it("should parse empty/incorrect user agent into empty list", function() {
|
||||
expect(UserAgent.parse("").length).to.equal(0);
|
||||
expect(UserAgent.parse("test").length).to.equal(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