1

I'm on a Mac and I'm attempting to run my k6 script against http://localhost:4200 (angular app) locally.

The angular app is running and I can access it via the browser and using curl.

My k6 script has the base URL set to http://localhost:4200. However, all requests are being made to http://127.0.0.1:4200 instead which is denied by MacOS.

How do I force k6 to NOT rewrite localhost to the loopback address?

EDIT

Adding various outputs of curl -vv.

localhost:4200

*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 4200 (#0)
> GET / HTTP/1.1
> Host: localhost:4200
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Access-Control-Allow-Origin: *
< Content-Type: text/html; charset=utf-8
< Accept-Ranges: bytes
< Content-Length: 942
< ETag: W/"3ae-UQojFJZul+b6hEhgbvnN6wFCVuA"
< Date: Thu, 20 Jan 2022 21:38:55 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< 
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>MyApp</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="assets/scripts/apm.js"></script>
  <link rel="apple-touch-icon" sizes="180x180" href="/assets/images/apple-touch-icon.png">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="icon" type="image/png" sizes="32x32" href="/assets/images/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/assets/images/favicon-16x16.png">
  <link rel="manifest" href="/site.webmanifest">
<link rel="stylesheet" href="styles.css"></head>
<body>
  <app-root></app-root>
<script src="runtime.js" type="module"></script><script src="polyfills.js" type="module"></script><script src="styles.js" defer></script><script src="vendor.js" type="module"></script><script src="main.js" type="module"></script></body>
</html>
* Connection #0 to host localhost left intact
* Closing connection 0

127.0.0.1:4200

*   Trying 127.0.0.1...
* TCP_NODELAY set
* Connection failed
* connect to 127.0.0.1 port 4200 failed: Connection refused
* Failed to connect to 127.0.0.1 port 4200: Connection refused
* Closing connection 0
curl: (7) Failed to connect to 127.0.0.1 port 4200: Connection refused

EDIT 2

Hosts file

127.0.0.1   localhost
255.255.255.255 broadcasthost
::1             localhost
# Added by Docker Desktop
# To allow the same kube context to work on the host and the container:
127.0.0.1 kubernetes.docker.internal
a11smiles
  • 1,190
  • 1
  • 9
  • 21
  • That's a weird "protection" feature. I researched and cannot find any indication that this is a real feature of macOS. What happens when you run curl against 127.0.0.0.1:4200? Are you running k6 inside a Docker container, but your application on the host? How are you verifying that requests to localhost are replaced with requests to 127.0.0.1? – knittl Jan 20 '22 at 17:50
  • When I run curl against the loopback I get a TCP socket refused (unlike running it against localhost which returns the webpage). I am not running in a container…both k6 and the app are running locally in the host. I know that the requests are being “rewritten” to the loopback because the k6 error is something like “tcp socket error: http://127.0.0.1:4200 connection refused” – a11smiles Jan 20 '22 at 17:55
  • Which makes sense, considering the hostname `localhost` resolves to the IP `127.0.0.1`. Can you [edit] your question and post output of both `curl -vv localhost:4200` and `curl -vv 127.0.0.1:4200`? – knittl Jan 20 '22 at 21:30
  • @knittl done. see edits. – a11smiles Jan 20 '22 at 21:42
  • I see. `curl` resolves to the IPv4 address of localhost. Can you post output of `curl -4 localhost:4200`? I can suggest one possible solution: use the IPv6 address `::1` in your k6 script. Probable cause: your Angular application only binds to IPv6 address `::1` and does _not_ listen to port 4200 on your IPv4 address. Change your application to listen on both protocols – knittl Jan 21 '22 at 06:31

1 Answers1

0

There is no application listening on port 4200 for your IPv4 address 127.0.0.1. 127.0.0.1 is the IPv4 loopback address. When k6 makes a request to localhost, this hostname resolves to the IPv4 127.0.0.1.

However, your application seems to be listening on port 4200 for your IPv6 address ::1. ::1 is the IPv6 loopback address. curl resolves the hostname localhost to its IPv6 address.

How are you binding your application to the port? Usually, when binding to all interfaces of a host, you'd use the special IP address 0.0.0.0.

I see a potential solutions:

  • Make your application bind to IPv4 and IPv6, usually done by binding to address 0.0.0.0.
  • Change your k6 script to connect to IPv6 ::1 directly
  • Specify --dns "policy=preferIPv6" or add dns:{policy:"preferIPv6"} to your options (since 0.29.0)
  • Disable IPv6 in your OS. This is a drastic change and I wouldn't recommend it
  • Change your hosts file to resolve localhost to the IPv4 address
knittl
  • 246,190
  • 53
  • 318
  • 364
  • updating the dns policy worked! thanks! – a11smiles Jan 21 '22 at 09:04
  • for the record...here's my `/etc/hosts` file: 127.0.0.1 localhost 255.255.255.255 broadcasthost ::1 localhost # Added by Docker Desktop # To allow the same kube context to work on the host and the container: 127.0.0.1 kubernetes.docker.internal – a11smiles Jan 21 '22 at 09:05
  • @a11smiles Do you see the last line? `::1 localhost # Added by Docker Desktop` (I think this is what breaks it). But the content is hard to read, you should [edit] it into your question instead – knittl Jan 21 '22 at 09:07
  • so, apparently, while the first entry of localhost resolves to 127.0.0.1, the second one (third line) resolving localhost to ::1 is taking presidence. Thanks again! – a11smiles Jan 21 '22 at 09:07
  • done. i added the hosts file to the original post. – a11smiles Jan 21 '22 at 09:08