miragejs: Axios request that are sent via `passthrough()` don't resolve

Hi,

I have a problem with using miragejs and axios together. When I send a request to a mocked route which has a handler, everything is ok: promise is pending, requests gets sent and I get 200, promise resolves. But when I send a request to a not mocked route and passthrough is configured to let it pass, strange thing happens: promise is pending, request gets sent and I get 200 but the promise doesn’t resolve, it’s stuck in pending state. It only happens when I use axios and when I try to send a request to a route that is not mocked, fetch works just fine. Here’s a simple example: https://codesandbox.io/s/buggy-passthrough-example-o919g

Is it possible to somehow make miragejs work with Axios?

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 23
  • Comments: 26

Most upvoted comments

For me, it neither got fixed by degrading Axios or Miragejs version and after digging more into Mirage and Pretenderjs repo issues I found a fix that works with any Axios and Miragejs version:

Note: You should add this code after const server = new Pretender() OR INSIDE const server = new Server({ routes () { //add code here } });

`// FIX -->
const NativeXMLHttpRequest = window.XMLHttpRequest;

window.XMLHttpRequest = function XMLHttpRequest() {
  const request = new NativeXMLHttpRequest(arguments);
  delete request.onloadend;
  return request;
};
// <-- FIX`

@cah-briangantzler @bbansalWolfPack

If anyone else having this problem, you can fix it by patching axios currently latest version 0.27.2 with this diff

diff --git a/node_modules/axios/lib/adapters/xhr.js b/node_modules/axios/lib/adapters/xhr.js
index 76d7e7a..7e11408 100644
--- a/node_modules/axios/lib/adapters/xhr.js
+++ b/node_modules/axios/lib/adapters/xhr.js
@@ -80,7 +80,7 @@ module.exports = function xhrAdapter(config) {
     if ('onloadend' in request) {
       // Use onloadend if available
       request.onloadend = onloadend;
-    } else {
+    }
       // Listen for ready state to emulate onloadend
       request.onreadystatechange = function handleLoad() {
         if (!request || request.readyState !== 4) {
@@ -98,7 +98,7 @@ module.exports = function xhrAdapter(config) {
         // so we should call onloadend on the next 'tick'
         setTimeout(onloadend);
       };
-    }
+

You can place this file to your project’s root /patches/axios+0.27.2.patch
do npm i patch-package and add to your package.json scripts section "postinstall": "patch-package"

That makes change permanent for local development but I would remove it on production along with disabling Mirage mock API server.

I fix the issue downgrading axios to 0.21.0 and works with miragejs [ 0.1.41, 0.1.42.0, 0.1.43.0 ]

Thank you @xerardoo that works for me ❤️

I’m experiencing the same exact issue here, with a catch: Only new installations are having this behavior, even though they’re using the same version as old installations (0.1.41)

It’s very odd, because we’ve been using miragejs in this project for more than a year, our server definitions are untouched for months, and all of a sudden it stops resolving promises.

I wonder if it’s related to some axios update that may have broken some compatibility

I had the same problem and tried to play around with different Axios versions. I got it running with latest miragejs (0.1.42) and with an older Axios version (0.21.0). Hopefully that helps.

@AzitaAzimi The issue is with the child dependency package of Mirage which is pretenderjs that handles the passthrough requests and as per version upgrades there has been a mismatch with some event handling with the new version of axios, hence I found the above-mentioned solution in prentenderjs issues for which the link is attached below and consider as a temporary fix as there are open pull requests to solve this issue but the package is not maintained due to which pull requests are not merged. Hence, I would advise whenever one upgrades miragejs package please comment out the temporary fix and check if the issue is resolved by them then remove the temporary fix else continue with it till it is officially fixed.

https://github.com/pretenderjs/pretender/issues/354#issuecomment-1299297701

For me, it neither got fixed by degrading Axios or Miragejs version and after digging more into Mirage and Pretenderjs repo issues I found a fix that works with any Axios and Miragejs version:

Note: You should add this code after const server = new Pretender() OR INSIDE const server = new Server({ routes () { //add code here } });

`// FIX -->
const NativeXMLHttpRequest = window.XMLHttpRequest;

window.XMLHttpRequest = function XMLHttpRequest() {
  const request = new NativeXMLHttpRequest(arguments);
  delete request.onloadend;
  return request;
};
// <-- FIX`

Worked for me as well! Thank you 👍 , like @AzitaAzimi I’d be curious to know how does it fix it?

The problem with downgrading is that axios 0.21.1 has known vulnerabilities. This issue seems to stem from the xhr adapter that was changed in axios 0.21.2. The handler request.onreadystatechange is not added to the request anymore and therefore the promise is never resolved.

For me, it neither got fixed by degrading Axios or Miragejs version and after digging more into Mirage and Pretenderjs repo issues I found a fix that works with any Axios and Miragejs version:

Note: You should add this code after const server = new Pretender() OR INSIDE const server = new Server({ routes () { //add code here } });

`// FIX -->
const NativeXMLHttpRequest = window.XMLHttpRequest;

window.XMLHttpRequest = function XMLHttpRequest() {
  const request = new NativeXMLHttpRequest(arguments);
  delete request.onloadend;
  return request;
};
// <-- FIX`

Dear @sunnykanakhara, This solution worked for me as well. I searched about the code to find why and how this code can solve the problem. I think it creates a new XMLHttpRequest object and then deletes the onloadend property from it before returning it. However, there is one potential issue that should be considered. The arguments object passed to the NativeXMLHttpRequest constructor is not valid. The XMLHttpRequest constructor does not take any arguments, so passing arguments to it will likely result in an error.

Still, my investigation has not satisfied my confusion, so could you please let me know what is the secret?

@kurdin

I’ve had issue with applying your patch, this is my version:

File name: /patches/axios+0.27.2.patch

diff --git a/node_modules/axios/lib/adapters/xhr.js b/node_modules/axios/lib/adapters/xhr.js
index 76d7e7a..900964c 100644
--- a/node_modules/axios/lib/adapters/xhr.js
+++ b/node_modules/axios/lib/adapters/xhr.js
@@ -80,7 +80,7 @@ module.exports = function xhrAdapter(config) {
     if ('onloadend' in request) {
       // Use onloadend if available
       request.onloadend = onloadend;
-    } else {
+    }
       // Listen for ready state to emulate onloadend
       request.onreadystatechange = function handleLoad() {
         if (!request || request.readyState !== 4) {
@@ -98,7 +98,6 @@ module.exports = function xhrAdapter(config) {
         // so we should call onloadend on the next 'tick'
         setTimeout(onloadend);
       };
-    }
 
     // Handle browser request cancellation (as opposed to a manual cancellation)
     request.onabort = function handleAbort() {

Error that happened to me:

**ERROR** Failed to apply patch for package axios
    
  This happened because the patch file patches/axios+0.27.2.patch could not be parsed.

Miragejs is not very maintained currently. If it’s important to you that this gets fixed, I’d suggest digging in to the code and putting up a PR. I’ll be happy to review/merge, but I can’t spend time fixing issues, unfortunately.

@engelkes-finstreet thanks for sharing! I tried it out on my end and it worked!