@@ -2,7 +2,7 @@ import axios from 'axios'
22import clonedeep from 'lodash/cloneDeep'
33import Qs from 'qs'
44import { ConcurrencyQueue } from './concurrency-queue'
5- import { isHost } from './Util'
5+ import { isHost , normalizePlugins } from './Util'
66
77export default function contentstackHttpClient ( options ) {
88 const defaultConfig = {
@@ -109,6 +109,11 @@ export default function contentstackHttpClient (options) {
109109 const instance = axios . create ( axiosOptions )
110110 instance . httpClientParams = options
111111 instance . concurrencyQueue = new ConcurrencyQueue ( { axios : instance , config } )
112+
113+ // Normalize and store plugins
114+ const plugins = normalizePlugins ( config . plugins )
115+
116+ // Request interceptor for versioning strategy (must run first)
112117 instance . interceptors . request . use ( ( request ) => {
113118 if ( request . versioningStrategy && request . versioningStrategy === 'path' ) {
114119 request . baseURL = request . baseURL . replace ( '{api-version}' , version )
@@ -117,5 +122,117 @@ export default function contentstackHttpClient (options) {
117122 }
118123 return request
119124 } )
125+
126+ // Request interceptor for plugins (runs after versioning)
127+ if ( plugins . length > 0 ) {
128+ instance . interceptors . request . use (
129+ ( request ) => {
130+ // Run all onRequest hooks sequentially, using return values
131+ let currentRequest = request
132+ for ( const plugin of plugins ) {
133+ try {
134+ if ( typeof plugin . onRequest === 'function' ) {
135+ const result = plugin . onRequest ( currentRequest )
136+ // Use returned value if provided, otherwise use current request
137+ if ( result !== undefined ) {
138+ currentRequest = result
139+ }
140+ }
141+ } catch ( error ) {
142+ // Log error and continue with next plugin
143+ if ( config . logHandler ) {
144+ config . logHandler ( 'error' , {
145+ name : 'PluginError' ,
146+ message : `Error in plugin onRequest: ${ error . message } ` ,
147+ error : error
148+ } )
149+ }
150+ }
151+ }
152+ return currentRequest
153+ } ,
154+ ( error ) => {
155+ // Handle request errors - run plugins even on error
156+ let currentConfig = error . config
157+ for ( const plugin of plugins ) {
158+ try {
159+ if ( typeof plugin . onRequest === 'function' && currentConfig ) {
160+ const result = plugin . onRequest ( currentConfig )
161+ // Use returned value if provided, otherwise use current config
162+ if ( result !== undefined ) {
163+ currentConfig = result
164+ error . config = currentConfig
165+ }
166+ }
167+ } catch ( pluginError ) {
168+ if ( config . logHandler ) {
169+ config . logHandler ( 'error' , {
170+ name : 'PluginError' ,
171+ message : `Error in plugin onRequest (error handler): ${ pluginError . message } ` ,
172+ error : pluginError
173+ } )
174+ }
175+ }
176+ }
177+ return Promise . reject ( error )
178+ }
179+ )
180+
181+ // Response interceptor for plugins
182+ instance . interceptors . response . use (
183+ ( response ) => {
184+ // Run all onResponse hooks sequentially for successful responses
185+ // Use return values from plugins
186+ let currentResponse = response
187+ for ( const plugin of plugins ) {
188+ try {
189+ if ( typeof plugin . onResponse === 'function' ) {
190+ const result = plugin . onResponse ( currentResponse )
191+ // Use returned value if provided, otherwise use current response
192+ if ( result !== undefined ) {
193+ currentResponse = result
194+ }
195+ }
196+ } catch ( error ) {
197+ // Log error and continue with next plugin
198+ if ( config . logHandler ) {
199+ config . logHandler ( 'error' , {
200+ name : 'PluginError' ,
201+ message : `Error in plugin onResponse: ${ error . message } ` ,
202+ error : error
203+ } )
204+ }
205+ }
206+ }
207+ return currentResponse
208+ } ,
209+ ( error ) => {
210+ // Handle response errors - run plugins even on error
211+ // Pass the error object (which may contain error.response if server responded)
212+ let currentError = error
213+ for ( const plugin of plugins ) {
214+ try {
215+ if ( typeof plugin . onResponse === 'function' ) {
216+ const result = plugin . onResponse ( currentError )
217+ // Use returned value if provided, otherwise use current error
218+ if ( result !== undefined ) {
219+ currentError = result
220+ }
221+ }
222+ } catch ( pluginError ) {
223+ if ( config . logHandler ) {
224+ config . logHandler ( 'error' , {
225+ name : 'PluginError' ,
226+ message : `Error in plugin onResponse (error handler): ${ pluginError . message } ` ,
227+ error : pluginError
228+ } )
229+ }
230+ }
231+ }
232+ return Promise . reject ( currentError )
233+ }
234+ )
235+ }
236+
120237 return instance
121238}
0 commit comments