Skip to content

Commit 9df0423

Browse files
authoredFeb 26, 2023
fix: pinging the server at 127.0.0.1 when using just the port number (#357)
* add 0.0.0.0 server ci example * add explicit zero test * add timeout to the waiting failing demo * add test and explanation * run more tests in Node v16 * add debugging * update what we run on node v16 * switch from localhost to 127.0.0.1 for default host * prepend localhost and common host names with http * update readme * ipv6 test * update localhost in README snippets
1 parent 0e9984e commit 9df0423

File tree

7 files changed

+136
-32
lines changed

7 files changed

+136
-32
lines changed
 

‎.github/workflows/ci.yml

+38-1
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,34 @@ jobs:
7171
- name: Run demo expect 403 code 📊
7272
run: npm run demo-expect-403
7373

74+
tests-node-v16:
75+
runs-on: ubuntu-latest
76+
steps:
77+
- name: Checkout 🛎
78+
uses: actions/checkout@v3
79+
80+
- uses: actions/setup-node@v3
81+
with:
82+
node-version: 16
83+
84+
- name: Node version 🖨️
85+
run: node -v
86+
87+
- name: NPM install
88+
uses: bahmutov/npm-install@v1
89+
90+
- name: Run json-server test
91+
run: npm run demo-json-server
92+
93+
- name: Run explicit 0.0.0.0 host example
94+
run: npm run demo-zero-explicit
95+
96+
- name: Run 0.0.0.0 host with 127.0.0.1 url
97+
run: npm run demo-zero-127
98+
99+
- name: Run 0.0.0.0 host example
100+
run: npm run demo-zero
101+
74102
tests-node-v18:
75103
runs-on: ubuntu-latest
76104
steps:
@@ -93,8 +121,17 @@ jobs:
93121
- name: Run ::1 host example
94122
run: npm run demo-ip6
95123

124+
- name: Run explicit 0.0.0.0 host example
125+
run: npm run demo-zero-explicit
126+
127+
- name: Run 0.0.0.0 host with 127.0.0.1 url
128+
run: npm run demo-zero-127
129+
130+
- name: Run 0.0.0.0 host example
131+
run: npm run demo-zero
132+
96133
release:
97-
needs: ['tests1', 'tests2', 'tests-node-v18']
134+
needs: ['tests1', 'tests2', 'tests-node-v16', 'tests-node-v18']
98135
if: github.ref == 'refs/heads/master'
99136
runs-on: ubuntu-latest
100137
steps:

‎README.md

+28-9
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,17 @@ You can use either `start-server-and-test`, `server-test` or `start-test` comman
8080
You can use `:` in front of port number like `server-test :8080`, so all these are equivalent
8181

8282
```
83-
start-server-and-test start http://localhost:8080 test
84-
server-test start http://localhost:8080 test
85-
server-test http://localhost:8080 test
83+
start-server-and-test start http://127.0.0.1:8080 test
84+
server-test start http://127.0.0.1:8080 test
85+
server-test http://127.0.0.1:8080 test
86+
server-test 127.0.0.1:8080 test
8687
start-test :8080 test
8788
start-test 8080 test
8889
start-test 8080
8990
```
9091

92+
**Tip:** I highly recommend you specify the full url instead of the port, see the `localhost vs 0.0.0.0 vs 127.0.0.1` section later in this README.
93+
9194
### Options
9295

9396
If you use convention and name your scripts "start" and "test" you can simply provide URL
@@ -102,7 +105,7 @@ If you use convention and name your scripts "start" and "test" you can simply pr
102105
}
103106
```
104107

105-
You can also shorten local url to just port, the code below is equivalent to checking `http://localhost:8080`.
108+
You can also shorten local url to just port, the code below is equivalent to checking `http://127.0.0.1:8080`.
106109

107110
```json
108111
{
@@ -165,7 +168,7 @@ If you want to start the server, wait for it to respond, and then run multiple t
165168
}
166169
```
167170

