@@ -267,9 +267,10 @@ const canBeListed = (excluded, file) => {
267
267
return whether ;
268
268
} ;
269
269
270
- const renderDirectory = async ( current , relativePath , absolutePath , handlers , config ) => {
270
+ const renderDirectory = async ( current , acceptsJSON , handlers , config , paths ) => {
271
271
const { directoryListing, trailingSlash, unlisted = [ ] } = config ;
272
272
const slashSuffix = typeof trailingSlash === 'boolean' ? ( trailingSlash ? '/' : '' ) : '/' ;
273
+ const { relativePath, absolutePath} = paths ;
273
274
274
275
const excluded = [
275
276
'.DS_Store' ,
@@ -296,7 +297,10 @@ const renderDirectory = async (current, relativePath, absolutePath, handlers, co
296
297
details . base += slashSuffix ;
297
298
details . relative += slashSuffix ;
298
299
299
- details . isDirectory = true ;
300
+ // This is not camelcase, as we might be sending
301
+ // the data away as JSON later, which shouldn't contain
302
+ // any camelcased keys.
303
+ details [ 'is-directory' ] = true ;
300
304
} else {
301
305
details . ext = details . ext . split ( '.' ) [ 1 ] || 'txt' ;
302
306
@@ -321,8 +325,8 @@ const renderDirectory = async (current, relativePath, absolutePath, handlers, co
321
325
322
326
// Sort to list directories first, then sort alphabetically
323
327
files = files . sort ( ( a , b ) => {
324
- const aIsDir = a . isDirectory ;
325
- const bIsDir = b . isDirectory ;
328
+ const aIsDir = a [ 'is-directory' ] ;
329
+ const bIsDir = b [ 'is-directory' ] ;
326
330
327
331
if ( aIsDir && ! bIsDir ) {
328
332
return - 1 ;
@@ -355,7 +359,7 @@ const renderDirectory = async (current, relativePath, absolutePath, handlers, co
355
359
} ) ;
356
360
}
357
361
358
- const paths = [ ] ;
362
+ const subPaths = [ ] ;
359
363
360
364
for ( let index = 0 ; index < pathParts . length ; index ++ ) {
361
365
const parents = [ ] ;
@@ -370,17 +374,23 @@ const renderDirectory = async (current, relativePath, absolutePath, handlers, co
370
374
371
375
parents . shift ( ) ;
372
376
373
- paths . push ( {
377
+ subPaths . push ( {
374
378
name : pathParts [ index ] + ( isLast ? slashSuffix : '/' ) ,
375
379
url : index === 0 ? '' : parents . join ( '/' ) + slashSuffix
376
380
} ) ;
377
381
}
378
382
379
- return template ( {
383
+ const spec = {
380
384
files,
381
385
directory,
382
- paths
383
- } ) ;
386
+ paths : subPaths
387
+ } ;
388
+
389
+ if ( acceptsJSON ) {
390
+ return JSON . stringify ( spec ) ;
391
+ }
392
+
393
+ return template ( spec ) ;
384
394
} ;
385
395
386
396
module . exports = async ( request , response , config = { } , methods = { } ) => {
@@ -433,11 +443,20 @@ module.exports = async (request, response, config = {}, methods = {}) => {
433
443
}
434
444
}
435
445
446
+ const acceptsJSON = request . headers . accept . includes ( 'application/json' ) ;
447
+
448
+ if ( ( ( stats && stats . isDirectory ( ) ) || ! stats ) && acceptsJSON ) {
449
+ response . setHeader ( 'Content-Type' , 'application/json' ) ;
450
+ }
451
+
436
452
if ( stats && stats . isDirectory ( ) ) {
437
453
let directory = null ;
438
454
439
455
try {
440
- directory = await renderDirectory ( current , relativePath , absolutePath , handlers , config ) ;
456
+ directory = await renderDirectory ( current , acceptsJSON , handlers , config , {
457
+ relativePath,
458
+ absolutePath
459
+ } ) ;
441
460
} catch ( err ) {
442
461
response . statusCode = 500 ;
443
462
response . end ( err . message ) ;
@@ -460,6 +479,17 @@ module.exports = async (request, response, config = {}, methods = {}) => {
460
479
if ( ! stats ) {
461
480
response . statusCode = 404 ;
462
481
482
+ if ( acceptsJSON ) {
483
+ response . end ( JSON . stringify ( {
484
+ error : {
485
+ code : 'not_found' ,
486
+ message : 'Not Found'
487
+ }
488
+ } ) ) ;
489
+
490
+ return ;
491
+ }
492
+
463
493
const errorPage = '404.html' ;
464
494
const errorPageFull = path . join ( current , errorPage ) ;
465
495
0 commit comments