Skip to content

Commit

Permalink
Merge pull request #11 from OverloadUT/plex-headers-on-every-request
Browse files Browse the repository at this point in the history
Send X-Plex headers on every request, update defaults, add missing headers
  • Loading branch information
phillipj committed Jul 10, 2015
2 parents 5d8bae9 + 277c318 commit c585d19
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 24 deletions.
21 changes: 14 additions & 7 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,27 @@ Small module which helps you query the Plex Media Server HTTP API.

Instantiate a PlexAPI client.

The parameter can be a string representing the server's hostname, or an object with the following properties:

Options:
- **hostname**: hostname where Plex Server runs
- **port**: port number Plex Server is listening on (optional, default: 32400)
- **username**: plex.tv username (optional / required for PlexHome)
- **password**: plex.tv password (optional / required for PlexHome)
- **options**: override additional PlexHome options (optional for PlexHome)
- **identifier**: client identifier, default `generated uuid v4`
- **product**: default `App`
- **version**: default `1.0`
- **device**: default `App`
- **options**: override additional PlexHome options (optional, but recommended for PlexHome)
- **identifier**: A unique client identifier. Default is a `generated uuid v4`. *Note: you should really provide this rather than let it get generated. Every time your app runs, a new "device" will get registered on your Plex account, which can lead to poor performance once hundreds or thousands of them get created. Trust me!*
- **product**: The name of your application. Official Plex examples: `Plex Web`, `Plex Home Theater`, `Plex for Xbox One`. Default `Node.js App`
- **version**: The version of your app. Default `1.0`
- **deviceName**: The "name" of the device your app is running on. For apps like Plex Home Theater and mobile apps, it's the computer or phone's name chosen by the user. Default `Node.js App`
- **platform**: The platform your app is running on. The use of this is inconsistent in the official Plex apps. It is not displayed on the web interface. Official Plex examples: `Chrome`, `Plex Home Theater`, `Windows`. Default is `Node.js`.
- **platformVersion**: The platform version. Default is the version of Node running.
- **device**: The name of the type of computer your app is running on, usually the OS name. Official Plex examples: `Windows`, `iPhone`, `Xbox One`. Default is whatever `os.platform()` returns.

Here's an example of what an app shows up as on the Plex web interface

If argument is a `string` it is used as the hostname.
![Plex Device Example](docs/plex-device-example.png?raw)

For those who has PlexHome enabled on their server, will have to specify their username and password used at plex.tv.
The rows in that example from top to bottom are `deviceName`, `version`, `product`, and `device`.

**query(uri) : Retrieve content from URI**

Expand Down
Binary file added docs/plex-device-example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 15 additions & 1 deletion lib/api.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
var os = require('os');
var uuid = require('uuid');
var url = require('url');
var request = require('request');
Expand All @@ -19,6 +20,12 @@ function PlexAPI(options, deprecatedPort) {
this.password = opts.password;
this.options = opts.options || {};
this.options.identifier = this.options.identifier || uuid.v4();
this.options.product = this.options.product || 'Node.js App';
this.options.version = this.options.version || '1.0';
this.options.device = this.options.device || os.platform();
this.options.deviceName = this.options.deviceName || 'Node.js App';
this.options.platform = this.options.platform || 'Node.js';
this.options.platformVersion = this.options.platformVersion || process.version;

if (typeof this.hostname !== 'string') {
throw new TypeError('Invalid Plex Server hostname');
Expand Down Expand Up @@ -86,7 +93,14 @@ PlexAPI.prototype._request = function _request(relativeUrl, method, parseRespons
method: method || 'GET',
headers: {
'Accept': 'application/json',
'X-Plex-Client-Identifier': self.getIdentifier()
'X-Plex-Client-Identifier': self.getIdentifier(),
'X-Plex-Product': self.options.product,
'X-Plex-Version': self.options.version,
'X-Plex-Device': self.options.device,
'X-Plex-Device-Name': self.options.deviceName,
'X-Plex-Platform': self.options.platform,
'X-Plex-Platform-Version': self.options.platformVersion,
'X-Plex-Provides': 'controller'
}
};

Expand Down
18 changes: 7 additions & 11 deletions lib/auth.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
var os = require('os');
var uuid = require('uuid');
var request = require('request');
var Q = require('q');

var platform = os.platform();
var release = os.release();

var rxAuthToken = /authenticationToken="([^"]+)"/;

function authHeaderVal(username, password) {
Expand All @@ -20,12 +15,13 @@ function requestSignIn(username, password, headers) {
url: 'https://plex.tv/users/sign_in.xml',
headers: {
'Authorization': authHeaderVal(username, password),
'X-Plex-Client-Identifier': headers.identifier || uuid.v4(),
'X-Plex-Product': headers.product || 'App',
'X-Plex-Version': headers.version || '1.0',
'X-Plex-Device': headers.device || 'App',
'X-Plex-Platform': platform,
'X-Plex-Platform-Version': release,
'X-Plex-Client-Identifier': headers.identifier,
'X-Plex-Product': headers.product,
'X-Plex-Version': headers.version,
'X-Plex-Device': headers.device,
'X-Plex-Device-Name': headers.deviceName,
'X-Plex-Platform': headers.platform,
'X-Plex-Platform-Version': headers.platformVersion,
'X-Plex-Provides': 'controller'
}
};
Expand Down
33 changes: 33 additions & 0 deletions test/api-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,37 @@ describe('Module API', function() {
done();
});
});

it('should have configurable options that get sent in every request', function() {
api = new PlexAPI({
hostname : 'localhost',
options: {
identifier : 'mock-identifier',
product : 'mock-product',
version : 'mock-version',
device : 'mock-device',
deviceName : 'mock-deviceName',
platform : 'mock-platform',
platformVersion: 'mock-platformVersion'
}
});

server.stop();
var nockServer = server.start({
reqheaders: {
'X-Plex-Client-Identifier': 'mock-identifier',
'X-Plex-Product' : 'mock-product',
'X-Plex-Version' : 'mock-version',
'X-Plex-Device' : 'mock-device',
'X-Plex-Device-Name' : 'mock-deviceName',
'X-Plex-Platform' : 'mock-platform',
'X-Plex-Platform-Version' : 'mock-platformVersion'
}
});

api.query(ROOT_URL).done(function(result) {
expect(result).to.be.an('object');
nockServer.done();
});
});
});
16 changes: 11 additions & 5 deletions test/auth-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,13 @@ describe('Auth Tests', function() {
it('should override default options when specified', function () {
api = new PlexAPI({
hostname: 'localhost', username: 'foo', password: 'bar', options: {
identifier: 'mock-identifier',
product : 'mock-product',
version : 'mock-version',
device : 'mock-device'
identifier : 'mock-identifier',
product : 'mock-product',
version : 'mock-version',
device : 'mock-device',
deviceName : 'mock-deviceName',
platform : 'mock-platform',
platformVersion: 'mock-platformVersion'
}
});

Expand All @@ -143,7 +146,10 @@ describe('Auth Tests', function() {
'X-Plex-Client-Identifier': 'mock-identifier',
'X-Plex-Product' : 'mock-product',
'X-Plex-Version' : 'mock-version',
'X-Plex-Device' : 'mock-device'
'X-Plex-Device' : 'mock-device',
'X-Plex-Device-Name' : 'mock-deviceName',
'X-Plex-Platform' : 'mock-platform',
'X-Plex-Platform-Version' : 'mock-platformVersion'
}
});

Expand Down

0 comments on commit c585d19

Please sign in to comment.