braid-http 1.3.50 → 1.3.52

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.
@@ -266,9 +266,13 @@ async function braid_fetch (url, params = {}) {
266
266
  // see if we should retry..
267
267
  var retry = params.retry && // only try to reconnect if the user has chosen to
268
268
  e.name !== "AbortError" && // don't retry if the user has chosen to abort
269
- !e.startsWith?.('Parse error in headers') && // in this case, the server is spewing garbage, so reconnecting might be bad
270
- !e.message?.startsWith?.('Could not establish multiplexed request') && // the server has told us no, or is using a different version of multiplexing
271
- !cb_running // if an error is thrown in the callback, then it may not be good to reconnect, and generate more errors
269
+ !e.dont_retry && // some errors are unlikely to be fixed by retrying
270
+ !cb_running // if an error is thrown in the callback,
271
+ // then it may not be good to reconnect, and generate more errors
272
+
273
+ // some errors can be fixed by changing something, and retrying right away,
274
+ // for instance, for a duplicate multiplexer request id
275
+ if (e.dont_wait) waitTime = 0
272
276
 
273
277
  if (retry && !original_signal?.aborted) {
274
278
  // retry after some time..
@@ -278,7 +282,7 @@ async function braid_fetch (url, params = {}) {
278
282
  } else {
279
283
  // if we would have retried except that original_signal?.aborted,
280
284
  // then we want to return that as the error..
281
- if (retry && original_signal?.aborted) e = create_abort_error('already aborted')
285
+ if (retry && original_signal?.aborted) e = create_error('already aborted', {name: 'AbortError'})
282
286
 
283
287
  // let people know things are shutting down..
284
288
  subscription_counts_on_close?.()
@@ -288,7 +292,7 @@ async function braid_fetch (url, params = {}) {
288
292
  }
289
293
 
290
294
  try {
291
- if (original_signal?.aborted) throw create_abort_error('already aborted')
295
+ if (original_signal?.aborted) throw create_error('already aborted', {name: 'AbortError'})
292
296
 
293
297
  // We need a fresh underlying abort controller each time we connect
294
298
  underlying_aborter = new AbortController()
@@ -304,7 +308,7 @@ async function braid_fetch (url, params = {}) {
304
308
  // undocumented feature used by braid-chrome
305
309
  // to see the fetch args as they are right before it is actually called,
306
310
  // to display them for the user in the dev panel
307
- params.onFetch?.(url, params)
311
+ params.onFetch?.(url, params, underlying_aborter)
308
312
 
309
313
  // Now we run the original fetch....
310
314
 
@@ -363,7 +367,7 @@ async function braid_fetch (url, params = {}) {
363
367
  if (!err) {
364
368
  // check whether we aborted
365
369
  if (original_signal?.aborted)
366
- throw create_abort_error('already aborted')
370
+ throw create_error('already aborted', {name: 'AbortError'})
367
371
 
368
372
  // Yay! We got a new version! Tell the callback!
369
373
  cb_running = true
@@ -442,19 +446,16 @@ async function braid_fetch (url, params = {}) {
442
446
  give_up = false
443
447
  }
444
448
  if (give_up) {
445
- let e = new Error(`giving up because of http status: ${res.status}${(res.status === 401 || res.status === 403) ? ` (access denied)` : ''}`)
446
- subscription_error?.(e)
447
- return fail(e)
448
- }
449
- if (!res.ok) throw new Error(`status not ok: ${res.status}`)
449
+ if (subscription_cb) subscription_error?.(new Error(`giving up because of http status: ${res.status}${(res.status === 401 || res.status === 403) ? ` (access denied)` : ''}`))
450
+ } else if (!res.ok) throw new Error(`status not ok: ${res.status}`)
450
451
  }
451
452
 
452
- if (subscription_cb) start_subscription(subscription_cb, subscription_error)
453
-
454
- done(res)
453
+ if (subscription_cb && res.ok) start_subscription(subscription_cb, subscription_error)
455
454
 
456
455
  params?.retry?.onRes?.(res)
457
456
  waitTime = 1
457
+
458
+ done(res)
458
459
  } catch (e) { on_error(e) }
459
460
  }
460
461
  })
@@ -566,7 +567,7 @@ var subscription_parser = (cb) => ({
566
567
 
567
568
  // Or maybe there's an error to report upstream
568
569
  else if (this.state.result === 'error') {
569
- await this.cb(null, this.state.message)
570
+ await this.cb(null, create_error(this.state.message, {dont_retry: true}))
570
571
  return
571
572
  }
572
573
 
@@ -872,9 +873,9 @@ function ascii_ify(s) {
872
873
  return s.replace(/[^\x20-\x7E]/g, c => '\\u' + c.charCodeAt(0).toString(16).padStart(4, '0'))
873
874
  }
874
875
 
875
- function create_abort_error(msg) {
876
+ function create_error(msg, override) {
876
877
  var e = new Error(msg)
877
- e.name = 'AbortError'
878
+ if (override) Object.assign(e, override)
878
879
  return e
879
880
  }
880
881
 
@@ -915,6 +916,8 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
915
916
  var requests = new Map()
916
917
  var mux_error = null
917
918
  var try_deleting = new Set()
919
+ var not_used_timeout = null
920
+ var mux_aborter = new AbortController()
918
921
 
919
922
  function cleanup(e, stay_dead) {
920
923
  // the multiplexer stream has died.. let everyone know..
@@ -951,6 +954,7 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
951
954
  try {
952
955
  if (mux_params?.via === 'POST') throw 'skip multiplex method'
953
956
  var r = await braid_fetch(`${origin}/${multiplexer}`, {
957
+ signal: mux_aborter.signal,
954
958
  method: 'MULTIPLEX',
955
959
  headers: {'Multiplex-Version': multiplex_version},
956
960
  retry: true
@@ -958,7 +962,7 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
958
962
  if (r.status === 409) {
959
963
  var e = await r.json()
960
964
  if (e.error === 'Multiplexer already exists')
961
- return cleanup(new Error(e.error))
965
+ return cleanup(create_error(e.error, {dont_wait: true}))
962
966
  }
963
967
  if (!r.ok || r.headers.get('Multiplex-Version') !== multiplex_version)
964
968
  throw 'bad'
@@ -968,12 +972,13 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
968
972
  try {
969
973
  r = await braid_fetch(`${origin}/.well-known/multiplexer/${multiplexer}`,
970
974
  {method: 'POST',
975
+ signal: mux_aborter.signal,
971
976
  headers: {'Multiplex-Version': multiplex_version},
972
977
  retry: true})
973
978
  if (r.status === 409) {
974
979
  var e = await r.json()
975
980
  if (e.error === 'Multiplexer already exists')
976
- return cleanup(new Error(e.error))
981
+ return cleanup(create_error(e.error, {dont_wait: true}))
977
982
  }
978
983
  if (!r.ok) throw new Error('status not ok: ' + r.status)
979
984
  if (r.headers.get('Multiplex-Version') !== multiplex_version)
@@ -1047,9 +1052,11 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
1047
1052
  })
1048
1053
 
1049
1054
  // prepare a function that we'll call to cleanly tear things down
1055
+ clearTimeout(not_used_timeout)
1050
1056
  var unset = async e => {
1051
1057
  unset = () => {}
1052
1058
  requests.delete(request)
1059
+ if (!requests.size) not_used_timeout = setTimeout(() => mux_aborter.abort(), mux_params?.not_used_timeout ?? 1000 * 20)
1053
1060
  request_error = e
1054
1061
  bytes_available()
1055
1062
  await try_deleting_request(request)
@@ -1060,13 +1067,20 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
1060
1067
  var res = await normal_fetch(url, params)
1061
1068
 
1062
1069
  if (res.status === 409) {
1063
- var e = await r.json()
1064
- if (e.error === 'Request already multiplexed') throw new Error(e.error)
1070
+ var e = await res.json()
1071
+ if (e.error === 'Request already multiplexed') {
1072
+ // the id is already in use,
1073
+ // so we want to retry right away with a different id
1074
+ throw create_error(e.error, {dont_wait: true})
1075
+ }
1065
1076
  }
1066
1077
 
1067
1078
  if (res.status === 424) {
1068
- // this error will trigger a retry if the user is using that option
1069
- throw new Error('multiplexer not yet connected')
1079
+ // the multiplexer isn't there,
1080
+ // could be we arrived before the multiplexer,
1081
+ // or after it was shutdown;
1082
+ // in either case we want to retry right away
1083
+ throw create_error('multiplexer not connected', {dont_wait: true})
1070
1084
  }
1071
1085
 
1072
1086
  // if the response says it's ok,
@@ -1075,21 +1089,23 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
1075
1089
  if (res.ok && res.status !== 293) return res
1076
1090
 
1077
1091
  if (res.status !== 293)
1078
- throw new Error('Could not establish multiplexed request '
1079
- + params.headers.get('multiplex-through')
1080
- + ', got status: ' + res.status)
1092
+ throw create_error('Could not establish multiplexed request '
1093
+ + params.headers.get('multiplex-through')
1094
+ + ', got status: ' + res.status,
1095
+ { dont_retry: true })
1081
1096
 
1082
1097
  if (res.headers.get('Multiplex-Version') !== multiplex_version)
1083
- throw new Error('Could not establish multiplexed request '
1084
- + params.headers.get('multiplex-through')
1085
- + ', got unknown version: '
1086
- + res.headers.get('Multiplex-Version'))
1098
+ throw create_error('Could not establish multiplexed request '
1099
+ + params.headers.get('multiplex-through')
1100
+ + ', got unknown version: '
1101
+ + res.headers.get('Multiplex-Version'),
1102
+ { dont_retry: true })
1087
1103
 
1088
1104
  // we want to present the illusion that the connection is still open,
1089
1105
  // and therefor closable with "abort",
1090
1106
  // so we handle the abort ourselves to close the multiplexed request
1091
- params.signal?.addEventListener('abort', () =>
1092
- unset(create_abort_error('request aborted')))
1107
+ params.signal.addEventListener('abort', () =>
1108
+ unset(create_error('request aborted', {name: 'AbortError'})))
1093
1109
 
1094
1110
  // first, we need to listen for the headers..
1095
1111
  var headers_buffer = new Uint8Array()
@@ -1135,12 +1151,11 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
1135
1151
  try {
1136
1152
  await process_buffers(() => {
1137
1153
  var b = buffers.shift()
1138
- if (!b) {
1139
- if (mux_error || request_error) controller.error(mux_error || request_error)
1140
- return true
1141
- }
1154
+ if (!b) return true
1142
1155
  controller.enqueue(b)
1143
1156
  })
1157
+ } catch (e) {
1158
+ controller.error(e)
1144
1159
  } finally { controller.close() }
1145
1160
  }
1146
1161
  }), {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "braid-http",
3
- "version": "1.3.50",
3
+ "version": "1.3.52",
4
4
  "description": "An implementation of Braid-HTTP for Node.js and Browsers",
5
5
  "scripts": {
6
6
  "test": "node test/server.js"