@nxtedition/nxt-undici 2.0.8 → 2.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,34 +4,16 @@ import { findHeader, isDisturbed, parseURL } from '../utils.js'
4
4
  const redirectableStatusCodes = [300, 301, 302, 303, 307, 308]
5
5
 
6
6
  class Handler {
7
- constructor(opts, { dispatch, handler }) {
7
+ constructor(opts, { dispatch, handler, count = 0 }) {
8
8
  this.dispatch = dispatch
9
9
  this.handler = handler
10
10
  this.opts = opts
11
- this.abort = null
12
- this.aborted = false
13
- this.reason = null
14
- this.maxCount = Number.isFinite(opts.follow) ? opts.follow : opts.follow?.count ?? 0
15
-
16
- this.count = 0
17
- this.location = null
18
-
19
- this.handler.onConnect((reason) => {
20
- this.aborted = true
21
- if (this.abort) {
22
- this.abort(reason)
23
- } else {
24
- this.reason = reason
25
- }
26
- })
11
+ this.redirectOpts = null
12
+ this.count = count
27
13
  }
28
14
 
29
15
  onConnect(abort) {
30
- if (this.aborted) {
31
- abort(this.reason)
32
- } else {
33
- this.abort = abort
34
- }
16
+ return this.handler.onConnect(abort)
35
17
  }
36
18
 
37
19
  onUpgrade(statusCode, headers, socket) {
@@ -51,60 +33,65 @@ class Handler {
51
33
  return this.handler.onHeaders(statusCode, headers, resume, statusText)
52
34
  }
53
35
 
54
- if (isDisturbed(this.opts.body)) {
55
- throw new Error(`Disturbed request cannot be redirected.`)
56
- }
36
+ const location = findHeader(headers, 'location')
57
37
 
58
- this.location = findHeader(headers, 'location')
59
-
60
- if (!this.location) {
38
+ if (!location) {
39
+ // TODO (perf): Consume body?
61
40
  throw new Error(`Missing redirection location .`)
62
41
  }
63
42
 
64
43
  this.count += 1
65
44
 
66
45
  if (typeof this.opts.follow === 'function') {
67
- if (!this.opts.follow(this.location, this.count)) {
46
+ if (!this.opts.follow(location, this.count)) {
68
47
  return this.handler.onHeaders(statusCode, headers, resume, statusText)
69
48
  }
70
49
  } else {
71
- if (this.count >= this.maxCount) {
72
- throw new Error(`Max redirections reached: ${this.maxCount}.`)
50
+ const maxCount = Number.isFinite(this.opts.follow)
51
+ ? this.opts.follow
52
+ : Number.isFinite(this.opts.follow?.count)
53
+ ? this.opts.follow?.count
54
+ : 0
55
+
56
+ if (this.count >= maxCount) {
57
+ // TODO (perf): Consume body?
58
+ throw new Error(`Max redirections reached: ${maxCount}.`)
73
59
  }
74
60
  }
75
61
 
62
+ if (isDisturbed(this.opts.body)) {
63
+ // TODO (perf): Consume body?
64
+ throw new Error(`Disturbed request cannot be redirected.`)
65
+ }
66
+
76
67
  const { origin, pathname, search } = parseURL(
77
- new URL(this.location, this.opts.origin && new URL(this.opts.path, this.opts.origin)),
68
+ new URL(location, this.opts.origin && new URL(this.opts.path, this.opts.origin)),
78
69
  )
79
70
  const path = search ? `${pathname}${search}` : pathname
80
71
 
81
72
  // Remove headers referring to the original URL.
82
73
  // By default it is Host only, unless it's a 303 (see below), which removes also all Content-* headers.
83
74
  // https://tools.ietf.org/html/rfc7231#section-6.4
84
- this.opts = {
75
+ this.redirectOpts = {
85
76
  ...this.opts,
86
77
  headers: cleanRequestHeaders(
87
78
  this.opts.headers,
88
79
  statusCode === 303,
89
80
  this.opts.origin !== origin,
90
81
  ),
91
- follow: {
92
- ...this.opts.follow,
93
- count: this.maxCount - 1,
94
- },
95
82
  path,
96
83
  origin,
97
84
  }
98
85
 
99
86
  // https://tools.ietf.org/html/rfc7231#section-6.4.4
100
87
  // In case of HTTP 303, always replace method to be either HEAD or GET
101
- if (statusCode === 303 && this.opts.method !== 'HEAD') {
102
- this.opts = { ...this.opts, method: 'GET', body: null }
88
+ if (statusCode === 303 && this.redirectOpts.method !== 'HEAD') {
89
+ this.redirectOpts = { ...this.redirectOpts, method: 'GET', body: null }
103
90
  }
104
91
  }
105
92
 
106
93
  onData(chunk) {
107
- if (this.location) {
94
+ if (this.redirectOpts) {
108
95
  /*
109
96
  https://tools.ietf.org/html/rfc7231#section-6.4
110
97
 
@@ -128,7 +115,7 @@ class Handler {
128
115
  }
129
116
 
130
117
  onComplete(trailers) {
131
- if (this.location) {
118
+ if (this.redirectOpts) {
132
119
  /*
133
120
  https://tools.ietf.org/html/rfc7231#section-6.4
134
121
 
@@ -138,8 +125,12 @@ class Handler {
138
125
  See comment on onData method above for more detailed informations.
139
126
  */
140
127
  this.dispatch(
141
- this.opts,
142
- new Handler(this.opts, { handler: this.handler, dispatch: this.dispatch }),
128
+ this.redirectOpts,
129
+ new Handler(this.redirectOpts, {
130
+ handler: this.handler,
131
+ dispatch: this.dispatch,
132
+ count: this.count,
133
+ }),
143
134
  )
144
135
  } else {
145
136
  return this.handler.onComplete(trailers)
@@ -181,5 +172,5 @@ function cleanRequestHeaders(headers, removeContent, unknownOrigin) {
181
172
 
182
173
  export default (dispatch) => (opts, handler) =>
183
174
  opts.follow != null
184
- ? dispatch(opts, new Handler(opts, { handler, dispatch }))
175
+ ? dispatch(opts, new Handler(opts, { handler, dispatch, count: 0 }))
185
176
  : dispatch(opts, handler)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/nxt-undici",
3
- "version": "2.0.8",
3
+ "version": "2.0.10",
4
4
  "license": "MIT",
5
5
  "author": "Robert Nagy <robert.nagy@boffins.se>",
6
6
  "main": "lib/index.js",