1 | # axios-url-template
|
2 |
|
3 | [![npm version](https://img.shields.io/npm/v/axios-url-template.svg?style=flat-square)](https://www.npmjs.org/package/axios-url-template)
|
4 | ![Build status](https://github.com/rafw87/axios-url-template/actions/workflows/test.yml/badge.svg)
|
5 | [![Coverage Status](https://coveralls.io/repos/github/rafw87/axios-url-template/badge.svg?branch=master)](https://coveralls.io/github/rafw87/axios-url-template?branch=master)
|
6 | [![install size](https://packagephobia.now.sh/badge?p=axios-url-template)](https://packagephobia.now.sh/result?p=axios-url-template)
|
7 |
|
8 | This package adds support for URL templates to [Axios](https://www.npmjs.com/package/axios),
|
9 | according to [RFC 6570 URI Template specification](https://datatracker.ietf.org/doc/html/rfc6570).
|
10 |
|
11 | It uses [url-template](https://www.npmjs.com/package/url-template) package and wraps it into Axios interceptor.
|
12 |
|
13 | ## Installation
|
14 |
|
15 | ```bash
|
16 | $ npm install axios-url-template
|
17 | ```
|
18 | or
|
19 | ```bash
|
20 | $ yarn add axios-url-template
|
21 | ```
|
22 |
|
23 |
|
24 | ## Usage
|
25 |
|
26 | ```typescript
|
27 | import { urlTemplateInterceptor } from "axios-url-template";
|
28 |
|
29 | // attaching interceptor to Axios global instance
|
30 | axios.interceptors.request.use(urlTemplateInterceptor());
|
31 |
|
32 | // passing options
|
33 | axios.interceptors.request.use(urlTemplateInterceptor({
|
34 | urlAsTemplate: false,
|
35 | }));
|
36 |
|
37 | // attaching interceptor to Axios instance
|
38 | const instance = axios.create({ /* ... */});
|
39 | instance.interceptors.request.use(urlTemplateInterceptor());
|
40 |
|
41 | // example requests
|
42 |
|
43 | const response1 = await axios.get('/test/{id}', {
|
44 | urlTemplateParams: { id: 123 },
|
45 | });
|
46 | // config:
|
47 | // {
|
48 | // url: '/test/123',
|
49 | // urlTemplate: '/test/{id}',
|
50 | // urlTemplateParams: { id: 123 }
|
51 | // }
|
52 |
|
53 | const response2 = await axios.get('/test{?foo,bar}', {
|
54 | urlTemplateParams: { foo: 'foo1', bar: 'bar1' },
|
55 | });
|
56 | // config:
|
57 | // {
|
58 | // url: '/test?foo=foo1&bar=bar1',
|
59 | // urlTemplate: '/test{?foo,bar}',
|
60 | // urlTemplateParams: { foo: 'foo1', bar: 'bar1' },
|
61 | // }
|
62 |
|
63 | const response3 = await axios.request({
|
64 | urlTemplate: '/test/{id}',
|
65 | urlTemplateParams: { id: 123 },
|
66 | });
|
67 | // config:
|
68 | // {
|
69 | // url: '/test/123',
|
70 | // urlTemplate: '/test/{id}',
|
71 | // urlTemplateParams: { id: 123 },
|
72 | // }
|
73 | ```
|
74 | Interceptor may be also registered using shortcut method:
|
75 | ```typescript
|
76 | import { useUrlTemplateInterceptor } from "axios-url-template";
|
77 |
|
78 | useUrlTemplateInterceptor(axios);
|
79 |
|
80 | const instance = axios.create({ /* ... */});
|
81 | useUrlTemplateInterceptor(instance, { urlAsTemplate: false });
|
82 | ```
|
83 |
|
84 |
|
85 | ### Options
|
86 | - `urlAsTemplate`: when set to `true`, then `url` is treated as template and possibly interpolated.
|
87 | When set to `false` it does not touch `url` unless `urlTemplate` is explicitly specified. Default: `true`.
|
88 |
|
89 |
|
90 | ## Behavior
|
91 |
|
92 | When `urlTemplate` (and optional `urlTemplateParams`) is provided in Axios config object,
|
93 | this interceptor uses it to generate `url`. Those template fields are persisted in config object,
|
94 | so after execution config will contain all of those fields:
|
95 | - `url`
|
96 | - `urlTemplate`
|
97 | - `urlTemplateParams` - when no parameter are provided it will be an empty object
|
98 |
|
99 | When `urlAsTemplate` option is set to `true` (default), then `url` will be also treated as url template
|
100 | and passed through interpolation. In this case, `urlTemplate` and `urlTemplateParams`
|
101 | will be added accordingly, and `url` will be replaced with interpolated value,
|
102 | giving the same effect as for `urlTemplate`.
|
103 |
|
104 | When no `urlTemplate` is provided and `urlAsTemplate` option is set to `false` then
|
105 | the interceptor passes request config without any changes.
|
106 |
|
107 |
|
108 | ## Use cases
|
109 | This interceptor helps to automate things like structural logging and/or request metrics,
|
110 | where low cardinality route is preferred over full URL with dynamic parts.
|
111 |
|
112 | When request is performed in traditional way, there is no easy option to retrieve such route
|
113 | from full URL provided in call to Axios. It may be provided as custom fields,
|
114 | but it increases overhead and may generate mistakes.
|
115 |
|
116 | The interceptor ensures consistency, as actual URL provided to Axios is computed
|
117 | from route (url template) and parameters.
|
118 |
|
119 | Example (in TypeScript):
|
120 | ```typescript
|
121 | import axios, { AxiosResponse } from 'axios';
|
122 | import { useUrlTemplateInterceptor } from "axios-url-template";
|
123 |
|
124 | // example logging interceptor
|
125 | function loggingInterceptor(response: AxiosResponse) {
|
126 | const { status, statusText } = response;
|
127 | const { urlTemplate, urlTemplateParams } = response.config;
|
128 | const url = axios.getUri(response.config);
|
129 |
|
130 | const logObject = {
|
131 | status,
|
132 | statusText,
|
133 | url,
|
134 | route: urlTemplate, // low cardinality value is preferred
|
135 | routeParams: urlTemplateParams, // dynamic route parts
|
136 | };
|
137 |
|
138 | // do something with such log object
|
139 | console.log(JSON.stringify(logObject, null, 2));
|
140 | }
|
141 |
|
142 | // attach url template interceptor
|
143 | useUrlTemplateInterceptor(axios, { urlAsTemplate: true })
|
144 |
|
145 | // attach logging interceptor
|
146 | axios.interceptors.response.use(loggingInterceptor);
|
147 |
|
148 | async function execute() {
|
149 | await axios.get("https://postman-echo.com/status/{status}", {
|
150 | urlTemplateParams: { status: 201 },
|
151 | });
|
152 |
|
153 | await axios.get("https://postman-echo.com/get{?foo,bar}", {
|
154 | urlTemplateParams: { foo: "foo1", bar: "bar1" },
|
155 | params: { baz: 'baz1' }, // additional param, not being part of route
|
156 | });
|
157 | }
|
158 | execute().catch(console.error);
|
159 | ```
|
160 |
|
161 | Result:
|
162 | ```jsonl
|
163 | {
|
164 | "status": 201,
|
165 | "statusText": "Created",
|
166 | "url": "https://postman-echo.com/status/201",
|
167 | "route": "https://postman-echo.com/status/{status}",
|
168 | "routeParams": {
|
169 | "status": 201
|
170 | }
|
171 | }
|
172 | {
|
173 | "status": 200,
|
174 | "statusText": "OK",
|
175 | "url": "https://postman-echo.com/get?foo=foo1&bar=bar1&baz=baz1",
|
176 | "route": "https://postman-echo.com/get{?foo,bar}",
|
177 | "routeParams": {
|
178 | "foo": "foo1",
|
179 | "bar": "bar1"
|
180 | }
|
181 | }
|
182 | ```
|
183 |
|
184 | ## License
|
185 | MIT
|