Skip to content

Commit

Permalink
Merge pull request #20 from phillipj/fix-xml-parsing
Browse files Browse the repository at this point in the history
Fix XML parsing and enable HTTPS requests
  • Loading branch information
phillipj committed Sep 2, 2015
2 parents 91a004c + 2765464 commit 4440a43
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 17 deletions.
41 changes: 25 additions & 16 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ var Q = require('q');
var xml2js = require('xml2js');
var headers = require('plex-api-headers');

var xmlToJSON = Q.denodeify(xml2js.parseString);

var uri = require('./uri');

var PLEX_SERVER_PORT = 32400;
Expand Down Expand Up @@ -35,7 +37,7 @@ function PlexAPI(options, deprecatedPort) {
console.warn('PlexAPI constuctor port argument is deprecated, use an options object instead.');
}

this.serverUrl = 'http://' + hostname + ':' + this.port;
this.serverUrl = hostname + ':' + this.port;
this._initializeAuthenticator();
}

Expand Down Expand Up @@ -88,7 +90,7 @@ PlexAPI.prototype.find = function find(relativeUrl, criterias) {
PlexAPI.prototype._request = function _request(relativeUrl, method, parseResponse) {
var self = this;
var deferred = Q.defer();
var reqUrl = generateRelativeUrl.call(this, relativeUrl);
var reqUrl = this._generateRelativeUrl(relativeUrl);
var reqOpts = {
url: url.parse(reqUrl),
encoding: null,
Expand All @@ -104,6 +106,9 @@ PlexAPI.prototype._request = function _request(relativeUrl, method, parseRespons
if (err) {
return deferred.reject(err);
}

var resolveValue = body;

if (response.statusCode === 401) {
if (self.authenticator === undefined) {
return deferred.reject(new Error('Plex Server denied request, you must provide a way to authenticate! ' +
Expand All @@ -116,6 +121,7 @@ PlexAPI.prototype._request = function _request(relativeUrl, method, parseRespons
})
);
}

if (response.statusCode !== 200) {
return deferred.reject(new Error('Plex Server didnt respond with status code 200, response code: ' + response.statusCode));
}
Expand All @@ -124,19 +130,17 @@ PlexAPI.prototype._request = function _request(relativeUrl, method, parseRespons
// releasing socket back to the agent connection pool: http://nodejs.org/api/http.html#http_agent_maxsockets
response.on('data', function onData() {});

if (parseResponse) {
if (response.headers['content-type'] === 'application/json') {
return deferred.resolve(JSON.parse(body.toString('utf8')));
}
if (response.headers['content-type'].indexOf('xml') > -1) {
return deferred.resolve(xml2js.parseString(body.toString('utf8'), {
object: true
}));
}
return deferred.resolve(body);
} else {
if (!parseResponse) {
return deferred.resolve();
}

if (response.headers['content-type'] === 'application/json') {
resolveValue = JSON.parse(body.toString('utf8'));
} else if (response.headers['content-type'].indexOf('xml') > -1) {
resolveValue = xmlToJSON(body.toString('utf8'), { attrkey: 'attributes' });
}

return deferred.resolve(resolveValue);
});

return deferred.promise;
Expand Down Expand Up @@ -179,6 +183,14 @@ PlexAPI.prototype._initializeAuthenticator = function _initializeAuthenticator()
}
};

PlexAPI.prototype._generateRelativeUrl = function _generateRelativeUrl(relativeUrl) {
return this._serverScheme() + this.serverUrl + relativeUrl;
};

PlexAPI.prototype._serverScheme = function _serverScheme() {
return this.port === 443 ? 'https://' : 'http://';
};

function filterChildrenByCriterias(children, criterias) {
var context = {
criterias: criterias || {}
Expand All @@ -196,8 +208,5 @@ function criteriasMatchChild(child) {
}, true);
}

function generateRelativeUrl(relativeUrl) {
return this.serverUrl + relativeUrl;
}

module.exports = PlexAPI;
21 changes: 21 additions & 0 deletions test/query-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,25 @@ describe('query()', function() {
});
});
});

describe('XML responses', function() {
it('should convert XML to a JSON object', function() {
var plexTvApi = new PlexAPI({
hostname: 'plex.tv',
port: 443
});

server.stop();
server.start({
schemeAndHost: 'https://plex.tv',
port: 443,
contentType: 'application/xml'
});

return plexTvApi.query('/devices.xml').then(function(result) {
expect(result.MediaContainer).to.be.an('object');
expect(result.MediaContainer.attributes.publicAddress).to.equal('47.1.2.4');
});
});
});
});
7 changes: 7 additions & 0 deletions test/samples/devices.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer publicAddress="47.1.2.4">
<Device name="Node.js App" publicAddress="46.1.2.3" product="Node.js App" productVersion="1.0" platform="Node.js" platformVersion="v3.0.0" device="darwin" model="" vendor="" provides="controller" clientIdentifier="758b6938-907052f04d99" version="1.0" id="33847205" token="kiYsW" createdAt="1440669823" lastSeenAt="1440669824" screenResolution="" screenDensity="">
</Device>
<Device name="Yet another Node.js App" publicAddress="46.1.2.4" product="Node.js App" productVersion="1.0" platform="Node.js" platformVersion="v3.0.0" device="darwin" model="" vendor="" provides="controller" clientIdentifier="2d404e6b-4286-da65748a1ed4" version="1.0" id="33847195" token="ofaq" createdAt="1440669789" lastSeenAt="1440669790" screenResolution="" screenDensity="">
</Device>
</MediaContainer>
3 changes: 2 additions & 1 deletion test/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,12 @@ function replaceActualPathToRoot(path) {
module.exports = {
start: function start(options) {
options = options || {};
options.schemeAndHost = options.schemeAndHost || 'http://localhost';
options.port = options.port || PLEX_SERVER_PORT;
options.contentType = options.contentType || 'application/json';
respondWith = 'content';

var scope = nock('http://localhost:' + options.port, {
var scope = nock(options.schemeAndHost + ':' + options.port, {
reqheaders: options.reqheaders
})
.defaultReplyHeaders({
Expand Down

0 comments on commit 4440a43

Please sign in to comment.