Skip to content

Commit 7bb9716

Browse files
authored
feat: no match return 501 response (#2868)
1 parent 0fe070f commit 7bb9716

11 files changed

Lines changed: 250 additions & 249 deletions

lib/handle-request.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,14 @@ async function handleRequest(request) {
6262
)
6363

6464
if (!allowUnmocked) {
65-
const reqStr = common.stringifyRequest(request, requestBodyString)
66-
const err = new Error(`Nock: No match for request ${reqStr}`)
67-
err.code = 'ERR_NOCK_NO_MATCH'
68-
err.statusCode = err.status = 404
69-
throw err
65+
const body = JSON.stringify({
66+
code: 'ERR_NOCK_NO_MATCH',
67+
message: `Nock: No match for request ${common.stringifyRequest(request, requestBodyString)}`,
68+
})
69+
return new Response(body, {
70+
status: 501,
71+
headers: { 'Content-Type': 'application/json' },
72+
})
7073
}
7174
}
7275
}

migration_guides/migrating_to_15.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ The goal of this release is to create more predictable, modern and consistent AP
2424
})
2525
```
2626

27-
2. **`reply` now receives a `Request` object**
27+
2. **Unmatched requests now return Response objects with 501 status instead of throwing errors**
28+
Previously, nock would throw an error when no matching mock was found. Now it returns a Response object with status code 501 and a JSON body containing the code "ERR_NOCK_NO_MATCH". This makes error handling more consistent across different HTTP client libraries.
29+
30+
```js
31+
const { statusCode } = await got('http://example.test/not-mocked').catch(err => err.response)
32+
console.log(statusCode) // 501
33+
```
34+
35+
3. **`reply` now receives a `Request` object**
2836
The `interceptor` no longer contains the `req` property. Use the `Request` object passed to the `reply`.
2937

3038
```js

tests/got/test_basic_auth.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict'
22

33
const { expect } = require('chai')
4-
const assertRejects = require('assert-rejects')
54
const nock = require('../..')
65
const got = require('./got_client')
76

@@ -24,10 +23,11 @@ describe('basic auth with username and password', () => {
2423
})
2524

2625
it('fails when it doesnt match', async () => {
27-
await assertRejects(
28-
got('http://example.test/test'),
29-
/Nock: No match for request/,
30-
)
26+
const { statusCode, body } = await got('http://example.test/test', {
27+
responseType: 'json',
28+
}).catch(err => err.response)
29+
expect(statusCode).to.equal(501)
30+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
3131
})
3232
})
3333

@@ -50,9 +50,10 @@ describe('basic auth with username only', () => {
5050
})
5151

5252
it('fails when it doesnt match', async () => {
53-
await assertRejects(
54-
got('http://example.test/test'),
55-
/Nock: No match for request/,
56-
)
53+
const { statusCode, body } = await got('http://example.test/test', {
54+
responseType: 'json',
55+
}).catch(err => err.response)
56+
expect(statusCode).to.equal(501)
57+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
5758
})
5859
})

tests/got/test_body_match.js

Lines changed: 48 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
'use strict'
22

