Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't deal with standard express errors any more #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 29 additions & 33 deletions src/actions/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import jwtDecode from 'jwt-decode';
import {SubmissionError} from 'redux-form';

import {API_BASE_URL} from '../config';
import {normalizeResponseErrors} from './utils';
import {handleResponseErrors} from './utils';
import {saveAuthToken, clearAuthToken} from '../local-storage';

export const SET_AUTH_TOKEN = 'SET_AUTH_TOKEN';
Expand Down Expand Up @@ -44,38 +44,34 @@ const storeAuthInfo = (authToken, dispatch) => {

export const login = (username, password) => dispatch => {
dispatch(authRequest());
return (
fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username,
password
})
return fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username,
password
})
// Reject any requests which don't return a 200 status, creating
// errors which follow a consistent format
.then(res => normalizeResponseErrors(res))
.then(res => res.json())
.then(({authToken}) => storeAuthInfo(authToken, dispatch))
.catch(err => {
const {code} = err;
const message =
code === 401
? 'Incorrect username or password'
: 'Unable to login, please try again';
dispatch(authError(err));
// Could not authenticate, so return a SubmissionError for Redux
// Form
return Promise.reject(
new SubmissionError({
_error: message
})
);
})
);
})
.then(res => handleResponseErrors(res))
.then(res => res.json())
.then(({authToken}) => storeAuthInfo(authToken, dispatch))
.catch(err => {
const {status} = err;
const message =
status === 401
? 'Incorrect username or password'
: 'Unable to login, please try again';
dispatch(authError(err));
// Could not authenticate, so return a SubmissionError for Redux
// Form
return Promise.reject(
new SubmissionError({
_error: message
})
);
});
};

export const refreshAuthToken = () => (dispatch, getState) => {
Expand All @@ -88,7 +84,7 @@ export const refreshAuthToken = () => (dispatch, getState) => {
Authorization: `Bearer ${authToken}`
}
})
.then(res => normalizeResponseErrors(res))
.then(res => handleResponseErrors(res))
.then(res => res.json())
.then(({authToken}) => storeAuthInfo(authToken, dispatch))
.catch(err => {
Expand Down
4 changes: 2 additions & 2 deletions src/actions/protected-data.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {API_BASE_URL} from '../config';
import {normalizeResponseErrors} from './utils';
import {handleResponseErrors} from './utils';

export const FETCH_PROTECTED_DATA_SUCCESS = 'FETCH_PROTECTED_DATA_SUCCESS';
export const fetchProtectedDataSuccess = data => ({
Expand All @@ -22,7 +22,7 @@ export const fetchProtectedData = () => (dispatch, getState) => {
Authorization: `Bearer ${authToken}`
}
})
.then(res => normalizeResponseErrors(res))
.then(res => handleResponseErrors(res))
.then(res => res.json())
.then(({data}) => dispatch(fetchProtectedDataSuccess(data)))
.catch(err => {
Expand Down
4 changes: 2 additions & 2 deletions src/actions/users.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {SubmissionError} from 'redux-form';

import {API_BASE_URL} from '../config';
import {normalizeResponseErrors} from './utils';
import {handleResponseErrors} from './utils';

export const registerUser = user => dispatch => {
return fetch(`${API_BASE_URL}/users`, {
Expand All @@ -11,7 +11,7 @@ export const registerUser = user => dispatch => {
},
body: JSON.stringify(user)
})
.then(res => normalizeResponseErrors(res))
.then(res => handleResponseErrors(res))
.then(res => res.json())
.catch(err => {
const {reason, message, location} = err;
Expand Down
23 changes: 5 additions & 18 deletions src/actions/utils.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,9 @@
// Boilerplate code for handling errors from the API. If the error response
// contains JSON then we return a rejected promise containing the decoded
// JSON. If the error doesn't contain JSON then we return a rejected promise
// containing the status text. If there is no error then we continue with
// the promise chain.
export const normalizeResponseErrors = res => {
// Boilerplate code for handling errors from the API. If the API sent back an
// error, return a rejected promise containing the decoded JSON body. If the
// request succeeded then we continue with the promise chain.
export const handleResponseErrors = res => {
if (!res.ok) {
if (
res.headers.has('content-type') &&
res.headers.get('content-type').startsWith('application/json')
) {
// It's a nice JSON error returned by us, so decode it
return res.json().then(err => Promise.reject(err));
}
// It's a less informative error returned by express
return Promise.reject({
code: res.status,
message: res.statusText
});
return res.json().then(err => Promise.reject(err));
}
return res;
};