提交 e2cc6609 authored 作者: vipcxj's avatar vipcxj

improve: 从网络请求方法中抽象出中间件

上级 bb29d888
...@@ -9,3 +9,5 @@ ...@@ -9,3 +9,5 @@
# misc # misc
.DS_Store .DS_Store
npm-debug.log* npm-debug.log*
/.idea
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="JavaScriptLibraryMappings"> <component name="JavaScriptLibraryMappings">
<file url="PROJECT" libraries="{polyfill}" /> <file url="file://$PROJECT_DIR$" libraries="{app-web-client/node_modules}" />
<file url="PROJECT" libraries="{app-web-client/node_modules, polyfill}" />
<includedPredefinedLibrary name="Node.js Core" />
</component> </component>
</project> </project>
\ No newline at end of file
...@@ -3,9 +3,7 @@ ...@@ -3,9 +3,7 @@
<component name="JavaScriptSettings"> <component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" /> <option name="languageLevel" value="JSX" />
</component> </component>
<component name="JsBowerSettings"> <component name="WebPackConfiguration">
<node-interpreter value="project" /> <option name="path" value="" />
<exe-path />
<config-path />
</component> </component>
</project> </project>
\ No newline at end of file
import _ from 'lodash'; /* eslint-disable no-param-reassign */
import { isNil, defaults } from 'lodash';
import { fetch } from './polyfill'; import { fetch } from './polyfill';
import { encrypt } from './helper';
import { errors } from './error';
import { getToken } from './auth';
import { checkStatus, normParams, parseObject } from './http-helper'; import { checkStatus, normParams, parseObject } from './http-helper';
import middleware from './middleware';
const defaultOptions = { const defaultOptions = {
headers: { Accept: 'application/json' }, headers: { Accept: 'application/json' },
...@@ -12,32 +11,25 @@ const defaultOptions = { ...@@ -12,32 +11,25 @@ const defaultOptions = {
/** /**
* Requests a URL, returning a promise. * Requests a URL, returning a promise.
* *
* @param {string} url The URL we want to request * @param {string} url The URL we want to delete
* @param auth * @param auth
* @param params * @param params
* @param {object} [options] The options we want to pass to "fetch" * @param {object} [options] The options we want to pass to "fetch"
* @return {object} An object containing either "data" or "err" * @return {object} An object containing either "data" or "err"
*/ */
export default async function doDelete(url, params = {}, options = {}, auth = true) { export default async function doDelete(url, params = {}, options = {}, auth = true) {
let token; params = normParams(params);
if (auth) { const res = await middleware.delete.onRequest(url, params, options, auth);
token = await getToken(); let queryParams = (res ? res.params : params).map(([k, v]) => (isNil(v) ? k : `${k}=${encodeURIComponent(v)}`));
if (!token) {
return Promise.reject(errors.tokenMissing());
}
token = encrypt(token);
}
let queryParams = token ? [...normParams(params), ['token', token]] : normParams(params);
queryParams = queryParams.map(([k, v]) => (_.isNil(v) ? k : `${k}=${encodeURIComponent(v)}`));
queryParams = queryParams.join('&'); queryParams = queryParams.join('&');
let realUrl = url; let realUrl = res ? res.url : url;
if (queryParams) { if (queryParams) {
realUrl = `${url}?${queryParams}`; realUrl = `${url}?${queryParams}`;
} }
const realOptions = _.defaults(options, defaultOptions); const realOptions = defaults(res ? res.options : options, defaultOptions);
realOptions.method = 'DELETE'; realOptions.method = 'DELETE';
return fetch(realUrl, realOptions) return fetch(realUrl, realOptions)
.then(checkStatus) .then(checkStatus)
.then(parseObject); .then(resp => parseObject(resp, middleware.delete.onResponse));
} }
...@@ -21,7 +21,7 @@ export function normParams(unnormed) { ...@@ -21,7 +21,7 @@ export function normParams(unnormed) {
} }
// eslint-disable-next-line max-len // eslint-disable-next-line max-len
export function parseObject(response, { num2str = false, bool2str = false, nul2str = false, ud2str = false, nil2str = false } = {}) { export function parseObject(response, middleware, { num2str = false, bool2str = false, nul2str = false, ud2str = false, nil2str = false } = {}) {
if (response.status === 204) { // no-content if (response.status === 204) { // no-content
return null; return null;
} else { } else {
...@@ -73,25 +73,31 @@ export function parseObject(response, { num2str = false, bool2str = false, nul2s ...@@ -73,25 +73,31 @@ export function parseObject(response, { num2str = false, bool2str = false, nul2s
const mapValue = _.curry(mapObj)(_, mapArr); const mapValue = _.curry(mapObj)(_, mapArr);
if (contentType.indexOf('json') !== -1) { if (contentType.indexOf('json') !== -1) {
return response.json() return response.json()
.then((json) => { .then(json => (middleware ? middleware(json) : json))
if (json.errorCode === 0) { .then((data) => {
let { data } = json; let out = data;
if (_.isObjectLike(data)) { if (_.isObjectLike(out)) {
data = new Resolver(data).resolve(); out = new Resolver(out).resolve();
}
return needMap ? mapValue(data) : data;
} else {
throw new Error(json.message);
} }
return needMap ? mapValue(out) : out;
}); });
} else if (contentType.indexOf('xml') !== -1) { } else if (contentType.indexOf('xml') !== -1) {
return response.text().then((text) => { return response.text()
.then((text) => {
return require.ensure([], (require) => { return require.ensure([], (require) => {
const { parseString } = require('xml2js'); const { parseString } = require('xml2js');
const options = {}; const options = {};
const json = JSON.parse(parseString(text, options)); const json = JSON.parse(parseString(text, options));
return needMap ? mapValue(json) : json; return json;
}); });
})
.then((json => (middleware ? middleware(json) : json)))
.then((data) => {
let out = data;
if (_.isObjectLike(out)) {
out = new Resolver(out).resolve();
}
return needMap ? mapValue(out) : out;
}); });
} else if (contentType.indexOf('text') !== -1) { } else if (contentType.indexOf('text') !== -1) {
return response.text(); return response.text();
......
/* eslint-disable no-unused-vars */
import { getToken } from './auth';
import { encrypt } from './helper';
import { errors } from './error';
const putTokenOnUrl = async (url, params, options) => {
let token = await getToken();
if (!token) {
throw errors.tokenMissing();
}
token = encrypt(token);
return {
url,
options,
params: [...params, ['token', token]],
};
};
const putTokenToBody = async (url, data, params, options) => {
let token = await getToken();
if (!token) {
throw errors.tokenMissing();
}
token = encrypt(token);
return {
url,
params,
options,
data: {
...data,
token,
},
};
};
const parseResponse = (response) => {
const { errorCode, data, message } = response;
if (errorCode === 0) {
return data;
} else {
throw new Error(message || data);
}
};
export default {
get: {
onRequest: async (url, params, options, auth) => {
if (auth) {
return putTokenOnUrl(url, params, options);
}
},
onResponse: parseResponse,
},
post: {
onRequest: async (url, data, params, options, auth) => {
if (auth) {
return putTokenToBody(url, data, params, options);
}
},
onResponse: parseResponse,
},
delete: {
onRequest: async (url, params, options, auth) => {
if (auth) {
return putTokenOnUrl(url, params, options);
}
},
onResponse: parseResponse,
},
};
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
import _ from 'lodash'; import { isNil, defaults } from 'lodash';
import { fetch } from './polyfill'; import { fetch } from './polyfill';
import { encrypt } from './helper';
import { checkStatus, normParams, parseObject } from './http-helper'; import { checkStatus, normParams, parseObject } from './http-helper';
import { getToken } from './auth'; import middleware from './middleware';
import { errors } from './error';
const defaultOptions = { const defaultOptions = {
headers: { headers: {
...@@ -12,26 +10,20 @@ const defaultOptions = { ...@@ -12,26 +10,20 @@ const defaultOptions = {
}, },
}; };
export default async function post(url, data, params = {}, options = {}, auth = true) { export default async function post(url, data, params = {}, options = {}, auth = true) {
if (!data) { if (!data) {
data = {}; data = {};
} }
if (auth) { params = normParams(params);
const token = await getToken(); const res = await middleware.post.onRequest(url, data, params, options, auth);
if (!token) { let queryParams = res ? res.params : params;
return Promise.reject(errors.tokenMissing()); queryParams = queryParams.map(([k, v]) => (isNil(v) ? k : `${k}=${encodeURIComponent(v)}`));
}
data.token = encrypt(token);
}
let queryParams = normParams(params);
queryParams = queryParams.map(([k, v]) => (_.isNil(v) ? k : `${k}=${encodeURIComponent(v)}`));
queryParams = queryParams.join('&'); queryParams = queryParams.join('&');
let realUrl = url; let realUrl = res ? res.url : url;
if (queryParams) { if (queryParams) {
realUrl = `${url}?${queryParams}`; realUrl = `${url}?${queryParams}`;
} }
const realOptions = _.defaults(options, defaultOptions); const realOptions = defaults(res ? res.options : options, defaultOptions);
if (!realOptions.headers) { if (!realOptions.headers) {
realOptions.headers = { realOptions.headers = {
Accept: 'application/json', Accept: 'application/json',
...@@ -42,5 +34,5 @@ export default async function post(url, data, params = {}, options = {}, auth = ...@@ -42,5 +34,5 @@ export default async function post(url, data, params = {}, options = {}, auth =
realOptions.body = JSON.stringify(data); realOptions.body = JSON.stringify(data);
return fetch(realUrl, realOptions) return fetch(realUrl, realOptions)
.then(checkStatus) .then(checkStatus)
.then(parseObject); .then(resp => parseObject(resp, middleware.post.onResponse));
} }
import _ from 'lodash'; import { isNil, defaults } from 'lodash';
import { fetch } from './polyfill'; import { fetch } from './polyfill';
import { encrypt } from './helper';
import { getToken } from './auth';
import { errors } from './error';
import { checkStatus, normParams, parseObject } from './http-helper'; import { checkStatus, normParams, parseObject } from './http-helper';
import middleware from './middleware';
const defaultOptions = { const defaultOptions = {
headers: { Accept: 'application/json' }, headers: { Accept: 'application/json' },
...@@ -19,23 +17,19 @@ const defaultOptions = { ...@@ -19,23 +17,19 @@ const defaultOptions = {
* @return {object} An object containing either "data" or "err" * @return {object} An object containing either "data" or "err"
*/ */
export default async function request(url, params = {}, options = {}, auth = true) { export default async function request(url, params = {}, options = {}, auth = true) {
let token; const normedParams = normParams(params);
if (auth) { const res = await middleware.get.onRequest(url, normedParams, options, auth);
token = await getToken(); const newUrl = res ? res.url : url;
if (!token) { const newParams = res ? res.params : normedParams;
return Promise.reject(errors.tokenMissing()); const newOptions = res ? res.options : options;
} let queryParams = newParams.map(([k, v]) => (isNil(v) ? k : `${k}=${encodeURIComponent(v)}`));
token = encrypt(token);
}
let queryParams = token ? [...normParams(params), ['token', token]] : normParams(params);
queryParams = queryParams.map(([k, v]) => (_.isNil(v) ? k : `${k}=${encodeURIComponent(v)}`));
queryParams = queryParams.join('&'); queryParams = queryParams.join('&');
let realUrl = url; let realUrl = newUrl;
if (queryParams) { if (queryParams) {
realUrl = `${url}?${queryParams}`; realUrl = `${url}?${queryParams}`;
} }
return fetch(realUrl, _.defaults(options, defaultOptions)) return fetch(realUrl, defaults(newOptions, defaultOptions))
.then(checkStatus) .then(checkStatus)
.then(parseObject); .then(resp => parseObject(resp, middleware.get.onResponse));
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论