Last active
          February 26, 2023 14:01 
        
      - 
      
 - 
        
Save gugadev/36483bae3aec4b283b5af8653ca699cb to your computer and use it in GitHub Desktop.  
Revisions
- 
        
gugadev revised this gist
Feb 26, 2023 . 1 changed file with 9 additions and 5 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -15,14 +15,18 @@ type FetchResponseType = "text" | "json" | "blob" | "arrayBuffer" type FetchInterceptorArgs = { config: FetchInterceptorResponseConfig, responseTypes: FetchResponseType[] } function createFetchResponseInterceptor({ config, responseTypes }: FetchInterceptorArgs) { /** * @description Proxifies the Response.prototype[text|json|blob|arrayBuffer] * instance methods to check by status codes and fire custom logic. * If you don't want to continue with .text(), .json(), .blob() or * .arrayBuffer() if there is a non 200 code, just return in every if. */ const createInterceptor = (responseType: FetchResponseType): FetchResponseType => { return new Proxy(Response.prototype[responseType], { apply(target: any, obj: any, args: any) { if (obj.status === 401 && config.onUnauthenticated) { config.onUnauthenticated(obj) } @@ -35,7 +39,7 @@ function createFetchResponseInterceptor({ config, responseTypes }: FetchIntercep if (obj.status === 502 && config.onRateLimit) { config.onRateLimit(obj) } return target.call(obj, args) }, }) } @@ -69,7 +73,7 @@ function createFetchResponseInterceptor({ config, responseTypes }: FetchIntercep // If you use Object.seal instead of Object.freeze, // the browser will attach a new interceptor every // time the code is re-executed, producing a duplicated, // truplicated, etc. Response instance methods calls. try { Response.prototype.text = text Response.prototype.json = json  - 
        
gugadev revised this gist
Feb 26, 2023 . 1 changed file with 8 additions and 1 deletion.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -63,12 +63,19 @@ function createFetchResponseInterceptor({ config, responseTypes }: FetchIntercep responseTypes: ["text", "json", "blob", "arrayBuffer"] }) // use this empty catch because we want to ignore // the errors when the browsers tries to assing // things into it's prototype because it's freezed. // If you use Object.seal instead of Object.freeze, // the browser will attach a new interceptor every // time the code is re-executed, producing a duplicated, // truplicated, etc. the method calls. try { Response.prototype.text = text Response.prototype.json = json Response.prototype.blob = blob Response.prototype.arrayBuffer = arrayBuffer Object.freeze(Response.prototype) // do not use seal } catch {} const statusCodes = [200, 401, 403, 500]  - 
        
gugadev created this gist
Feb 26, 2023 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,83 @@ type InterceptorResponse = Omit< typeof Response.prototype, 'text' | 'formData' | 'blob' | 'json' | 'arrayBuffer' > type FetchInterceptorResponseConfig = { onUnauthenticated?: (obj: InterceptorResponse) => void onInternalError?: (obj: InterceptorResponse) => void onForbidden?: (obj: InterceptorResponse) => void onRateLimit?: (obj: InterceptorResponse) => void } type FetchResponseType = "text" | "json" | "blob" | "arrayBuffer" type FetchInterceptorArgs = { config: FetchInterceptorResponseConfig, responseTypes: FetchResponseType[] } function createFetchResponseInterceptor({ config, responseTypes }: FetchInterceptorArgs) { const createInterceptor = (responseType: FetchResponseType) => { return new Proxy(Response.prototype[responseType], { apply(target: any, obj: any, args: any) { const response: string | object | ArrayBuffer | Blob | FormData = target.call(obj, args) if (obj.status === 401 && config.onUnauthenticated) { config.onUnauthenticated(obj) } if (obj.status === 403 && config.onForbidden) { config.onForbidden(obj) } if (obj.status === 500 && config.onInternalError) { config.onInternalError(obj) } if (obj.status === 502 && config.onRateLimit) { config.onRateLimit(obj) } return response }, }) } return responseTypes.map(responseType => createInterceptor(responseType)) } /* Using interceptor */ ;(async () => { const [text, json, blob, arrayBuffer] = createFetchResponseInterceptor({ config: { onUnauthenticated: obj => { console.log(`Signing out because it's not authenticated`) // do sign out... }, onForbidden: obj => { console.log(`User has not permissions to access to this resource.`) // do something else if you want... }, onInternalError: obj => { console.log(`Something went wrong at server side`) // do something else if you want... }, }, responseTypes: ["text", "json", "blob", "arrayBuffer"] }) try { Response.prototype.text = text Response.prototype.json = json Response.prototype.blob = blob Response.prototype.arrayBuffer = arrayBuffer Object.freeze(Response.prototype) } catch {} const statusCodes = [200, 401, 403, 500] for (const statusCode of statusCodes) { const res = await fetch(`https://httpstat.us/${statusCode}`); const body = await res.text(); if (res.ok) { console.log("Server responded with: ", body) } } })()