Skip to content

Commit 7efda8d

Browse files
committed
Merge pull request #8 from OverloadUT/bugfix-auth-on-perform
Fix perform() to use authentication when needed, like query() does
2 parents ce527ce + 6c53e76 commit 7efda8d

File tree

2 files changed

+128
-49
lines changed

2 files changed

+128
-49
lines changed

lib/api.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ PlexAPI.prototype.perform = function perform(relativeUrl) {
4949
throw new TypeError('Requires url argument');
5050
}
5151

52+
var self = this;
5253
var deferred = Q.defer();
5354
var reqUrl = generateRelativeUrl.call(this, relativeUrl);
5455
var reqOpts = {
@@ -59,10 +60,21 @@ PlexAPI.prototype.perform = function perform(relativeUrl) {
5960
}
6061
};
6162

63+
if (this.authToken) {
64+
reqOpts.headers['X-Plex-Token'] = this.authToken;
65+
}
66+
67+
if (this.username) {
68+
reqOpts.headers['X-Plex-Username'] = this.username;
69+
}
70+
6271
request.get(reqOpts, function onResponse(err, res) {
6372
if (err) {
6473
return deferred.reject(new Error('Error while requesting server: ' + String(err)));
6574
}
75+
if (res.statusCode === 401) {
76+
return deferred.resolve(self._authenticateAndRetry(relativeUrl, self.perform));
77+
}
6678
if (res.statusCode !== 200) {
6779
return deferred.reject(new Error('Plex Server didnt respond with status code 200, response code: ' + res.statusCode));
6880
}
@@ -114,7 +126,7 @@ PlexAPI.prototype._request = function _request(relativeUrl) {
114126
return deferred.reject(err);
115127
}
116128
if (response.statusCode === 401) {
117-
return deferred.resolve(self._authenticateAndRetry(relativeUrl));
129+
return deferred.resolve(self._authenticateAndRetry(relativeUrl, self._request));
118130
}
119131
if (response.statusCode !== 200) {
120132
return deferred.reject(new Error('Plex Server didnt respond with status code 200, response code: ' + response.statusCode));
@@ -134,7 +146,7 @@ PlexAPI.prototype._request = function _request(relativeUrl) {
134146
return deferred.promise;
135147
};
136148

137-
PlexAPI.prototype._authenticateAndRetry = function _authenticateAndRetry(url) {
149+
PlexAPI.prototype._authenticateAndRetry = function _authenticateAndRetry(url, retryfunc) {
138150
var self = this;
139151

140152
if (this.authToken) {
@@ -144,7 +156,7 @@ PlexAPI.prototype._authenticateAndRetry = function _authenticateAndRetry(url) {
144156
return auth.retrieveAuthToken(self.username, self.password, self.options)
145157
.then(function onAuthResult(token) {
146158
self.authToken = token;
147-
return self._request(url);
159+
return retryfunc.call(self, url);
148160
});
149161
};
150162

test/auth-test.js

Lines changed: 113 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var ROOT_URL = '/';
55

66
var PlexAPI = require('..');
77

8-
describe('query()', function() {
8+
describe('Auth Tests', function() {
99
var api;
1010
var scope;
1111

@@ -21,70 +21,137 @@ describe('query()', function() {
2121

2222
afterEach(server.stop);
2323

24-
it('should request https://plex.tv/users/sign_in.xml when Plex Server responds with 401', function() {
25-
var plexTvMock = server.requiresAuthToken();
24+
describe('query()', function() {
2625

27-
server.start();
26+
it('should request https://plex.tv/users/sign_in.xml when Plex Server responds with 401', function () {
27+
var plexTvMock = server.requiresAuthToken();
2828

29-
return api.query(ROOT_URL).then(function(result) {
30-
plexTvMock.done();
31-
});
32-
});
29+
server.start();
3330

34-
it('should uses username / password given upon instantiation when requesting plex.tv', function() {
35-
var plexTvMock = server.requiresAuthToken({
36-
reqheaders: {
37-
'Authorization': 'Basic Zm9vOmJhcg=='
38-
}
31+
return api.query(ROOT_URL).then(function (result) {
32+
plexTvMock.done();
33+
});
3934
});
4035

41-
server.start();
36+
it('should uses username / password given upon instantiation when requesting plex.tv', function () {
37+
var plexTvMock = server.requiresAuthToken({
38+
reqheaders: {
39+
'Authorization': 'Basic Zm9vOmJhcg=='
40+
}
41+
});
4242

43-
return api.query(ROOT_URL).then(function(result) {
44-
plexTvMock.done();
43+
server.start();
44+
45+
return api.query(ROOT_URL).then(function (result) {
46+
plexTvMock.done();
47+
});
4548
});
46-
});
4749

48-
it('should retry original request with authentication token after requesting plex.tv', function() {
49-
var plexTvMock = server.requiresAuthToken();
50+
it('should retry original request with authentication token after requesting plex.tv', function () {
51+
var plexTvMock = server.requiresAuthToken();
5052

51-
scope = server.start({
52-
reqheaders: {
53-
'X-Plex-Token': 'abc-pretend-to-be-token'
54-
}
53+
scope = server.start({
54+
reqheaders: {
55+
'X-Plex-Token': 'abc-pretend-to-be-token'
56+
}
57+
});
58+
59+
return api.query(ROOT_URL).then(function (result) {
60+
scope.done();
61+
});
5562
});
5663

57-
return api.query(ROOT_URL).then(function(result) {
58-
scope.done();
64+
it('should override default options when specified', function () {
65+
api = new PlexAPI({
66+
hostname: 'localhost', username: 'foo', password: 'bar', options: {
67+
identifier: 'mock-identifier',
68+
product : 'mock-product',
69+
version : 'mock-version',
70+
device : 'mock-device'
71+
}
72+
});
73+
74+
scope = server.requiresAuthToken({
75+
reqheaders: {
76+
'X-Plex-Client-Identifier': 'mock-identifier',
77+
'X-Plex-Product' : 'mock-product',
78+
'X-Plex-Version' : 'mock-version',
79+
'X-Plex-Device' : 'mock-device'
80+
}
81+
});
82+
83+
server.start()
84+
85+
return api.query(ROOT_URL).then(function (result) {
86+
scope.done();
87+
});
5988
});
6089
});
6190

62-
it('should override default options when specified', function() {
63-
api = new PlexAPI({
64-
hostname: 'localhost',
65-
username: 'foo',
66-
password: 'bar',
67-
options: {
68-
identifier: 'mock-identifier',
69-
product: 'mock-product',
70-
version: 'mock-version',
71-
device: 'mock-device'
72-
}
91+
describe('perform()', function() {
92+
93+
it('should request https://plex.tv/users/sign_in.xml when Plex Server responds with 401', function () {
94+
var plexTvMock = server.requiresAuthToken();
95+
96+
server.start();
97+
98+
return api.perform(ROOT_URL).then(function (result) {
99+
plexTvMock.done();
100+
});
73101
});
74102

75-
scope = server.requiresAuthToken({
76-
reqheaders: {
77-
'X-Plex-Client-Identifier': 'mock-identifier',
78-
'X-Plex-Product': 'mock-product',
79-
'X-Plex-Version': 'mock-version',
80-
'X-Plex-Device': 'mock-device'
81-
}
103+
it('should uses username / password given upon instantiation when requesting plex.tv', function () {
104+
var plexTvMock = server.requiresAuthToken({
105+
reqheaders: {
106+
'Authorization': 'Basic Zm9vOmJhcg=='
107+
}
108+
});
109+
110+
server.start();
111+
112+
return api.perform(ROOT_URL).then(function (result) {
113+
plexTvMock.done();
114+
});
82115
});
83116

84-
server.start()
117+
it('should retry original request with authentication token after requesting plex.tv', function () {
118+
var plexTvMock = server.requiresAuthToken();
119+
120+
scope = server.start({
121+
reqheaders: {
122+
'X-Plex-Token': 'abc-pretend-to-be-token'
123+
}
124+
});
125+
126+
return api.perform(ROOT_URL).then(function (result) {
127+
scope.done();
128+
});
129+
});
85130

86-
return api.query(ROOT_URL).then(function(result) {
87-
scope.done();
131+
it('should override default options when specified', function () {
132+
api = new PlexAPI({
133+
hostname: 'localhost', username: 'foo', password: 'bar', options: {
134+
identifier: 'mock-identifier',
135+
product : 'mock-product',
136+
version : 'mock-version',
137+
device : 'mock-device'
138+
}
139+
});
140+
141+
scope = server.requiresAuthToken({
142+
reqheaders: {
143+
'X-Plex-Client-Identifier': 'mock-identifier',
144+
'X-Plex-Product' : 'mock-product',
145+
'X-Plex-Version' : 'mock-version',
146+
'X-Plex-Device' : 'mock-device'
147+
}
148+
});
149+
150+
server.start()
151+
152+
return api.perform(ROOT_URL).then(function (result) {
153+
scope.done();
154+
});
88155
});
89156
});
90157
});

0 commit comments

Comments
 (0)