3-
const assertRejects = require('assert-rejects')
43
const { expect } = require('chai')
54
const FormData = require('form-data')
65
const nock = require('../..')
@@ -132,18 +131,28 @@ describe('`matchBody()`', () => {
132131
it("doesn't match body with mismatching keys", async () => {
133132
nock('http://example.test').post('/', { a: 'a' }).reply(200)
134133

135-
const request = got.post('http://example.test', {
136-
json: { a: 'a', b: 'b' },
137-
})
138-
await assertRejects(request, /Nock: No match for request/)
134+
const { statusCode, body } = await got
135+
.post('http://example.test', {
136+
json: { a: 'a', b: 'b' },
137+
responseType: 'json',
138+
})
139+
.catch(err => err.response)
140+
expect(statusCode).to.equal(501)
141+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
139142
})
140143

141144
// https://github.com/nock/nock/issues/1713
142145
it("doesn't match body with same number of keys but different keys", async () => {
143146
nock('http://example.test').post('/', { a: {} }).reply()
144147

145-
const request = got.post('http://example.test', { json: { b: 123 } })
146-
await assertRejects(request, /Nock: No match for request/)
148+
const { statusCode, body } = await got
149+
.post('http://example.test', {
150+
json: { b: 123 },
151+
responseType: 'json',
152+
})
153+
.catch(err => err.response)
154+
expect(statusCode).to.equal(501)
155+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
147156
})
148157

149158
it('match body with form multipart', async () => {
@@ -252,11 +261,14 @@ describe('`matchBody()`', () => {
252261
it("doesn't match utf-8 buffer body with mismatching utf-8 buffer", async () => {
253262
nock('http://example.test').post('/', Buffer.from('goodbye')).reply(200)
254263

255-
const request = got.post('http://example.test', {
256-
body: Buffer.from('hello'),
257-
})
258-
259-
await assertRejects(request, /Nock: No match for request/)
264+
const { statusCode, body } = await got
265+
.post('http://example.test', {
266+
body: Buffer.from('hello'),
267+
responseType: 'json',
268+
})
269+
.catch(err => err.response)
270+
expect(statusCode).to.equal(501)
271+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
260272
})
261273

262274
it('match binary buffer body with binary buffer', async () => {
@@ -277,32 +289,41 @@ describe('`matchBody()`', () => {
277289
.post('/', Buffer.from([0xff, 0xff, 0xfa]))
278290
.reply(200)
279291

280-
const request = got.post('http://example.test', {
281-
body: Buffer.from([0xff, 0xff, 0xff]),
282-
})
283-
284-
await assertRejects(request, /Nock: No match for request/)
292+
const { statusCode, body } = await got
293+
.post('http://example.test', {
294+
body: Buffer.from([0xff, 0xff, 0xff]),
295+
responseType: 'json',
296+
})
297+
.catch(err => err.response)
298+
expect(statusCode).to.equal(501)
299+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
285300
})
286301

287302
it("doesn't match binary buffer body with mismatching utf-8 buffer", async () => {
288303
nock('http://example.test')
289304
.post('/', Buffer.from([0xff, 0xff, 0xff]))
290305
.reply(200)
291306

292-
const request = got.post('http://example.test', {
293-
body: Buffer.from('hello'),
294-
})
295-
296-
await assertRejects(request, /Nock: No match for request/)
307+
const { statusCode, body } = await got
308+
.post('http://example.test', {
309+
body: Buffer.from('hello'),
310+
responseType: 'json',
311+
})
312+
.catch(err => err.response)
313+
expect(statusCode).to.equal(501)
314+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
297315
})
298316

299317
it("doesn't match utf-8 buffer body with mismatching binary buffer", async () => {
300318
nock('http://example.test').post('/', Buffer.from('hello')).reply(200)
301319

302-
const request = got.post('http://example.test', {
303-
body: Buffer.from([0xff, 0xff, 0xff]),
304-
})
305-
306-
await assertRejects(request, /Nock: No match for request/)
320+
const { statusCode, body } = await got
321+
.post('http://example.test', {
322+
body: Buffer.from([0xff, 0xff, 0xff]),
323+
responseType: 'json',
324+
})
325+
.catch(err => err.response)
326+
expect(statusCode).to.equal(501)
327+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
307328
})
308329
})

tests/got/test_header_matching.js

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use strict'
22

33
const http = require('node:http')
4-
const assertRejects = require('assert-rejects')
54
const { expect } = require('chai')
65
const sinon = require('sinon')
76
const nock = require('../..')
@@ -37,12 +36,12 @@ describe('Header matching', () => {
3736
.get('/')
3837
.reply(200, 'Hello World!')
3938

40-
await assertRejects(
41-
got('http://example.test/', {
42-
headers: { 'X-My-Headers': 456 },
43-
}),
44-
/Nock: No match for request/,
45-
)
39+
const { statusCode, body } = await got('http://example.test/', {
40+
headers: { 'X-My-Headers': 456 },
41+
responseType: 'json',
42+
}).catch(err => err.response)
43+
expect(statusCode).to.equal(501)
44+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
4645
})
4746

4847
it('should not consume mock request when match is declined by function', async () => {
@@ -53,12 +52,12 @@ describe('Header matching', () => {
5352
.get('/')
5453
.reply(200, 'Hello World!')
5554

56-
await assertRejects(
57-
got('http://example.test/', {
58-
headers: { '-My-Headers': 456 },
59-
}),
60-
/Nock: No match for request/,
61-
)
55+
const { statusCode, body } = await got('http://example.test/', {
56+
headers: { '-My-Headers': 456 },
57+
responseType: 'json',
58+
}).catch(err => err.response)
59+
expect(statusCode).to.equal(501)
60+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
6261

6362
expect(scope.isDone()).to.be.false()
6463
})
@@ -215,12 +214,12 @@ describe('Header matching', () => {
215214
.matchHeader('x-my-headers', () => false)
216215
.reply(200, 'Hello World!')
217216

218-
await assertRejects(
219-
got('http://example.test/', {
220-
headers: { 'X-My-Headers': 456 },
221-
}),
222-
/Nock: No match for request/,
223-
)
217+
const { statusCode, body } = await got('http://example.test/', {
218+
headers: { 'X-My-Headers': 456 },
219+
responseType: 'json',
220+
}).catch(err => err.response)
221+
expect(statusCode).to.equal(501)
222+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
224223
})
225224

226225
it('should not consume mock request when match is declined by function', async () => {
@@ -229,12 +228,12 @@ describe('Header matching', () => {
229228
.matchHeader('x-my-headers', () => false)
230229
.reply(200, 'Hello World!')
231230

232-
await assertRejects(
233-
got('http://example.test/', {
234-
headers: { '-My-Headers': 456 },
235-
}),
236-
/Nock: No match for request/,
237-
)
231+
const { statusCode, body } = await got('http://example.test/', {
232+
headers: { '-My-Headers': 456 },
233+
responseType: 'json',
234+
}).catch(err => err.response)
235+
expect(statusCode).to.equal(501)
236+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
238237

239238
expect(scope.isDone()).to.be.false()
240239
})
@@ -274,12 +273,14 @@ describe('Header matching', () => {
274273
.post('/')
275274
.reply(200, { status: 'ok' })
276275

277-
await assertRejects(
278-
got.post('http://example.test/', {
276+
const { statusCode, body } = await got
277+
.post('http://example.test/', {
279278
headers: { 'X-App-Token': 'apptoken' },
280-
}),
281-
/Nock: No match for request/,
282-
)
279+
responseType: 'json',
280+
})
281+
.catch(err => err.response)
282+
expect(statusCode).to.equal(501)
283+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
283284
})
284285

285286
it('should match when request header matches regular expression', async () => {
@@ -306,12 +307,14 @@ describe('Header matching', () => {
306307
.post('/')
307308
.reply()
308309

309-
await assertRejects(
310-
got.post('http://example.test/', {
310+
const { statusCode, body } = await got
311+
.post('http://example.test/', {
311312
headers: { 'X-My-Super-Power': 'mullet growing' },
312-
}),
313-
/Nock: No match/,
314-
)
313+
responseType: 'json',
314+
})
315+
.catch(err => err.response)
316+
expect(statusCode).to.equal(501)
317+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
315318

316319
expect(scope.isDone()).to.be.false()
317320
})
@@ -369,12 +372,14 @@ describe('Header matching', () => {
369372
.post('/')
370373
.reply()
371374

372-
await assertRejects(
373-
got.post('http://example.test/', {
375+
const { statusCode, body } = await got
376+
.post('http://example.test/', {
374377
headers: { 'X-My-Super-Power': 'mullet growing' },
375-
}),
376-
/Nock: No match/,
377-
)
378+
responseType: 'json',
379+
})
380+
.catch(err => err.response)
381+
expect(statusCode).to.equal(501)
382+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
378383

379384
expect(scope.isDone()).to.be.false()
380385
})
@@ -510,12 +515,12 @@ describe('Header matching', () => {
510515
.get('/')
511516
.reply()
512517

513-
await assertRejects(
514-
got('http://example.test/', {
515-
headers: { Cookie: 'cookie', Donut: 'donut' },
516-
}),
517-
/Nock: No match for request/,
518-
)
518+
const { statusCode, body } = await got('http://example.test/', {
519+
headers: { Cookie: 'cookie', Donut: 'donut' },
520+
responseType: 'json',
521+
}).catch(err => err.response)
522+
expect(statusCode).to.equal(501)
523+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
519524

520525
expect(scope.isDone()).to.be.false()
521526
})
@@ -572,12 +577,12 @@ describe('Header matching', () => {
572577
.get('/')
573578
.reply()
574579

575-
await assertRejects(
576-
got('http://example.test/', {
577-
headers: { Host: 'some.other.domain.test' },
578-
}),
579-
/Nock: No match for request/,
580-
)
580+
const { statusCode, body } = await got('http://example.test/', {
581+
headers: { Host: 'some.other.domain.test' },
582+
responseType: 'json',
583+
}).catch(err => err.response)
584+
expect(statusCode).to.equal(501)
585+
expect(body.code).to.equal('ERR_NOCK_NO_MATCH')
581586
})
582587
})
583588
})

0 commit comments

Comments
 (0)