@@ -1437,8 +1437,11 @@ describe('Cache Interceptor', () => {
14371437 } )
14381438 } )
14391439
1440+ // Partial list.
14401441 const cacheableStatusCodes = [
14411442 { code : 204 , body : '' } ,
1443+ { code : 302 , body : 'Found' } ,
1444+ { code : 307 , body : 'Temporary Redirect' } ,
14421445 { code : 404 , body : 'Not Found' } ,
14431446 { code : 410 , body : 'Gone' }
14441447 ]
@@ -1489,13 +1492,71 @@ describe('Cache Interceptor', () => {
14891492 } )
14901493 }
14911494
1492- test ( 'does not cache non-heuristically cacheable error status codes' , async ( ) => {
1495+ // Partial list.
1496+ const nonHeuristicallyCacheableStatusCodes = [
1497+ { code : 201 , body : 'Created' } ,
1498+ { code : 307 , body : 'Temporary Redirect' } ,
1499+ { code : 418 , body : 'I am a teapot' }
1500+ ]
1501+
1502+ for ( const { code, body } of nonHeuristicallyCacheableStatusCodes ) {
1503+ test ( `does not cache non-heuristically cacheable status ${ code } without explicit directive` , async ( ) => {
1504+ let requestsToOrigin = 0
1505+ const server = createServer ( { joinDuplicateHeaders : true } , ( _ , res ) => {
1506+ requestsToOrigin ++
1507+ res . statusCode = code
1508+ // By default the response may have a date and last-modified header set to 'now',
1509+ // causing the cache to compute a 0 heuristic expiry, causing the test to not ascertain
1510+ // it is really not cached.
1511+ res . setHeader ( 'date' , '' )
1512+ res . end ( body )
1513+ } ) . listen ( 0 )
1514+
1515+ const client = new Client ( `http://localhost:${ server . address ( ) . port } ` )
1516+ . compose ( interceptors . cache ( { cacheByDefault : 60 } ) )
1517+
1518+ after ( async ( ) => {
1519+ server . close ( )
1520+ await client . close ( )
1521+ } )
1522+
1523+ await once ( server , 'listening' )
1524+
1525+ equal ( requestsToOrigin , 0 )
1526+
1527+ const request = {
1528+ origin : 'localhost' ,
1529+ method : 'GET' ,
1530+ path : '/'
1531+ }
1532+
1533+ // First request should hit the origin
1534+ {
1535+ const res = await client . request ( request )
1536+ equal ( requestsToOrigin , 1 )
1537+ equal ( res . statusCode , code )
1538+ strictEqual ( await res . body . text ( ) , body )
1539+ }
1540+
1541+ // Second request should also hit the origin (not cached)
1542+ {
1543+ const res = await client . request ( request )
1544+ equal ( requestsToOrigin , 2 ) // Should be 2 (not cached)
1545+ equal ( res . statusCode , code )
1546+ strictEqual ( await res . body . text ( ) , body )
1547+ }
1548+ } )
1549+ }
1550+
1551+ test ( 'discriminates caching of range requests, or does not cache them' , async ( ) => {
14931552 let requestsToOrigin = 0
1553+ const body = 'Fake range request response'
1554+ const code = 206
14941555 const server = createServer ( { joinDuplicateHeaders : true } , ( _ , res ) => {
14951556 requestsToOrigin ++
1496- res . statusCode = 418 // I'm a teapot - not in heuristically cacheable list
1557+ res . statusCode = code
14971558 res . setHeader ( 'cache-control' , 'public, max-age=60' )
1498- res . end ( 'I am a teapot' )
1559+ res . end ( body )
14991560 } ) . listen ( 0 )
15001561
15011562 const client = new Client ( `http://localhost:${ server . address ( ) . port } ` )
@@ -1513,23 +1574,127 @@ describe('Cache Interceptor', () => {
15131574 const request = {
15141575 origin : 'localhost' ,
15151576 method : 'GET' ,
1516- path : '/'
1577+ path : '/' ,
1578+ headers : {
1579+ range : 'bytes=10-'
1580+ }
15171581 }
15181582
15191583 // First request should hit the origin
15201584 {
15211585 const res = await client . request ( request )
15221586 equal ( requestsToOrigin , 1 )
1523- equal ( res . statusCode , 418 )
1524- strictEqual ( await res . body . text ( ) , 'I am a teapot' )
1587+ equal ( res . statusCode , code )
1588+ strictEqual ( await res . body . text ( ) , body )
15251589 }
15261590
1527- // Second request should also hit the origin (not cached)
1591+ // Second request with different range should hit the origin too
1592+ request . headers . range = 'bytes=5-'
15281593 {
15291594 const res = await client . request ( request )
1530- equal ( requestsToOrigin , 2 ) // Should be 2 (not cached)
1531- equal ( res . statusCode , 418 )
1532- strictEqual ( await res . body . text ( ) , 'I am a teapot' )
1595+ equal ( requestsToOrigin , 2 )
1596+ equal ( res . statusCode , code )
1597+ strictEqual ( await res . body . text ( ) , body )
1598+ }
1599+ } )
1600+
1601+ test ( 'discriminates caching of conditionnal requests (if-none-match), or does not cache them' , async ( ) => {
1602+ let requestsToOrigin = 0
1603+ const body = ''
1604+ const code = 304
1605+ const server = createServer ( { joinDuplicateHeaders : true } , ( _ , res ) => {
1606+ requestsToOrigin ++
1607+ res . statusCode = code
1608+ res . setHeader ( 'cache-control' , 'public, max-age=60' )
1609+ res . end ( body )
1610+ } ) . listen ( 0 )
1611+
1612+ const client = new Client ( `http://localhost:${ server . address ( ) . port } ` )
1613+ . compose ( interceptors . cache ( ) )
1614+
1615+ after ( async ( ) => {
1616+ server . close ( )
1617+ await client . close ( )
1618+ } )
1619+
1620+ await once ( server , 'listening' )
1621+
1622+ equal ( requestsToOrigin , 0 )
1623+
1624+ const request = {
1625+ origin : 'localhost' ,
1626+ method : 'GET' ,
1627+ path : '/' ,
1628+ headers : {
1629+ 'if-none-match' : 'some-etag'
1630+ }
1631+ }
1632+
1633+ // First request should hit the origin
1634+ {
1635+ const res = await client . request ( request )
1636+ equal ( requestsToOrigin , 1 )
1637+ equal ( res . statusCode , code )
1638+ strictEqual ( await res . body . text ( ) , body )
1639+ }
1640+
1641+ // Second request with different etag should hit the origin too
1642+ request . headers [ 'if-none-match' ] = 'another-etag'
1643+ {
1644+ const res = await client . request ( request )
1645+ equal ( requestsToOrigin , 2 )
1646+ equal ( res . statusCode , code )
1647+ strictEqual ( await res . body . text ( ) , body )
1648+ }
1649+ } )
1650+
1651+ test ( 'discriminates caching of conditionnal requests (if-modified-since), or does not cache them' , async ( ) => {
1652+ let requestsToOrigin = 0
1653+ const body = ''
1654+ const code = 304
1655+ const server = createServer ( { joinDuplicateHeaders : true } , ( _ , res ) => {
1656+ requestsToOrigin ++
1657+ res . statusCode = code
1658+ res . setHeader ( 'cache-control' , 'public, max-age=60' )
1659+ res . end ( body )
1660+ } ) . listen ( 0 )
1661+
1662+ const client = new Client ( `http://localhost:${ server . address ( ) . port } ` )
1663+ . compose ( interceptors . cache ( ) )
1664+
1665+ after ( async ( ) => {
1666+ server . close ( )
1667+ await client . close ( )
1668+ } )
1669+
1670+ await once ( server , 'listening' )
1671+
1672+ equal ( requestsToOrigin , 0 )
1673+
1674+ const request = {
1675+ origin : 'localhost' ,
1676+ method : 'GET' ,
1677+ path : '/' ,
1678+ headers : {
1679+ 'if-modified-since' : new Date ( ) . toUTCString ( )
1680+ }
1681+ }
1682+
1683+ // First request should hit the origin
1684+ {
1685+ const res = await client . request ( request )
1686+ equal ( requestsToOrigin , 1 )
1687+ equal ( res . statusCode , code )
1688+ strictEqual ( await res . body . text ( ) , body )
1689+ }
1690+
1691+ // Second request with different since should hit the origin too
1692+ request . headers [ 'if-modified-since' ] = new Date ( 0 ) . toUTCString ( )
1693+ {
1694+ const res = await client . request ( request )
1695+ equal ( requestsToOrigin , 2 )
1696+ equal ( res . statusCode , code )
1697+ strictEqual ( await res . body . text ( ) , body )
15331698 }
15341699 } )
15351700} )
0 commit comments