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.
Files changed (3) hide show
  1. package/index.js +19 -12
  2. package/package.json +1 -1
  3. 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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hypercore-fetch",
3
- "version": "9.0.6",
3
+ "version": "9.0.7",
4
4
  "description": "Implementation of Fetch that uses the Dat SDK for loading p2p content",
5
5
  "type": "module",
6
6
  "main": "index.js",
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