-
Notifications
You must be signed in to change notification settings - Fork 142
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
Custom Request Pre-Processing #9
Comments
I have considered something like this, and not a bad idea, but so far, I've done things like this, which has worked in the limited places I have needed it: export default connect(({ params: { userId }, location: pathname }) => {
const common = (urls) => Object.keys(urls).reduce((reqs, p) => {
reqs[p] = {
url: urls[p],
comparison: pathname,
refreshing: true,
headers: {
'X-Custom-Header': 'true'
}
}
return reqs
}, {})
return common({
userFetch: `/proxy/users/${userId}`,
likesFetch: `/proxy/likes/${userId}`,
})
})(Profile) If we did something like this, I'm thinking some kind of similar function set in |
@ryanbrainard yeah exactly. A way to specify common metadata to be coerced into the final canonical request, and should allow overrides as well. The bigger question is probably how/where to do it, because the metadata should only be specified in one place, upfront somewhere. And then is used by all connect(), or selectively via decorators |
@thomasloh I'm hesitant to add any global options, but this could be a common option that's passed into every export default connect(({ params: { userId }, location: pathname }) => {
return {
userFetch: `/proxy/users/${userId}`,
likesFetch: `/proxy/likes/${userId}`,
}
}, requestPreprocessor: myCommonRequestPreprocessor)(Profile) where Another way to possibly do it is instead of making it a pre-processor, it would be letting applications overrides the defaults used in Also to consider: the order of exactly when this happens. Should it be before, after, or completely replace |
@ryanbrainard oh yeah no definitely don't want to maintain any state there! I should rephrase, it should be defined once somewhere, like you suggested, in a separate module/file, which can then be used by interested Personally I like the idea of preprocessors, because it behaves like middleware and allow composition. Something like, // requestPreprocessor.js
const compose = (...fns) => (reqs, props) => fns.reduce((finalReqs, fn) => fn(finalReqs, props), reqs);
function addAuthorizationHeader(reqs, props) {
}
function addComparison(reqs, props) {
}
export default compose(
addAuthorizationHeader,
addComparison
...
) Calling it just import refetchPreprocessor from "/common/refetch-preprocessor" // naming of this is in userland of course
connect(() => {...}, preprocessor: refetchPreprocessor) |
I liked your approach, maybe we can support something like I think it's like the middleware idea from Redux. You provide the common usage, but people can create enhancers. For example, you don't need to handle CSV requests, you can create a enhancer for it. You provide the core, people provide "uncommon" things using enhancers. Usageimport myRequestPreprocessor from './myRequestPreprocessor.js';
import handleCSV from 'refetch-csv';
import { handleJWTRequest, handleJWTResponse } from 'refetch-jwt';
// if you have many enhancers, and want to use it on many components,
// just create a `request-enhancers.js` and/or `response-enhancers.js` files and
// export your enhancers as an array
// second param: request enhancers (accept one enhancer or an array of enhancers)
// third param: response enhancers (accept one enhancer or an array of enhancers)
export default connect(props => ({ foo: 'bar' }), [myRequestPreprocessor, handleJWTRequest], [handleCSV, handleJWTResponse]); myRequestPreprocessor.js// the returned object is merged into react-refetcht's default request
const requestPreprocessor = request => ({
url: `http://foo.com/api/${request.url}`,
headers: {
'foo': 'bar'
}
});
export default requestPreprocessor; refetch-csv// the resolved promise should be the final response
const handleCSV = (request, response) => {
return Promise((resolve, reject) => {
if (request.dataType === 'csv') {
myCSVParser(response.body)
.then(data => resolve(Object.assign({}, response, { body: data })))
.catch(error => reject(new Error(error));
}
resolve(response);
});
};
export default handleCSV; refetch-jwt// if you return nothing, nothing is merged
const handleJWTRequest = request => {
if (localStorage.token) {
return {
headers: { Authorization: `Token: ${localStorage.token}` }
}
}
};
// of course if we release it as a npm module, we should support a configurable pathname
const handleJWTResponse = (request, response) => {
return Promise((resolve, reject) => {
if (request.pathname === '/auth/login' && response.ok) {
localStorage.token = response.body.token;
}
const UNAUTHORIZED = 401;
if ((request.pathname === '/auth/logout' && response.ok) || response.status === UNAUTHORIZED) {
localStorage.token = null;
}
resolve(response);
});
};
export default { handleJWTRequest, handleJWTResponse }; |
@hnordt Great Idea!! I'm waiting this ti use this lib in production! Are you making some of these changes? |
@hnordt +1 |
@ryanbrainard my suggestion on #40 (comment) can handle this. |
May I suggest fetch-intercept? |
v1.0.0-beta.0 has the ability to change the |
Good work guys! Il lunedì 28 marzo 2016, Ryan Brainard notifications@github.com ha
Luca Colonnello |
for example, ability to specify default header(s) to be added to all requests
The text was updated successfully, but these errors were encountered: