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

Xhr #90

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
6 changes: 3 additions & 3 deletions bootstrap-theme.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions default-theme.js

Large diffs are not rendered by default.

28 changes: 27 additions & 1 deletion dummy/src/actions/request-test-buttons.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {fetch} from "../../../src/index";
import {fetch, xhr} from "../../../src/index";

export const REQUEST_TEST_START = "REQUEST_TEST_START";
export const REQUEST_TEST_COMPLETE = "REQUEST_TEST_COMPLETE";
Expand Down Expand Up @@ -47,3 +47,29 @@ export function requestTest(url, key) {
});
};
}
export function requestTestXhr(url, key) {
return dispatch => {
dispatch(requestTestStart(key));

return xhr(url, {
credentials: "include"
})
.then(resp => {
if (resp && resp.statusText === "OK") {
dispatch(requestTestComplete(key))
} else {
dispatch(requestTestError(key));
}

return resp.json();
})
.then(json => {
console.log("@-->resp json", json);
return json;
})
.catch(resp => {
console.log("fail", resp);
dispatch(requestTestError(key))
});
};
}
21 changes: 21 additions & 0 deletions dummy/src/views/Main.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,27 @@ class Main extends React.Component {
path="/demo/members_only_group"
endpointKey="any"/></td>
</tr>
<tr>
<td>Default user:</td>
<td><RequestTestButton
xhr
path="/demo/members_only"
endpointKey="default"/></td>
</tr>
<tr>
<td>Alternate user class:</td>
<td><RequestTestButton
xhr
path="/demo/members_only_mang"
endpointKey="evilUser"/></td>
</tr>
<tr>
<td>Group that includes both user classes:</td>
<td><RequestTestButton
xhr
path="/demo/members_only_group"
endpointKey="any"/></td>
</tr>
</tbody>
</Table>
</IndexPanel>
Expand Down
8 changes: 6 additions & 2 deletions dummy/src/views/partials/RequestTestButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { PropTypes } from "react";
import {Glyphicon} from "react-bootstrap";
import {ButtonLoader} from "../../../../src/views/bootstrap";
import {connect} from "react-redux";
import {requestTest} from "../../actions/request-test-buttons";
import {requestTest, requestTestXhr} from "../../actions/request-test-buttons";
import {getApiUrl} from "../../../../src/utils/session-storage";

class RequestTestButton extends React.Component {
Expand All @@ -17,7 +17,11 @@ class RequestTestButton extends React.Component {

handleClick () {
let url = getApiUrl() + this.props.path;
this.props.dispatch(requestTest(url, this.props.path));
if (!this.props.xhr) {
this.props.dispatch(requestTest(url, this.props.path));
} else {
this.props.dispatch(requestTestXhr(url, this.props.path));
}
}

render () {
Expand Down
4 changes: 2 additions & 2 deletions index.js

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions material-ui-theme.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ export {

/* utils */
export {default as fetch} from "./utils/fetch";
export {xhr} from "./utils/fetch";
84 changes: 84 additions & 0 deletions src/utils/fetch.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,34 @@ function updateAuthCredentials(resp) {
return resp;
}

function updateAuthCredentialsXhr(xhrReq, url) {
// check config apiUrl matches the current response url
if (isApiRequest(url)) {
// set header for each key in `tokenFormat` config
var newHeaders = {};

// set flag to ensure that we don't accidentally nuke the headers
// if the response tokens aren't sent back from the API
var blankHeaders = true;

// set header key + val for each key in `tokenFormat` config
for (var key in getTokenFormat()) {
newHeaders[key] = xhrReq.getResponseHeader(key);

if (newHeaders[key]) {
blankHeaders = false;
}
}

// persist headers for next request
if (!blankHeaders) {
persistData(C.SAVED_CREDS_KEY, newHeaders);
}
}

return xhrReq.response;
}

export default function (url, options={}) {
if (!options.headers) {
options.headers = {}
Expand All @@ -82,3 +110,59 @@ export default function (url, options={}) {
return originalFetch(url, options)
.then(resp => updateAuthCredentials(resp));
}

export function xhr(url, options) {
return extendRequesterXhr(url, xhrRequest, options);
}

function extendRequesterXhr(url, requester, options={}) {
if (!options.headers) {
options.headers = {}
}
extend(options.headers, getAuthHeaders(url));
return requester(url, options)
.then(xhrReq => updateAuthCredentialsXhr(xhrReq, url));
}

function xhrRequest(url, options) {
return new Promise((resolve, reject) => {
const xhrReq = new XMLHttpRequest();
xhrReq.open(options.method, url);
xhrReq.onload = () => {
if (xhrReq.status >= 200 && xhrReq.status < 300) {
resolve(xhrReq);
} else {
reject({
status: xhrReq.status,
statusText: xhrReq.statusText
});
}
};
xhrReq.onerror = () => {
reject({
status: xhrReq.status,
statusText: xhrReq.statusText
});
};
if (options.headers) {
Object.keys(options.headers).forEach((key) => {
xhrReq.setRequestHeader(key, options.headers[key]);
});
}
let params = options.params;
if (params && typeof params === 'object' && !params.formData) {
params = objectToQueryString(params);
}
if (options.progress) {
xhrReq.upload.addEventListener('progress', options.progress, false);
}
if (params.formData) {
params = params.formData;
}
xhrReq.send(params);
});
}

function objectToQueryString(obj) {
return Object.keys(obj).map(k => `${encodeURIComponent(k)}=${encodeURIComponent(obj[k])}`).join('&');
}
9 changes: 8 additions & 1 deletion test/actions/client-config-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import ReactDOM from "react-dom";
import {retrieveData, getCurrentEndpointKey} from "../../src/utils/session-storage";
import {syncHistoryWithStore, push} from "react-router-redux";
import {expect} from "chai";
import {fetch} from "../../src";
import {fetch, xhr} from "../../src";
import nock from "nock";

var testUid = "[email protected]",
Expand Down Expand Up @@ -164,6 +164,13 @@ export default function() {
expect(retrieveData("authHeaders")["access-token"]).to.equal(nextToken);
done();
});

// next request should include auth headers
xhr(`${altApiUrl}/api/hello`).then(() => {
// cookie should have been updated to latest
expect(retrieveData("authHeaders")["access-token"]).to.equal(nextToken);
done();
});
})
.catch(err => console.log("@-->error", err.stack));

Expand Down