168-
The above script `ci` after the `localhost:9000` responds executes the `npm run test:unit` command. Then when it finishes it runs `npm run test:e2e`. If the first or second command fails, the `ci` script fails. Of course, your mileage on Windows might vary.
171+
The above script `ci` after the `127.0.0.1:9000` responds executes the `npm run test:unit` command. Then when it finishes it runs `npm run test:e2e`. If the first or second command fails, the `ci` script fails. Of course, your mileage on Windows might vary.
169172

170173
#### expected
171174

@@ -198,7 +201,7 @@ Then you can execute tests simply:
198201
```text
199202
$ npx start-test 'http-server -c-1 .' 8080 'cypress run'
200203
starting server using command "http-server -c-1 ."
201-
and when url "http://localhost:8080" is responding
204+
and when url "http://127.0.0.1:8080" is responding
202205
running tests using command "cypress run"
203206
Starting up http-server, serving .
204207
...
@@ -211,12 +214,28 @@ $ yarn start-test 'http-server -c-1 .' 8080 'cypress run'
211214
yarn run v1.13.0
212215
$ /private/tmp/test-t/node_modules/.bin/start-test 'http-server -c-1 .' 8080 'cypress run'
213216
starting server using command "http-server -c-1 ."
214-
and when url "http://localhost:8080" is responding
217+
and when url "http://127.0.0.1:8080" is responding
215218
running tests using command "cypress run"
216219
Starting up http-server, serving .
217220
...
218221
```
219222

223+
## localhost vs 0.0.0.0 vs 127.0.0.1
224+
225+
The latest versions of Node and some web servers listen on host `0.0.0.0` which _no longer means localhost_. Thus if you specify _just the port number_, like `:3000`, this package will try `http://127.0.0.1:3000` to ping the server. A good practice is to specify the full URL you would like to ping.
226+
227+
```
228+
# same as "http://127.0.0.1:3000"
229+
start-server start 3000 test
230+
# better
231+
start-server start http://127.0.0.1:3000 test
232+
# or
233+
start-server start http://0.0.0.0:3000 test
234+
# of course, if your server is listening on localhost
235+
# you can still set the URL
236+
start-server start http://localhost:3000 test
237+
```
238+
220239
## Note for yarn users
221240

