Skip to content

Commit

Permalink
New: interceptors in axios client
Browse files Browse the repository at this point in the history
  • Loading branch information
pustovitDmytro committed Feb 8, 2021
1 parent 9cdba1f commit f43898d
Show file tree
Hide file tree
Showing 7 changed files with 2,589 additions and 654 deletions.
2 changes: 1 addition & 1 deletion examples/chat/app.js
@@ -1,6 +1,6 @@
import jsonServer from 'json-server';

const port = 3000;
const port = process.env.PORT || 3001;
const users = [ {
'id' : 1,
'name' : 'Leigh',
Expand Down
3,079 changes: 2,504 additions & 575 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Expand Up @@ -29,7 +29,7 @@
"@babel/cli": "^7.2.3",
"@babel/core": "^7.3.4",
"@babel/node": "^7.2.2",
"@babel/plugin-proposal-class-properties": "^7.3.4",
"@babel/plugin-proposal-class-properties": "^7.12.1",
"@babel/plugin-proposal-decorators": "^7.3.0",
"@babel/plugin-proposal-object-rest-spread": "^7.3.4",
"@babel/plugin-proposal-optional-chaining": "^7.2.0",
Expand All @@ -41,6 +41,7 @@
"@semantic-release/git": "^7.0.8",
"@semantic-release/npm": "^5.1.7",
"@semantic-release/release-notes-generator": "^7.1.4",
"ava": "^3.14.0",
"babel-eslint": "^10.0.1",
"babel-plugin-module-resolver": "^3.2.0",
"body-parser": "^1.19.0",
Expand All @@ -63,13 +64,14 @@
"json-server": "^0.15.0",
"mocha": "^6.1.4",
"nyc": "^14.1.1",
"semantic-release": "^15.13.19"
"semantic-release": "^17.3.0"
},
"dependencies": {
"axios": "^0.19.0",
"chalk": "^2.4.2",
"dot-prop": "^5.1.0",
"handlebars": "^4.4.5",
"js-yaml": "^3.14.1",
"myrmidon": "^1.4.3",
"supertest": "^4.0.2",
"uuid": "^3.3.2"
Expand Down
121 changes: 62 additions & 59 deletions src/requests/Axios.js
@@ -1,72 +1,75 @@
import axios from 'axios';
import { decorate, lastItem, isObject } from '../utils';
import Native from 'axios';
import { decorate } from '../utils';

export default class Axios {
constructor(chronicle) {
this._chronicle = chronicle;
const axios = Native.create({});

if (chronicle) {
axios.interceptors.request.use((config) => {
if (!config.url) {
return config;
}

const currentUrl = new URL(config.url, config.baseURL);

Object.entries(config.params || {}).forEach(([ key, val ]) => {
currentUrl.pathname = currentUrl.pathname.replace(`:${key}`, encodeURIComponent(val));
});

const authPart = currentUrl.username && currentUrl.password ? `${currentUrl.username}:${currentUrl.password}` : '';

return {
...config,
baseURL : `${currentUrl.protocol}//${authPart}${currentUrl.host}`,
url : currentUrl.pathname
};
});

axios.interceptors.response.use(response => {
const { config, request } = response;
const context = config.with;

if (!context) return response;
const action = chronicle.action(context);

action.request = {
url : new URL(config.url, config.baseURL),
headers : config.headers,
method : config.method,
body : config.data
};

action.response = {
body : response.data,
headers : response.header,
http : {
version : request.res.httpVersion
},
status : {
code : response.status,
message : response.statusText
},
type : response.type,
charset : response.charset
};

return response;
}, (error) => {
throw error;
});
}

return this._decorate(axios);
return decorate(axios, this);
}

_decorate(target) {
return decorate(target, this);
}

_process(response, context) {
if (!context) return;
const { config, request } = response;

const action = this._chronicle.action(context);

action.request = {
url : config.url,
headers : config.headers,
method : config.method,
body : config.data
};

action.response = {
body : response.data,
headers : response.header,
http : {
version : request.res.httpVersion
},
status : {
code : response.status,
message : response.statusText
},
type : response.type,
charset : response.charset
};
}

'before_default'({ params }) {
const config = lastItem(params);

if (isObject(config)) {
const { with: _with, ...axiosConfig } = config; // eslint-disable-line no-unused-vars

return [ ...params.slice(0, -1), axiosConfig ];
}

return params;
}

'after_default' = ({ rawParams, result }) => {
const config = lastItem(rawParams);

if (isObject(config)) {
this._process(result, config.with);
}

return result;
}

'after_get'(params, result) {
return this._decorate(result);
}
with(context) {
this._with = context;

'after_post'(params, result) {
return this._decorate(result);
return this;
}
}
30 changes: 15 additions & 15 deletions src/requests/Express.js
Expand Up @@ -13,7 +13,7 @@ function arrayKeyFilter(keys) {
}

function chronicleMiddleware(req, res, next) {
const action = this._chronicle.action(this);
const action = this.chronicle.action(this.context);
const originalWrite = res.write;
const originalEnd = res.end;
const chunks = [];
Expand Down Expand Up @@ -53,13 +53,13 @@ function chronicleMiddleware(req, res, next) {
message : res.statusMessage
}
};
const save = this._config?.save;
const save = this.config?.save;

if (save) {
const actions = this._chronicle._actions;
const actions = this.chronicle._actions;

if (isFunction(save)) {
save(action, actions, this._chronicle, this._config);
save(action, actions, this.chronicle, this.config);
} else {
let isApproved = true;

Expand All @@ -74,7 +74,7 @@ function chronicleMiddleware(req, res, next) {
server._chronicles.push(
Promise.all(
save.files.map(
({ path, ...opts }) => this._chronicle.save(path, opts)
({ path, ...opts }) => this.chronicle.save(path, opts)
)
)
);
Expand All @@ -95,26 +95,26 @@ export default class Express {

generateMiddleWare = (...args) => {
return (...expressArgs) => {
const config = this.getConfig(...args, ...expressArgs);
const context = this.getContext(...args, ...expressArgs);

chronicleMiddleware.call(config, ...expressArgs);
chronicleMiddleware.call({
context,
chronicle : this._chronicle,
config : this._config
}, ...expressArgs);
};
}

getConfig(...args) {
getContext(...args) {
if (typeof args[0] === 'function') {
return {
...args[0](...args.slice(1)),
_chronicle : this._chronicle,
_config : this._config
...args[0](...args.slice(1))
};
}

return {
_chronicle : this._chronicle,
_config : this._config,
group : args[0],
title : args[1]
group : args[0],
title : args[1]
};
}
}
4 changes: 2 additions & 2 deletions src/utils/decorators.js
Expand Up @@ -31,7 +31,7 @@ function _onParams({ params }) {
return params;
}

export function decorate(target, methods) {
export function decorate(target, methods = {}) {
const isDecorateFunction = isFunction(target);

const defaultConfig = {
Expand Down Expand Up @@ -64,7 +64,7 @@ export function decorate(target, methods) {
const onSuccessMethod = injectMethodNames.find(m => m === `after_${methodName}`);

if (isDecorateFunction && [ 'caller', 'caller', 'arguments' ].includes(methodName)) return;
if (!onParamsMethod && !onSuccessMethod) return;
if (!onParamsMethod && !onSuccessMethod) return decorated[methodName] = target[methodName];
const config = {
onParams : onParamsMethod ? methods[onParamsMethod] : _onParams,
onSuccess : onSuccessMethod ? methods[onSuccessMethod] : _onSuccess,
Expand Down
1 change: 1 addition & 0 deletions tests/requests/axios.client.test.js
Expand Up @@ -42,6 +42,7 @@ test('Axios default function request with chronicle', async function () {
body : data
});
});

after(async () => {
await factory.cleanup();
});

0 comments on commit f43898d

Please sign in to comment.