Commit 4490b70c authored by Robert Knight's avatar Robert Knight

Merge pull request #2619 from hypothesis/explicit-settings-for-websocket

Explicit settings for websocket
parents a3f7a2cc 8334e2f7
...@@ -162,7 +162,7 @@ module.exports = angular.module('h', [ ...@@ -162,7 +162,7 @@ module.exports = angular.module('h', [
.service('unicode', require('./unicode')) .service('unicode', require('./unicode'))
.service('viewFilter', require('./view-filter')) .service('viewFilter', require('./view-filter'))
.factory('serviceUrl', require('./service-url')) .factory('settings', require('./settings'))
.value('AnnotationSync', require('./annotation-sync')) .value('AnnotationSync', require('./annotation-sync'))
.value('AnnotationUISync', require('./annotation-ui-sync')) .value('AnnotationUISync', require('./annotation-ui-sync'))
......
...@@ -7,8 +7,8 @@ var currentToken = null; ...@@ -7,8 +7,8 @@ var currentToken = null;
// @ngInject // @ngInject
function fetchToken($http, $q, jwtHelper, serviceUrl, session) { function fetchToken($http, $q, jwtHelper, session, settings) {
var tokenUrl = new URL('token', serviceUrl).href; var tokenUrl = new URL('token', settings.apiUrl).href;
if (currentToken === null || jwtHelper.isTokenExpired(currentToken)) { if (currentToken === null || jwtHelper.isTokenExpired(currentToken)) {
if (tokenPromise === null) { if (tokenPromise === null) {
...@@ -47,13 +47,13 @@ function fetchToken($http, $q, jwtHelper, serviceUrl, session) { ...@@ -47,13 +47,13 @@ function fetchToken($http, $q, jwtHelper, serviceUrl, session) {
// @ngInject // @ngInject
function tokenGetter($injector, config, serviceUrl) { function tokenGetter($injector, config, settings) {
var requestUrl = config.url; var requestUrl = config.url;
// Only send the token on requests to the annotation storage service // Only send the token on requests to the annotation storage service
// and only if it is not the token request itself. // and only if it is not the token request itself.
if (requestUrl !== serviceUrl) { if (requestUrl !== settings.apiUrl) {
if (requestUrl.slice(0, serviceUrl.length) === serviceUrl) { if (requestUrl.slice(0, settings.apiUrl.length) === settings.apiUrl) {
return authPromise return authPromise
.then(function () { .then(function () {
return $injector.invoke(fetchToken); return $injector.invoke(fetchToken);
......
/**
* @ngdoc service
* @name serviceUrl
*
* @description
* The 'serviceUrl' exposes the base URL of the API backend.
*/
// @ngInject
function serviceUrl($document) {
return $document
.find('link')
.filter(function () {
return (this.rel === 'service' &&
this.type === 'application/annotatorsvc+json');
})
.filter(function () {
return this.href;
})
.prop('href');
}
module.exports = serviceUrl;
'use strict';
var angular = require('angular');
/**
* @ngdoc factory
* @name settings
*
* @description
* The 'settings' factory exposes shared application settings, read from the
* global variable 'hypothesis.settings' in the app page.
*/
// @ngInject
function settings($window) {
var data = {};
if ($window.hypothesis && $window.hypothesis.settings) {
angular.copy($window.hypothesis.settings, data);
}
return data;
}
module.exports = settings;
...@@ -10,16 +10,15 @@ ...@@ -10,16 +10,15 @@
# store.SearchResource(). # store.SearchResource().
### ###
module.exports = [ module.exports = [
'$http', '$resource', 'serviceUrl' '$http', '$resource', 'settings'
($http, $resource, serviceUrl) -> ($http, $resource, settings) ->
camelize = (string) -> camelize = (string) ->
string.replace /(?:^|_)([a-z])/g, (_, char) -> char.toUpperCase() string.replace /(?:^|_)([a-z])/g, (_, char) -> char.toUpperCase()
store = store =
$resolved: false $resolved: false
# We call the service_url and the backend api gives back # We call the API root and it gives back the actions it provides.
# the actions and urls it provides. $promise: $http.get(settings.apiUrl)
$promise: $http.get(serviceUrl)
.finally -> store.$resolved = true .finally -> store.$resolved = true
.then (response) -> .then (response) ->
for name, actions of response.data.links for name, actions of response.data.links
...@@ -27,6 +26,6 @@ module.exports = [ ...@@ -27,6 +26,6 @@ module.exports = [
# For the search resource, one URL is given for all actions. # For the search resource, one URL is given for all actions.
# For the annotations, each action has its own URL. # For the annotations, each action has its own URL.
prop = "#{camelize(name)}Resource" prop = "#{camelize(name)}Resource"
store[prop] = $resource(actions.url or serviceUrl, {}, actions) store[prop] = $resource(actions.url or settings.apiUrl, {}, actions)
store store
] ]
var baseURI = require('document-base-uri')
var uuid = require('node-uuid') var uuid = require('node-uuid')
// the randomly generated session UUID // the randomly generated session UUID
...@@ -17,14 +16,14 @@ var socket; ...@@ -17,14 +16,14 @@ var socket;
* @param annotationMapper - The local annotation store * @param annotationMapper - The local annotation store
* @param groups - The local groups store * @param groups - The local groups store
* @param session - Provides access to read and update the session state * @param session - Provides access to read and update the session state
* @param settings - Application settings
* *
* @return An angular-websocket wrapper around the socket. * @return An angular-websocket wrapper around the socket.
*/ */
// @ngInject // @ngInject
function connect($websocket, annotationMapper, groups, session) { function connect($websocket, annotationMapper, groups, session, settings) {
// Get the socket URL // Get the socket URL
var url = new URL('/ws', baseURI); var url = settings.websocketUrl;
url.protocol = url.protocol.replace('http', 'ws');
// Close any existing socket // Close any existing socket
if (socket) { if (socket) {
...@@ -32,7 +31,7 @@ function connect($websocket, annotationMapper, groups, session) { ...@@ -32,7 +31,7 @@ function connect($websocket, annotationMapper, groups, session) {
} }
// Open the socket // Open the socket
socket = $websocket(url.href, [], { socket = $websocket(url, [], {
reconnectIfNotNormalClose: true reconnectIfNotNormalClose: true
}); });
socket.send({ socket.send({
......
...@@ -13,7 +13,7 @@ describe 'store', -> ...@@ -13,7 +13,7 @@ describe 'store', ->
beforeEach module ($provide) -> beforeEach module ($provide) ->
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
$provide.value 'serviceUrl', 'http://example.com/api' $provide.value 'settings', {apiUrl: 'http://example.com/api'}
return return
afterEach -> afterEach ->
......
...@@ -34,6 +34,7 @@ describe('streamer', function () { ...@@ -34,6 +34,7 @@ describe('streamer', function () {
var fakeAnnotationMapper; var fakeAnnotationMapper;
var fakeGroups; var fakeGroups;
var fakeSession; var fakeSession;
var fakeSettings;
var socket; var socket;
beforeEach(function () { beforeEach(function () {
...@@ -52,11 +53,16 @@ describe('streamer', function () { ...@@ -52,11 +53,16 @@ describe('streamer', function () {
update: sinon.stub(), update: sinon.stub(),
}; };
fakeSettings = {
websocketUrl: 'ws://example.com/ws',
};
socket = streamer.connect( socket = streamer.connect(
fakeSocketConstructor, fakeSocketConstructor,
fakeAnnotationMapper, fakeAnnotationMapper,
fakeGroups, fakeGroups,
fakeSession fakeSession,
fakeSettings
); );
}); });
...@@ -70,7 +76,9 @@ describe('streamer', function () { ...@@ -70,7 +76,9 @@ describe('streamer', function () {
var oldSocket = socket; var oldSocket = socket;
var newSocket = streamer.connect(fakeSocketConstructor, var newSocket = streamer.connect(fakeSocketConstructor,
fakeAnnotationMapper, fakeAnnotationMapper,
fakeGroups fakeGroups,
fakeSession,
fakeSettings
); );
assert.ok(oldSocket.didClose); assert.ok(oldSocket.didClose);
assert.ok(!newSocket.didClose); assert.ok(!newSocket.didClose);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment