Commit f7a515c5 authored by Harrison Healey's avatar Harrison Healey Committed by GitHub

Add fallback for getRedirectLocation on older servers (#632)

parent 46dd5d74
......@@ -9,6 +9,8 @@ import {loadMe} from './users';
import {loadRolesIfNeeded} from './roles';
import {logError} from './errors';
import {batchActions} from 'redux-batched-actions';
import {getServerVersion} from 'selectors/entities/general';
import {isMinimumServerVersion} from 'utils/helpers';
import type {GeneralState} from '../types/general';
import type {GenericClientResponse, logLevel} from '../types/client4';
......@@ -183,9 +185,16 @@ export function getRedirectLocation(url: string): ActionFunc {
return async (dispatch: DispatchFunc, getState: GetStateFunc) => {
dispatch({type: GeneralTypes.REDIRECT_LOCATION_REQUEST, data: {}}, getState);
let pendingData: Promise<GenericClientResponse>;
if (isMinimumServerVersion(getServerVersion(getState()), 5, 3)) {
pendingData = Client4.getRedirectLocation(url);
} else {
pendingData = Promise.resolve({location: url});
}
let data: GenericClientResponse;
try {
data = await Client4.getRedirectLocation(url);
data = await pendingData;
} catch (error) {
forceLogoutIfNecessary(error, dispatch, getState);
dispatch({type: GeneralTypes.REDIRECT_LOCATION_FAILURE, data: error}, getState);
......
......@@ -68,10 +68,21 @@ function websocket(state: RequestStatusType = initialRequestState(), action: Gen
);
}
function redirectLocation(state: RequestStatusType = initialRequestState(), action: GenericAction): RequestStatusType {
return handleRequest(
GeneralTypes.REDIRECT_LOCATION_REQUEST,
GeneralTypes.REDIRECT_LOCATION_SUCCESS,
GeneralTypes.REDIRECT_LOCATION_FAILURE,
state,
action
);
}
export default combineReducers({
server,
config,
dataRetentionPolicy,
license,
websocket,
redirectLocation,
});
......@@ -66,3 +66,7 @@ export const getAutolinkedUrlSchemes = createSelector(
];
}
);
export const getServerVersion = (state) => {
return state.entities.general.serverVersion;
};
......@@ -211,6 +211,10 @@ const state: GlobalState = {
status: 'not_started',
error: null,
},
redirectLocation: {
status: 'not_started',
error: null,
},
},
posts: {
createPost: {
......
......@@ -4,6 +4,7 @@
import assert from 'assert';
import nock from 'nock';
import {GeneralTypes} from 'action_types';
import * as Actions from 'actions/general';
import {Client4} from 'client';
import {RequestStatus} from 'constants';
......@@ -131,17 +132,47 @@ describe('Actions.General', () => {
assert.equal(timezones.length === 0, false);
});
it('getRedirectLocation', async () => {
nock(Client4.getBaseRoute()).
get('/redirect_location').
query(true).
reply(200);
describe('getRedirectLocation', () => {
it('new server', async () => {
store.dispatch({type: GeneralTypes.RECEIVED_SERVER_VERSION, data: '5.3.0'});
await Actions.getRedirectLocation()(store.dispatch, store.getState);
const mock = nock(Client4.getBaseRoute()).
get('/redirect_location').
query({url: 'http://examp.le'}).
reply(200, '{"location": "https://example.com"}');
const {server} = store.getState().requests.general;
if (server.status === RequestStatus.FAILURE) {
throw new Error(JSON.stringify(server.error));
}
let requestStatus = store.getState().requests.general.redirectLocation.status;
assert.equal(requestStatus, RequestStatus.NOT_STARTED);
// Should have followed the link
const result = await store.dispatch(Actions.getRedirectLocation('http://examp.le'));
assert.deepEqual(result.data, {location: 'https://example.com'});
requestStatus = store.getState().requests.general.redirectLocation.status;
assert.equal(requestStatus, RequestStatus.SUCCESS);
assert.equal(mock.isDone(), true);
});
it('old server', async () => {
store.dispatch({type: GeneralTypes.RECEIVED_SERVER_VERSION, data: '5.0.0'});
const mock = nock(Client4.getBaseRoute()).
get('/redirect_location').
reply(404);
let requestStatus = store.getState().requests.general.redirectLocation.status;
assert.equal(requestStatus, RequestStatus.NOT_STARTED);
// Should return the original link
const result = await store.dispatch(Actions.getRedirectLocation('http://examp.le'));
assert.deepEqual(result.data, {location: 'http://examp.le'});
requestStatus = store.getState().requests.general.redirectLocation.status;
assert.equal(requestStatus, RequestStatus.SUCCESS);
// Should not call the API on an old server
assert.equal(mock.isDone(), false);
});
});
});
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