222241
By default, npm is used to run scripts, however you can specify that yarn is used as follows:
@@ -279,8 +298,8 @@ $ DEBUG=start-server-and-test npm run test
279298
start-server-and-test parsing CLI arguments: [ 'dev', '3000', 'subtask' ] +0ms
280299
start-server-and-test parsed args: { services: [ { start: 'npm run dev', url: [Array] } ], test: 'npm run subtask' }
281300
...
282-
making HTTP(S) head request to url:http://localhost:3000 ...
283-
HTTP(S) error for http://localhost:3000 Error: Request failed with status code 404
301+
making HTTP(S) head request to url:http://127.0.0.1:3000 ...
302+
HTTP(S) error for http://127.0.0.1:3000 Error: Request failed with status code 404
284303
```
285304

286305
### Disable HTTPS certificate checks

‎__snapshots__/utils-spec.js

+13-13
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ exports['utils getArguments allows 5 arguments 1'] = {
5353
{
5454
"start": "npm run start",
5555
"url": [
56-
"http://localhost:6000"
56+
"http://127.0.0.1:6000"
5757
]
5858
},
5959
{
6060
"start": "start:web",
6161
"url": [
62-
"http://localhost:6010"
62+
"http://127.0.0.1:6010"
6363
]
6464
}
6565
],
@@ -80,13 +80,13 @@ exports['utils getArguments determines NPM script for each command 1'] = {
8080
{
8181
"start": "npm run startA",
8282
"url": [
83-
"http://localhost:6000"
83+
"http://127.0.0.1:6000"
8484
]
8585
},
8686
{
8787
"start": "npm run startB",
8888
"url": [
89-
"http://localhost:6010"
89+
"http://127.0.0.1:6010"
9090
]
9191
}
9292
],
@@ -117,7 +117,7 @@ exports['utils getArguments returns 3 arguments 1'] = {
117117
{
118118
"start": "npm run start",
119119
"url": [
120-
"http://localhost:8080"
120+
"http://127.0.0.1:8080"
121121
]
122122
}
123123
],
@@ -142,7 +142,7 @@ exports['utils getArguments understands custom commands 1'] = {
142142
{
143143
"start": "custom-command --with argument",
144144
"url": [
145-
"http://localhost:3000"
145+
"http://127.0.0.1:3000"
146146
]
147147
}
148148
],
@@ -154,9 +154,9 @@ exports['utils getArguments understands several ports 1'] = {
154154
{
155155
"start": "npm run start",
156156
"url": [
157-
"http://localhost:3000",
158-
"http://localhost:4000",
159-
"http://localhost:5000"
157+
"http://127.0.0.1:3000",
158+
"http://127.0.0.1:4000",
159+
"http://127.0.0.1:5000"
160160
]
161161
}
162162
],
@@ -168,7 +168,7 @@ exports['utils getArguments understands single :port 1'] = {
168168
{
169169
"start": "npm run start",
170170
"url": [
171-
"http://localhost:3000"
171+
"http://127.0.0.1:3000"
172172
]
173173
}
174174
],
@@ -180,7 +180,7 @@ exports['utils getArguments understands single port 1'] = {
180180
{
181181
"start": "npm run start",
182182
"url": [
183-
"http://localhost:3000"
183+
"http://127.0.0.1:3000"
184184
]
185185
}
186186
],
@@ -192,7 +192,7 @@ exports['utils getArguments understands start plus url 1'] = {
192192
{
193193
"start": "start-server",
194194
"url": [
195-
"http://localhost:6000"
195+
"http://127.0.0.1:6000"
196196
]
197197
}
198198
],
@@ -204,7 +204,7 @@ exports['utils getArguments understands url plus test 1'] = {
204204
{
205205
"start": "npm run start",
206206
"url": [
207-
"http://localhost:6000"
207+
"http://127.0.0.1:6000"
208208
]
209209
}
210210
],

‎package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,11 @@
100100
"demo-commands": "node src/bin/start.js 'node test/server.js --port 8800' 8800 'node test/client --port 8800'",
101101
"demo-multiple": "node src/bin/start.js 'node test/server --port 6000' 6000 'node test/server --port 6010' 6010 'curl http://127.0.0.1:6000 && curl http://127.0.0.1:6010'",
102102
"demo-multiple-test-commands": "node src/bin/start.js 9000 'npm run message && npm run message2'",
103-
"demo-json-server": "node src/bin/start.js 'json-server test/data.json' 3000 'echo json-server working'",
104-
"demo-ip6": "node src/bin/start.js 'node test/ip6.mjs' 8000 'echo server with ::1 working'"
103+
"demo-json-server": "WAIT_ON_TIMEOUT=10000 DEBUG=start-server-and-test node src/bin/start.js 'json-server test/data.json' localhost:3000 'echo json-server working'",
104+
"demo-ip6": "WAIT_ON_TIMEOUT=10000 DEBUG=start-server-and-test node src/bin/start.js 'node test/ip6.mjs' localhost:8000 'echo server with ::1 working'",
105+
"demo-zero": "WAIT_ON_TIMEOUT=10000 node src/bin/start.js 'node test/zero.mjs' 8000 'echo server with 0.0.0.0 working'",
106+
"demo-zero-127": "WAIT_ON_TIMEOUT=10000 node src/bin/start.js 'node test/zero.mjs' http://127.0.0.1:8000 'echo server with 0.0.0.0 working'",
107+
"demo-zero-explicit": "node src/bin/start.js 'node test/zero.mjs' http://0.0.0.0:8000 'echo server with 0.0.0.0 working'"
105108
},
106109
"devDependencies": {
107110
"@types/node": "^18.14.1",

‎src/utils-spec.js

+19-4
Original file line numberDiff line numberDiff line change
@@ -201,12 +201,27 @@ describe('utils', () => {
201201
})
202202

203203
it('changes port to localhost', () => {
204-
la(arrayEq(normalizeUrl('6006'), ['http://localhost:6006']))
205-
la(arrayEq(normalizeUrl(8080), ['http://localhost:8080']))
204+
la(arrayEq(normalizeUrl('6006'), ['http://127.0.0.1:6006']))
205+
la(arrayEq(normalizeUrl(8080), ['http://127.0.0.1:8080']))
206206
})
207207

208208
it('changes :port to localhost', () => {
209-
la(arrayEq(normalizeUrl(':6006'), ['http://localhost:6006']))
209+
la(arrayEq(normalizeUrl(':6006'), ['http://127.0.0.1:6006']))
210+
})
211+
212+
it('appends http to localhost', () => {
213+
la(arrayEq(normalizeUrl('localhost'), ['http://localhost']))
214+
la(arrayEq(normalizeUrl('localhost:3030'), ['http://localhost:3030']))
215+
})
216+
217+
it('appends http to 127.0.0.1', () => {
218+
la(arrayEq(normalizeUrl('127.0.0.1'), ['http://127.0.0.1']))
219+
la(arrayEq(normalizeUrl('127.0.0.1:3030'), ['http://127.0.0.1:3030']))
220+
})
221+
222+
it('appends http to 0.0.0.0', () => {
223+
la(arrayEq(normalizeUrl('0.0.0.0'), ['http://0.0.0.0']))
224+
la(arrayEq(normalizeUrl('0.0.0.0:3030'), ['http://0.0.0.0:3030']))
210225
})
211226

212227
it('returns original argument if does not know what to do', () => {
@@ -217,7 +232,7 @@ describe('utils', () => {
217232
it('parses multiple resources', () => {
218233
la(
219234
arrayEq(normalizeUrl(':6006|http://foo.com'), [
220-
'http://localhost:6006',
235+
'http://127.0.0.1:6006',
221236
'http://foo.com'
222237
])
223238
)

‎src/utils.js

+16-3
Original file line numberDiff line numberDiff line change
@@ -189,28 +189,41 @@ const isUrlOrPort = input => {
189189
})
190190
}
191191

192+
/**
193+
* Returns the host to ping if the user specified just the port.
194+
* For a long time, the safest bet was "localhost", but now modern
195+
* web servers seem to bind to "0.0.0.0", which means
196+
* the "127.0.0.1" works better
197+
*/
198+
const getHost = () => '127.0.0.1'
199+
192200
const normalizeUrl = input => {
193201
const str = is.string(input) ? input.split('|') : [input]
202+
const defaultHost = getHost()
194203

195204
return str.map(s => {
196205
if (is.url(s)) {
197206
return s
198207
}
199208

200209
if (is.number(s) && is.port(s)) {
201-
return `http://localhost:${s}`
210+
return `http://${defaultHost}:${s}`
202211
}
203212

204213
if (!is.string(s)) {
205214
return s
206215
}
207216

217+
if (s.startsWith('localhost') || s.startsWith('127.0.0.1') || s.startsWith('0.0.0.0')) {
218+
return `http://${s}`
219+
}
220+
208221
if (is.port(parseInt(s))) {
209-
return `http://localhost:${s}`
222+
return `http://${defaultHost}:${s}`
210223
}
211224

212225
if (s[0] === ':') {
213-
return `http://localhost${s}`
226+
return `http://${defaultHost}${s}`
214227
}
215228
// for anything else, return original argument
216229
return s

‎test/zero.mjs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import http from 'node:http';
2+
3+
// Create a local server to receive data from
4+
const server = http.createServer();
5+
6+
// Listen to the request event
7+
server.on('request', (request, res) => {
8+
console.log('server responding')
9+
res.writeHead(200, { 'Content-Type': 'application/json' });
10+
res.end(JSON.stringify({
11+
data: 'Hello World!',
12+
}));
13+
});
14+
15+
server.listen(8000, '0.0.0.0', () => {
16+
console.log('server is listening on 0.0.0.0:8000')
17+
});

0 commit comments

Comments
 (0)
Please sign in to comment.