braid-http 1.3.53 → 1.3.54
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.
- package/braid-http-client.js +66 -31
- package/package.json +1 -1
package/braid-http-client.js
CHANGED
|
@@ -270,10 +270,6 @@ async function braid_fetch (url, params = {}) {
|
|
|
270
270
|
!cb_running // if an error is thrown in the callback,
|
|
271
271
|
// then it may not be good to reconnect, and generate more errors
|
|
272
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
|
|
276
|
-
|
|
277
273
|
if (retry && !original_signal?.aborted) {
|
|
278
274
|
// retry after some time..
|
|
279
275
|
console.log(`retrying in ${waitTime}s: ${url} after error: ${e}`)
|
|
@@ -319,7 +315,7 @@ async function braid_fetch (url, params = {}) {
|
|
|
319
315
|
(params.headers.has('subscribe') &&
|
|
320
316
|
braid_fetch.subscription_counts?.[origin] >
|
|
321
317
|
(!mux_params ? 1 : (mux_params.after ?? 0))))) {
|
|
322
|
-
res = await multiplex_fetch(url, params, mux_params
|
|
318
|
+
res = await multiplex_fetch(url, params, mux_params)
|
|
323
319
|
} else
|
|
324
320
|
res = await normal_fetch(url, params)
|
|
325
321
|
|
|
@@ -896,7 +892,7 @@ function random_base64url(n) {
|
|
|
896
892
|
|
|
897
893
|
// multiplex_fetch provides a fetch-like experience for HTTP requests
|
|
898
894
|
// where the result is actually being sent over a separate multiplexed connection.
|
|
899
|
-
async function multiplex_fetch(url, params, mux_params
|
|
895
|
+
async function multiplex_fetch(url, params, mux_params) {
|
|
900
896
|
var origin = new URL(url, typeof document !== 'undefined' ? document.baseURI : undefined).origin
|
|
901
897
|
|
|
902
898
|
// the mux_key is the same as the origin, unless it is being overriden
|
|
@@ -905,20 +901,33 @@ async function multiplex_fetch(url, params, mux_params, aborter) {
|
|
|
905
901
|
|
|
906
902
|
// create a new multiplexer if it doesn't exist for this origin
|
|
907
903
|
if (!multiplex_fetch.multiplexers) multiplex_fetch.multiplexers = {}
|
|
908
|
-
if (!multiplex_fetch.multiplexers[mux_key]) multiplex_fetch.multiplexers[mux_key] =
|
|
909
|
-
create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
910
904
|
|
|
911
|
-
//
|
|
912
|
-
|
|
905
|
+
// this for-loop allows us to retry right away,
|
|
906
|
+
// in case of duplicate ids
|
|
907
|
+
for (let attempt = 1; ; attempt++) {
|
|
908
|
+
await new Promise(done => setTimeout(done, attempt >= 3 ? 1000 : 0))
|
|
909
|
+
|
|
910
|
+
if (!multiplex_fetch.multiplexers[mux_key]) multiplex_fetch.multiplexers[mux_key] =
|
|
911
|
+
create_multiplexer(origin, mux_key, params, mux_params, attempt)
|
|
912
|
+
|
|
913
|
+
// call the special fetch function for the multiplexer
|
|
914
|
+
try {
|
|
915
|
+
return await (await multiplex_fetch.multiplexers[mux_key])(url, params, mux_params, attempt)
|
|
916
|
+
} catch (e) {
|
|
917
|
+
if (e === 'retry') continue
|
|
918
|
+
throw e
|
|
919
|
+
}
|
|
920
|
+
}
|
|
913
921
|
}
|
|
914
922
|
|
|
915
923
|
// returns a function with a fetch-like interface that transparently multiplexes the fetch
|
|
916
|
-
async function create_multiplexer(origin, mux_key, params, mux_params,
|
|
924
|
+
async function create_multiplexer(origin, mux_key, params, mux_params, attempt) {
|
|
917
925
|
var multiplex_version = '1.0'
|
|
918
926
|
|
|
919
927
|
// make up a new multiplexer id (unless it is being overriden)
|
|
920
|
-
var multiplexer =
|
|
921
|
-
|
|
928
|
+
var multiplexer = (attempt === 1 &&
|
|
929
|
+
params.headers.get('multiplex-through')?.split('/')[3])
|
|
930
|
+
|| random_base64url(Math.ceil((mux_params?.id_bits ?? 72) / 6))
|
|
922
931
|
|
|
923
932
|
var requests = new Map()
|
|
924
933
|
var mux_error = null
|
|
@@ -926,8 +935,9 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
926
935
|
var not_used_timeout = null
|
|
927
936
|
var mux_aborter = new AbortController()
|
|
928
937
|
|
|
929
|
-
function
|
|
938
|
+
function cleanup_multiplexer(e, stay_dead) {
|
|
930
939
|
// the multiplexer stream has died.. let everyone know..
|
|
940
|
+
mux_aborter.abort()
|
|
931
941
|
mux_error = e
|
|
932
942
|
if (!stay_dead) delete multiplex_fetch.multiplexers[mux_key]
|
|
933
943
|
for (var f of requests.values()) f()
|
|
@@ -969,7 +979,7 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
969
979
|
if (r.status === 409) {
|
|
970
980
|
var e = await r.json()
|
|
971
981
|
if (e.error === 'Multiplexer already exists')
|
|
972
|
-
return
|
|
982
|
+
return cleanup_multiplexer('retry')
|
|
973
983
|
}
|
|
974
984
|
if (!r.ok || r.headers.get('Multiplex-Version') !== multiplex_version)
|
|
975
985
|
throw 'bad'
|
|
@@ -985,7 +995,7 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
985
995
|
if (r.status === 409) {
|
|
986
996
|
var e = await r.json()
|
|
987
997
|
if (e.error === 'Multiplexer already exists')
|
|
988
|
-
return
|
|
998
|
+
return cleanup_multiplexer('retry')
|
|
989
999
|
}
|
|
990
1000
|
if (!r.ok) throw new Error('status not ok: ' + r.status)
|
|
991
1001
|
if (r.headers.get('Multiplex-Version') !== multiplex_version)
|
|
@@ -996,7 +1006,7 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
996
1006
|
// fallback to normal fetch if multiplexed connection fails
|
|
997
1007
|
console.error(`Could not establish multiplexer.\n`
|
|
998
1008
|
+ `Got error: ${e}.\nFalling back to normal connection.`)
|
|
999
|
-
|
|
1009
|
+
cleanup_multiplexer('retry', true)
|
|
1000
1010
|
return false
|
|
1001
1011
|
}
|
|
1002
1012
|
}
|
|
@@ -1006,29 +1016,38 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
1006
1016
|
parse_multiplex_stream(r.body.getReader(), async (request, bytes) => {
|
|
1007
1017
|
if (requests.has(request)) requests.get(request)(bytes)
|
|
1008
1018
|
else try_deleting_request(request)
|
|
1009
|
-
}, e =>
|
|
1019
|
+
}, e => cleanup_multiplexer(e))
|
|
1010
1020
|
})()
|
|
1011
1021
|
|
|
1012
1022
|
// return a "fetch" for this multiplexer
|
|
1013
|
-
return async (url, params) => {
|
|
1023
|
+
return async (url, params, mux_params, attempt) => {
|
|
1014
1024
|
|
|
1015
1025
|
// if we already know the multiplexer is not working,
|
|
1016
1026
|
// then fallback to normal fetch
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1027
|
+
if ((await promise_done(mux_promise)) && (await mux_promise) === false) {
|
|
1028
|
+
// if the user is specifically asking for multiplexing,
|
|
1029
|
+
// throw an error instead
|
|
1030
|
+
if (params.headers.get('multiplex-through')) throw new Error('multiplexer failed')
|
|
1031
|
+
|
|
1021
1032
|
return await normal_fetch(url, params)
|
|
1033
|
+
}
|
|
1022
1034
|
|
|
1023
1035
|
// make up a new request id (unless it is being overriden)
|
|
1024
|
-
var request =
|
|
1025
|
-
|
|
1036
|
+
var request = (attempt === 1
|
|
1037
|
+
&& params.headers.get('multiplex-through')?.split('/')[4])
|
|
1038
|
+
|| random_base64url(Math.ceil((mux_params?.id_bits ?? 72) / 6))
|
|
1026
1039
|
|
|
1027
1040
|
// add the Multiplex-Through header without affecting the underlying params
|
|
1028
1041
|
var mux_headers = new Headers(params.headers)
|
|
1029
1042
|
mux_headers.set('Multiplex-Through', `/.well-known/multiplexer/${multiplexer}/${request}`)
|
|
1030
1043
|
mux_headers.set('Multiplex-Version', multiplex_version)
|
|
1031
|
-
|
|
1044
|
+
|
|
1045
|
+
// also create our own aborter in case we need to abort ourselves
|
|
1046
|
+
var aborter = new AbortController()
|
|
1047
|
+
params.signal?.addEventListener('abort', () => aborter.abort())
|
|
1048
|
+
|
|
1049
|
+
// now create a new params with the new headers and abort signal
|
|
1050
|
+
params = {...params, headers: mux_headers, signal: aborter.signal}
|
|
1032
1051
|
|
|
1033
1052
|
// setup a way to receive incoming data from the multiplexer
|
|
1034
1053
|
var buffers = []
|
|
@@ -1066,11 +1085,16 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
1066
1085
|
if (!requests.size) not_used_timeout = setTimeout(() => mux_aborter.abort(), mux_params?.not_used_timeout ?? 1000 * 20)
|
|
1067
1086
|
request_error = e
|
|
1068
1087
|
bytes_available()
|
|
1069
|
-
await try_deleting_request(request)
|
|
1088
|
+
if (e !== 'retry') await try_deleting_request(request)
|
|
1070
1089
|
}
|
|
1071
1090
|
|
|
1072
1091
|
// do the underlying fetch
|
|
1073
1092
|
try {
|
|
1093
|
+
var mux_was_done = await promise_done(mux_promise)
|
|
1094
|
+
|
|
1095
|
+
// callback for testing
|
|
1096
|
+
mux_params?.onFetch?.(url, params)
|
|
1097
|
+
|
|
1074
1098
|
var res = await normal_fetch(url, params)
|
|
1075
1099
|
|
|
1076
1100
|
if (res.status === 409) {
|
|
@@ -1078,7 +1102,7 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
1078
1102
|
if (e.error === 'Request already multiplexed') {
|
|
1079
1103
|
// the id is already in use,
|
|
1080
1104
|
// so we want to retry right away with a different id
|
|
1081
|
-
throw
|
|
1105
|
+
throw "retry"
|
|
1082
1106
|
}
|
|
1083
1107
|
}
|
|
1084
1108
|
|
|
@@ -1087,7 +1111,18 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
1087
1111
|
// could be we arrived before the multiplexer,
|
|
1088
1112
|
// or after it was shutdown;
|
|
1089
1113
|
// in either case we want to retry right away
|
|
1090
|
-
|
|
1114
|
+
|
|
1115
|
+
// but before we do,
|
|
1116
|
+
// if we know the multiplexer was created,
|
|
1117
|
+
// but it isn't there now,
|
|
1118
|
+
// and our client doesn't realize it,
|
|
1119
|
+
// then shut it down ourselves before retrying,
|
|
1120
|
+
// so when we retry,
|
|
1121
|
+
// a new multiplexer is created
|
|
1122
|
+
if (mux_was_done && !mux_error)
|
|
1123
|
+
cleanup_multiplexer(new Error('multiplexer detected to be closed'))
|
|
1124
|
+
|
|
1125
|
+
throw "retry"
|
|
1091
1126
|
}
|
|
1092
1127
|
|
|
1093
1128
|
// if the response says it's ok,
|
|
@@ -1172,14 +1207,14 @@ async function create_multiplexer(origin, mux_key, params, mux_params, aborter)
|
|
|
1172
1207
|
|
|
1173
1208
|
// add a convenience property for the user to know if
|
|
1174
1209
|
// this response is being multiplexed
|
|
1175
|
-
res.
|
|
1210
|
+
res.multiplexed_through = params.headers.get('multiplex-through')
|
|
1176
1211
|
|
|
1177
1212
|
// return the fake response object
|
|
1178
1213
|
return res
|
|
1179
1214
|
} catch (e) {
|
|
1180
1215
|
// if we had an error, be sure to unregister ourselves
|
|
1181
1216
|
unset(e)
|
|
1182
|
-
throw mux_error || e
|
|
1217
|
+
throw (e === 'retry' && e) || mux_error || e
|
|
1183
1218
|
}
|
|
1184
1219
|
}
|
|
1185
1220
|
}
|