mswjs / msw

Industry standard API mocking for JavaScript.
https://mswjs.io
MIT License
15.93k stars 517 forks source link

Image src not intercepted when using IP address instead of localhost in address bar #1045

Closed ccpu closed 2 years ago

ccpu commented 2 years ago

It seems that when using an IP address in the address bar (in my case http://192.168.1.120:3000/) the image src is not intercepted/detected by MSW. But changing the URL to http://localhost:3000/ works perfectly fine!

Meanwhile, every other fetch request works whether the IP address or localhost is entered in the browser address bar.

Environment

Name Version
msw 0.36.3
browser chrome
OS windows 10

Request handlers

Here is the demo repo.


export const handlers = [
  rest.get("http://abc.com/image.jpg", async (req, res, ctx) => {
    var base64image =
      "iVBORw0KGgoAAAANSUhEUgAAAAUA AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO 9TXL0Y4OHwAAAABJRU5ErkJggg==";

    const buffer = _base64ToArrayBuffer(base64image);

    return res(
      ctx.set("Content-Length", buffer.byteLength.toString()),
      ctx.set("Content-Type", "image/jpeg"),
      ctx.body(buffer)
    );
  }),

  rest.get("http://abc.com/message", async (req, res, ctx) => {
    return res(ctx.json({ message: "Message form MSW handler using fetch!" }));
  }),
];

export const worker = setupWorker(...handlers);

worker.start().then(() => {
  ReactDOM.render(
    <React.StrictMode>
      <App />
    </React.StrictMode>,
    document.getElementById("root")
  );
});

Actual request

    // All request using fetch works fine
    fetch("http://abc.com/message").then(async (res) => {
      const body = await res.json();
      setMessage(body.message);
    });

   // Only work when using localhost in address bar
   <img
        src="http://abc.com/image.jpg"
        width={50}
        height={50}
        alt="Red Circle"
        style={{ border: "1px solid green" }}
      />

Current behavior

Image source intercepted when using localhost to navigate app but not working when using IP address.

Expected behavior

The image source must be intercepted regardless of using IP address or localhost for navigating the app,

Screenshots

with-localhost with ip address

kettanaito commented 2 years ago

Hi, @ccpu.

When using absolute URLs (or custom SSL certificates) you need to make your page trusted by the browser. Service Worker functions only with trusted pages, so I believe the "Not secure" label to the left of the location bar is the reason some requests are not intercepted.

To be frank, I didn't expect src and href of static assets to be captured by the worker at all. It's rather a discovery for me that they are.

We're going into detail about this in the Using local HTTPS section. Your case is not concerned with certificates but I've linked the section that describes how to make a hostname trusted in your browser.

Can you try following those steps and letting me know if the issue is gone?

ccpu commented 2 years ago

Hi, @kettanaito

Unfortunately, your suggestion did not work for me.

I am having this issue when using docker and playwright. For time being I am using the page.route API to manipulate request parameters.

Many thanks,

kettanaito commented 2 years ago

I recommend looking if it works fine locally and the issue occurs only in Docker. Then the root cause is likely related to the environmental change. There is an infinite number of things that can go wrong: from environmental variables to network connections and firewalls. I can't help you much here, you'd have to figure out what makes those requests fail in Docker.

If you can reproduce this locally, feel free to submit a reproduction repo and I will look into it. I'm 99% sure it's about trusted certificates, though.

ccpu commented 2 years ago

The problem occurred both locally and in Docker, although I don't use certificates, but I think it also has to do with security.

I have tried many chrome flag without success. It could be my machine! I have no idea, just can't think of anything else :(

As of now I am ok with the workaround mentioned above, but it would be nice to know the root cause.

This is the demo repo, no need for docker, just change localhost to the local IP address to see that the image not loading.

The image src served form the handler that is located in index.tsx file.

kettanaito commented 2 years ago

@ccpu, if you figure this out, please let me know in the comments, I'm curious.

This is the demo repo, no need for docker, just change localhost to the local IP address to see that the image not loading.

Sounds if I follow this I'll get that precise issue of an untrusted IP address. The worker won't register on an insecure hostname, and local IP would be insecure, unlike localhost. I think generating a self-signed certificate and adding it to your system may be a better option (you configure to trust a hostname on the system's level).

The image src served form the handler that is located in index.tsx file.

I'm still genuinely surprised this is possible 😃

ccpu commented 2 years ago

It appears that the docker environment requires an SSL certificate in order for service workers to work. I was hoping to ignore SSL, but apparently, it is not possible.

I should note that for the host itself, this can be accomplished using only the options --ignore-certificate-errors and --unsafely-treat-insecure-origin-as-secure. For Docker, however, SSL is also required.

Thank you for following up and suggestions.