hypercore-fetch 9.0.6 → 9.0.7
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/index.js +19 -12
- package/package.json +1 -1
- package/test.js +28 -3
package/index.js
CHANGED
|
@@ -209,7 +209,8 @@ export default async function makeHyperFetch ({
|
|
|
209
209
|
}
|
|
210
210
|
})
|
|
211
211
|
router.get(`hyper://*/${SPECIAL_FOLDER}/${EXTENSIONS_FOLDER_NAME}/*`, async function listenExtension (request) {
|
|
212
|
-
const { hostname, pathname } = new URL(request.url)
|
|
212
|
+
const { hostname, pathname: rawPathname } = new URL(request.url)
|
|
213
|
+
const pathname = decodeURI(rawPathname)
|
|
213
214
|
const name = pathname.slice(`/${SPECIAL_FOLDER}/${EXTENSIONS_FOLDER_NAME}/`.length)
|
|
214
215
|
|
|
215
216
|
const core = await getCore(`hyper://${hostname}/`)
|
|
@@ -229,7 +230,9 @@ export default async function makeHyperFetch ({
|
|
|
229
230
|
}
|
|
230
231
|
})
|
|
231
232
|
router.post(`hyper://*/${SPECIAL_FOLDER}/${EXTENSIONS_FOLDER_NAME}/*`, async function broadcastExtension (request) {
|
|
232
|
-
const { hostname, pathname } = new URL(request.url)
|
|
233
|
+
const { hostname, pathname: rawPathname } = new URL(request.url)
|
|
234
|
+
const pathname = decodeURI(rawPathname)
|
|
235
|
+
|
|
233
236
|
const name = pathname.slice(`/${SPECIAL_FOLDER}/${EXTENSIONS_FOLDER_NAME}/`.length)
|
|
234
237
|
|
|
235
238
|
const core = await getCore(`hyper://${hostname}/`)
|
|
@@ -241,7 +244,9 @@ export default async function makeHyperFetch ({
|
|
|
241
244
|
return { status: 200 }
|
|
242
245
|
})
|
|
243
246
|
router.post(`hyper://*/${SPECIAL_FOLDER}/${EXTENSIONS_FOLDER_NAME}/*/*`, async function extensionToPeer (request) {
|
|
244
|
-
const { hostname, pathname } = new URL(request.url)
|
|
247
|
+
const { hostname, pathname: rawPathname } = new URL(request.url)
|
|
248
|
+
const pathname = decodeURI(rawPathname)
|
|
249
|
+
|
|
245
250
|
const subFolder = pathname.slice(`/${SPECIAL_FOLDER}/${EXTENSIONS_FOLDER_NAME}/`.length)
|
|
246
251
|
const [name, extensionPeer] = subFolder.split('/')
|
|
247
252
|
|
|
@@ -304,7 +309,8 @@ export default async function makeHyperFetch ({
|
|
|
304
309
|
})
|
|
305
310
|
|
|
306
311
|
router.put('hyper://*/**', async function putFiles (request) {
|
|
307
|
-
const { hostname, pathname } = new URL(request.url)
|
|
312
|
+
const { hostname, pathname: rawPathname } = new URL(request.url)
|
|
313
|
+
const pathname = decodeURI(rawPathname)
|
|
308
314
|
const contentType = request.headers.get('Content-Type') || ''
|
|
309
315
|
const isFormData = contentType.includes('multipart/form-data')
|
|
310
316
|
|
|
@@ -339,7 +345,8 @@ export default async function makeHyperFetch ({
|
|
|
339
345
|
return { status: 201, headers: { Location: request.url } }
|
|
340
346
|
})
|
|
341
347
|
router.delete('hyper://*/**', async function putFiles (request) {
|
|
342
|
-
const { hostname, pathname } = new URL(request.url)
|
|
348
|
+
const { hostname, pathname: rawPathname } = new URL(request.url)
|
|
349
|
+
const pathname = decodeURI(rawPathname)
|
|
343
350
|
|
|
344
351
|
const drive = await getDrive(`hyper://${hostname}`)
|
|
345
352
|
|
|
@@ -368,7 +375,9 @@ export default async function makeHyperFetch ({
|
|
|
368
375
|
|
|
369
376
|
router.head('hyper://*/**', async function headFiles (request) {
|
|
370
377
|
const url = new URL(request.url)
|
|
371
|
-
const { hostname, pathname, searchParams } = url
|
|
378
|
+
const { hostname, pathname: rawPathname, searchParams } = url
|
|
379
|
+
const pathname = decodeURI(rawPathname)
|
|
380
|
+
|
|
372
381
|
const accept = request.headers.get('Accept') || ''
|
|
373
382
|
const isRanged = request.headers.get('Range') || ''
|
|
374
383
|
const noResolve = searchParams.has('noResolve')
|
|
@@ -435,14 +444,12 @@ export default async function makeHyperFetch ({
|
|
|
435
444
|
return { status: 404, body: 'Not Found' }
|
|
436
445
|
}
|
|
437
446
|
|
|
438
|
-
resHeaders.Link = new URL(path, drive.core.url).href
|
|
439
|
-
|
|
440
447
|
resHeaders.ETag = `${entry.seq}`
|
|
448
|
+
resHeaders['Content-Length'] = `${entry.value.blob.byteLength}`
|
|
441
449
|
|
|
442
450
|
const contentType = getMimeType(path)
|
|
443
451
|
resHeaders[HEADER_CONTENT_TYPE] = contentType
|
|
444
452
|
|
|
445
|
-
|
|
446
453
|
if (entry?.value?.metadata?.mtime) {
|
|
447
454
|
const date = new Date(entry.value.metadata.mtime)
|
|
448
455
|
resHeaders[HEADER_LAST_MODIFIED] = date.toUTCString()
|
|
@@ -476,7 +483,9 @@ export default async function makeHyperFetch ({
|
|
|
476
483
|
// TODO: Redirect on directories without trailing slash
|
|
477
484
|
router.get('hyper://*/**', async function getFiles (request) {
|
|
478
485
|
const url = new URL(request.url)
|
|
479
|
-
const { hostname, pathname, searchParams } = url
|
|
486
|
+
const { hostname, pathname: rawPathname, searchParams } = url
|
|
487
|
+
const pathname = decodeURI(rawPathname)
|
|
488
|
+
|
|
480
489
|
const accept = request.headers.get('Accept') || ''
|
|
481
490
|
const noResolve = searchParams.has('noResolve')
|
|
482
491
|
const isDirectory = pathname.endsWith('/')
|
|
@@ -551,7 +560,6 @@ async function serveFile (headers, drive, pathname) {
|
|
|
551
560
|
|
|
552
561
|
const entry = await drive.entry(pathname)
|
|
553
562
|
|
|
554
|
-
|
|
555
563
|
const resHeaders = {
|
|
556
564
|
ETag: `${entry.seq}`,
|
|
557
565
|
[HEADER_CONTENT_TYPE]: contentType,
|
|
@@ -559,7 +567,6 @@ async function serveFile (headers, drive, pathname) {
|
|
|
559
567
|
Link: `<${fullURL}>; rel="canonical"`
|
|
560
568
|
}
|
|
561
569
|
|
|
562
|
-
|
|
563
570
|
if (entry?.value?.metadata?.mtime) {
|
|
564
571
|
const date = new Date(entry.value.metadata.mtime)
|
|
565
572
|
resHeaders[HEADER_LAST_MODIFIED] = date.toUTCString()
|
package/package.json
CHANGED
package/test.js
CHANGED
|
@@ -57,7 +57,7 @@ test('Quick check', async (t) => {
|
|
|
57
57
|
|
|
58
58
|
t.deepEqual(await existsResponse.json(), [], 'Empty dir on create')
|
|
59
59
|
|
|
60
|
-
const uploadLocation = new URL('./example.txt', created)
|
|
60
|
+
const uploadLocation = new URL('./example .txt', created)
|
|
61
61
|
|
|
62
62
|
const uploadResponse = await fetch(uploadLocation, {
|
|
63
63
|
method: 'put',
|
|
@@ -74,7 +74,7 @@ test('Quick check', async (t) => {
|
|
|
74
74
|
const contentType = uploadedContentResponse.headers.get('Content-Type')
|
|
75
75
|
const contentLink = uploadedContentResponse.headers.get('Link')
|
|
76
76
|
|
|
77
|
-
t.match(contentLink, /^<hyper:\/\/[0-9a-z]{52}\/example.txt>; rel="canonical"$/, 'Link header includes both public key and path.')
|
|
77
|
+
t.match(contentLink, /^<hyper:\/\/[0-9a-z]{52}\/example%20.txt>; rel="canonical"$/, 'Link header includes both public key and path.')
|
|
78
78
|
t.equal(contentType, 'text/plain; charset=utf-8', 'Content got expected mime type')
|
|
79
79
|
t.equal(content, SAMPLE_CONTENT, 'Got uploaded content back out')
|
|
80
80
|
|
|
@@ -82,7 +82,7 @@ test('Quick check', async (t) => {
|
|
|
82
82
|
|
|
83
83
|
await checkResponse(dirResponse, t)
|
|
84
84
|
|
|
85
|
-
t.deepEqual(await dirResponse.json(), ['example.txt'], 'File got added')
|
|
85
|
+
t.deepEqual(await dirResponse.json(), ['example .txt'], 'File got added')
|
|
86
86
|
})
|
|
87
87
|
|
|
88
88
|
test('GET full url for created keys', async (t) => {
|
|
@@ -111,6 +111,31 @@ test('GET full url for created keys', async (t) => {
|
|
|
111
111
|
t.equal(existingURL, createdURL, 'URL same as in initial create')
|
|
112
112
|
})
|
|
113
113
|
|
|
114
|
+
test('HEAD request', async (t) => {
|
|
115
|
+
const created = await nextURL(t)
|
|
116
|
+
const uploadLocation = new URL('./example.txt', created)
|
|
117
|
+
await fetch(uploadLocation, { method: 'put', body: SAMPLE_CONTENT })
|
|
118
|
+
|
|
119
|
+
const headResponse = await fetch(uploadLocation, { method: 'head' })
|
|
120
|
+
|
|
121
|
+
await checkResponse(headResponse, t, 'Able to load HEAD')
|
|
122
|
+
|
|
123
|
+
const headersEtag = headResponse.headers.get('Etag')
|
|
124
|
+
const headersContentType = headResponse.headers.get('Content-Type')
|
|
125
|
+
const headersContentLength = headResponse.headers.get('Content-Length')
|
|
126
|
+
const headersAcceptRanges = headResponse.headers.get('Accept-Ranges')
|
|
127
|
+
const headersLastModified = headResponse.headers.get('Last-Modified')
|
|
128
|
+
const headersLink = headResponse.headers.get('Link')
|
|
129
|
+
|
|
130
|
+
// Version at which the file was added
|
|
131
|
+
t.equal(headersEtag, '1', 'Headers got expected etag')
|
|
132
|
+
t.equal(headersContentType, 'text/plain; charset=utf-8', 'Headers got expected mime type')
|
|
133
|
+
t.ok(headersContentLength, "Headers have 'Content-Length' set.")
|
|
134
|
+
t.ok(headersLastModified, "Headers have 'Last-Modified' set.")
|
|
135
|
+
t.equal(headersAcceptRanges, 'bytes')
|
|
136
|
+
t.match(headersLink, /^<hyper:\/\/[0-9a-z]{52}\/example.txt>; rel="canonical"$/, 'Link header includes both public key and path.')
|
|
137
|
+
})
|
|
138
|
+
|
|
114
139
|
test('PUT file', async (t) => {
|
|
115
140
|
const created = await nextURL(t)
|
|
116
141
|
|