jeffbski / wait-on

wait-on is a cross-platform command line utility and Node.js API which will wait for files, ports, sockets, and http(s) resources to become available
MIT License
1.87k stars 77 forks source link

wait-on failure for localhost of react-app Node.js 18 #137

Closed MikeMcC399 closed 1 year ago

MikeMcC399 commented 1 year ago

Environment

ubuntu-22.04 on GitHub Node.js 18.14.1

wait-on 7.0.1

Problem description

wait-on fails waiting for http://localhost:3000 of react-app on GitHub in an ubuntu-22.04 runner using the current default Node.js 18.14.1. The problem does not happen using Node.js 16.19.1.

Node.js 18 is the default version on GitHub runners since Feb 18, 2023.

verbose logs show:

Run npx wait-on http://localhost:3000 -t 15000 -v
  npx wait-on http://localhost:3000 -t 15000 -v
  shell: /usr/bin/bash -e {0}
waiting for 1 resources: http://localhost:3000
making HTTP(S) head request to  url:http://localhost:3000 ...
  HTTP(S) error for http://localhost:3000 Error: connect ECONNREFUSED ::1:3000
  .
  repeated multiple times
  .
  .
Error: Timed out waiting for: http://localhost:3000
making HTTP(S) head request to  url:http://localhost:3000 ...
    at /home/runner/work/react-app-test/react-app-test/node_modules/wait-on/lib/wait-on.js:132:31
  HTTP(S) error for http://localhost:3000 Error: connect ECONNREFUSED ::1:3000
    at doInnerSub (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/operators/mergeInternals.js:22:31)
    at outerNext (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/operators/mergeInternals.js:17:70)
    at OperatorSubscriber._this._next (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/operators/OperatorSubscriber.js:33:21)
    at Subscriber.next (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/Subscriber.js:51:18)
making HTTP(S) head request to  url:http://localhost:3000 ...
    at AsyncAction.work (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/observable/timer.js:28:28)
  HTTP(S) error for http://localhost:3000 Error: connect ECONNREFUSED ::1:3000
    at AsyncAction._execute (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/scheduler/AsyncAction.js:79:18)
wait-on(1851) Timed out waiting for: http://localhost:3000; exiting with error
    at AsyncAction.execute (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/scheduler/AsyncAction.js:67:26)
    at AsyncScheduler.flush (/home/runner/work/react-app-test/react-app-test/node_modules/rxjs/dist/cjs/internal/scheduler/AsyncScheduler.js:38:33)
    at listOnTimeout (node:internal/timers:569:17)
Error: Process completed with exit code 1.

netstat shows the following listener:

Run netstat -lnt | grep 3000
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN

Steps to reproduce

GitHub

View workflow log https://github.com/MikeMcC399/react-app-test/actions/workflows/test-react-app-wait-on.yml or

fork https://github.com/MikeMcC399/react-app-test and run .github/workflows/test-react-app-wait-on.yml

Workaround

wait for http://127.0.0.1:3000 instead of http://localhost:3000

Related issues

MikeMcC399 commented 1 year ago

Due to GitHub setting Node.js default to 18 recently, this issue and related issues are becoming more visible.

Possible resolutions

See https://nodejs.org/dist/latest-v18.x/docs/api/net.html#socketconnect

autoSelectFamily : If set to true, it enables a family autodetection algorithm that loosely implements section 5 of RFC 8305. The all option passed to lookup is set to true and the sockets attempts to connect to all obtained IPv6 and IPv4 addresses, in sequence, until a connection is established. The first returned AAAA address is tried first, then the first returned A address and so on. Each connection attempt is given the amount of time specified by the autoSelectFamilyAttemptTimeout option before timing out and trying the next address. Ignored if the family option is not 0 or if localAddress is set. Connection errors are not emitted if at least one connection succeeds. Default: false.

metcoder95 commented 1 year ago

Also worth it to mention that autoSelectFamily is not backported (and most likely it won't be) to Node.js versions < 18, meaning that fully moving into autoSelectFamily will result in a major bump.

If looking to preserve support for older versions, a combination of both approaches can be done.

MikeMcC399 commented 1 year ago

@jeffbski

This seems quite the showstopper for wait-on under Node.js 18 and later. Are you able to comment and share your plans?

sinedied commented 1 year ago

The 127.0.0.1 workaround does not work for me.

Regarding this, it's possible to change the default DNS resolution order with dns.setDefaultResultOrder('ipv4first');, but it's not helping either for me. On Node 18, it's stuck indefinitely on any tcp:<host>:<port> combination šŸ˜¢

MikeMcC399 commented 1 year ago

@sinedied

The 127.0.0.1 workaround does not work for me.

Are you using the react-app or something else? If it is something else then you should open a new issue.

It depends on the server what the right workaround is. It could be using 127.0.0.1 instead of localhost or it could be [::1] instead of localhost. Some other servers can be started in an alternate way, by specifying a host parameter 0.0.0.0 (for instance -h 0.0.0.0, -host 0.0.0.0, -HOST 0.0.0.0 according to the appropriate documentation) which makes them listen on both IPv4 and IPv6. That does not work for all development servers however.

sinedied commented 1 year ago

I finally found a workaround, had to use a mix of localhost and 127.0.0.1 depending on the host server. But yeah it's really not user friendly :/

MikeMcC399 commented 1 year ago
tommymarshall commented 1 year ago

Ran into this same problem as well. Thankfully (I guess?) I know what port my app has to run on and have had no problems changing from wait-on http://localhost:300 to wait-on tcp:3000.

MikeMcC399 commented 1 year ago

I retested this issue and it is still reproducible on Node.js 18.16.0 which remains as the LTS version until Node.js 20.x takes over the LTS role on Oct 24, 2023 (see Node.js release schedule).

The issue is however not reproducible on Node.js 20.2.0. See job 9155121075 which succeeds.

Updating to Node.js 20.x may therefore be a workaround for some situations.

I will leave this issue open, probably until Node.js 20.x gets LTS status.

GianCastle commented 1 year ago

I started to have the same issue on my CRA app (react scripts 4) and NodeJS 18. After I switched from localhost:3000 to 127.0.0.1:3000 it started to work again

MikeMcC399 commented 1 year ago

Status

Mitigations

So, now closing this issue, as there is nothing more to do here.