@jaredwray/mockhttp 0.8.0 → 0.9.0

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/dist/index.d.ts CHANGED
@@ -7,6 +7,7 @@ type HttpBinOptions = {
7
7
  requestInspection?: boolean;
8
8
  responseInspection?: boolean;
9
9
  statusCodes?: boolean;
10
+ responseFormats?: boolean;
10
11
  cookies?: boolean;
11
12
  anything?: boolean;
12
13
  auth?: boolean;
@@ -155,6 +156,7 @@ declare class MockHttp extends Hookified {
155
156
  * @param fastifyInstance - the server instance to register the routes on.
156
157
  */
157
158
  registerResponseInspectionRoutes(fastifyInstance?: FastifyInstance): Promise<void>;
159
+ registerResponseFormatRoutes(fastifyInstance?: FastifyInstance): Promise<void>;
158
160
  /**
159
161
  * Register the redirect routes.
160
162
  * @param fastifyInstance - the server instance to register the routes on.
package/dist/index.js CHANGED
@@ -1296,156 +1296,114 @@ var userAgentRoute = /* @__PURE__ */ __name((fastify) => {
1296
1296
  });
1297
1297
  }, "userAgentRoute");
1298
1298
 
1299
- // src/routes/response-inspection/cache.ts
1300
- var cacheGetSchema = {
1301
- description: "Handles cache validation and retrieval.",
1299
+ // src/routes/response-formats/index.ts
1300
+ import { brotliCompressSync, deflateSync, gzipSync } from "zlib";
1301
+ var plainSchema = {
1302
+ description: "Returns random plain text content",
1302
1303
  tags: [
1303
- "Response Inspection"
1304
+ "Response Formats"
1304
1305
  ],
1305
1306
  response: {
1306
1307
  200: {
1307
1308
  type: "string",
1308
- description: "The cached content or resource."
1309
- },
1310
- 304: {
1311
- type: "null",
1312
- description: "Indicates the resource has not been modified."
1309
+ description: "Random plain text content"
1313
1310
  }
1314
1311
  }
1315
1312
  };
1316
- var cacheSetSchema = {
1317
- description: "Sets a Cache-Control header for n seconds.",
1313
+ var textSchema = {
1314
+ description: "Returns random text content",
1318
1315
  tags: [
1319
- "Response Inspection"
1316
+ "Response Formats"
1320
1317
  ],
1321
- params: {
1322
- type: "object",
1323
- properties: {
1324
- value: {
1325
- type: "integer",
1326
- description: "Number of seconds to cache the resource."
1327
- }
1328
- },
1329
- required: [
1330
- "value"
1331
- ]
1332
- },
1333
1318
  response: {
1334
1319
  200: {
1335
1320
  type: "string",
1336
- description: "Confirmation message for setting cache."
1321
+ description: "Random text content"
1337
1322
  }
1338
1323
  }
1339
1324
  };
1340
- var cacheRoutes = /* @__PURE__ */ __name((fastify) => {
1341
- fastify.get("/cache", {
1342
- schema: cacheGetSchema
1343
- }, async (request, reply) => {
1344
- const ifModifiedSince = request.headers["if-modified-since"];
1345
- const ifNoneMatch = request.headers["if-none-match"];
1346
- if (ifModifiedSince ?? ifNoneMatch) {
1347
- await reply.status(304).send();
1348
- return;
1325
+ var htmlSchema = {
1326
+ description: "Returns random HTML content",
1327
+ tags: [
1328
+ "Response Formats"
1329
+ ],
1330
+ response: {
1331
+ 200: {
1332
+ type: "string",
1333
+ description: "Random HTML content"
1349
1334
  }
1350
- await reply.send("Cache content or resource response here.");
1351
- });
1352
- fastify.get("/cache/:value", {
1353
- schema: cacheSetSchema
1354
- }, async (request, reply) => {
1355
- const { value } = request.params;
1356
- await reply.header("Cache-Control", `max-age=${value}`).send(`Cache-Control set for ${value} seconds.`);
1357
- });
1358
- }, "cacheRoutes");
1359
-
1360
- // src/routes/response-inspection/etag.ts
1361
- var etagSchema = {
1362
- description: "Handles ETag-based conditional requests.",
1335
+ }
1336
+ };
1337
+ var xmlSchema = {
1338
+ description: "Returns random XML content",
1363
1339
  tags: [
1364
- "Response Inspection"
1340
+ "Response Formats"
1365
1341
  ],
1366
- params: {
1367
- type: "object",
1368
- properties: {
1369
- etag: {
1370
- type: "string",
1371
- description: "The ETag value for the resource."
1372
- }
1373
- },
1374
- required: [
1375
- "etag"
1376
- ]
1377
- },
1378
1342
  response: {
1379
1343
  200: {
1380
1344
  type: "string",
1381
- description: "Resource content for matching ETag."
1382
- },
1383
- 304: {
1384
- type: "null",
1385
- description: "Indicates the resource has not been modified."
1386
- },
1387
- 412: {
1388
- type: "null",
1389
- description: "Indicates a precondition failed due to mismatched ETag."
1345
+ description: "Random XML content"
1390
1346
  }
1391
1347
  }
1392
1348
  };
1393
- var etagRoutes = /* @__PURE__ */ __name((fastify) => {
1394
- fastify.get("/etag/:etag", {
1395
- schema: etagSchema
1396
- }, async (request, reply) => {
1397
- const { etag } = request.params;
1398
- const ifNoneMatch = request.headers["if-none-match"];
1399
- const ifMatch = request.headers["if-match"];
1400
- if (ifNoneMatch === etag) {
1401
- await reply.status(304).send();
1402
- return;
1349
+ var jsonSchema = {
1350
+ description: "Returns random JSON content",
1351
+ tags: [
1352
+ "Response Formats"
1353
+ ],
1354
+ response: {
1355
+ 200: {
1356
+ type: "object",
1357
+ description: "Random JSON content",
1358
+ additionalProperties: true
1403
1359
  }
1404
- if (ifMatch && ifMatch !== etag) {
1405
- await reply.status(412).send();
1406
- return;
1360
+ }
1361
+ };
1362
+ var denySchema = {
1363
+ description: "Returns page denied by robots.txt rules",
1364
+ tags: [
1365
+ "Response Formats"
1366
+ ],
1367
+ response: {
1368
+ 403: {
1369
+ type: "string",
1370
+ description: "Page denied by robots.txt rules"
1407
1371
  }
1408
- await reply.header("ETag", etag).send("Resource content for matching ETag.");
1409
- });
1410
- }, "etagRoutes");
1411
-
1412
- // src/routes/response-inspection/plain.ts
1413
- var plainSchema = {
1414
- description: "Returns random plain text content",
1372
+ }
1373
+ };
1374
+ var gzipSchema = {
1375
+ description: "Returns GZip-encoded data",
1415
1376
  tags: [
1416
- "Response Inspection"
1377
+ "Response Formats"
1417
1378
  ],
1418
- // @ts-expect-error
1419
1379
  response: {
1420
1380
  200: {
1421
1381
  type: "string",
1422
- description: "Random plain text content"
1382
+ description: "GZip-encoded content"
1423
1383
  }
1424
1384
  }
1425
1385
  };
1426
- var textSchema = {
1427
- description: "Returns random text content",
1386
+ var deflateSchema = {
1387
+ description: "Returns Deflate-encoded data",
1428
1388
  tags: [
1429
- "Response Inspection"
1389
+ "Response Formats"
1430
1390
  ],
1431
- // @ts-expect-error
1432
1391
  response: {
1433
1392
  200: {
1434
1393
  type: "string",
1435
- description: "Random text content"
1394
+ description: "Deflate-encoded content"
1436
1395
  }
1437
1396
  }
1438
1397
  };
1439
- var htmlSchema = {
1440
- description: "Returns random HTML content",
1398
+ var brotliSchema = {
1399
+ description: "Returns Brotli-encoded data",
1441
1400
  tags: [
1442
- "Response Inspection"
1401
+ "Response Formats"
1443
1402
  ],
1444
- // @ts-expect-error
1445
1403
  response: {
1446
1404
  200: {
1447
1405
  type: "string",
1448
- description: "Random HTML content"
1406
+ description: "Brotli-encoded content"
1449
1407
  }
1450
1408
  }
1451
1409
  };
@@ -1547,47 +1505,636 @@ var randomHtmlContent = [
1547
1505
  </body>
1548
1506
  </html>`
1549
1507
  ];
1550
- var plainRoute = /* @__PURE__ */ __name((fastify) => {
1551
- fastify.get(
1552
- "/plain",
1553
- {
1554
- schema: plainSchema
1508
+ var randomXmlContent = [
1509
+ `<?xml version="1.0" encoding="UTF-8"?>
1510
+ <root>
1511
+ <message>Hello from MockHTTP</message>
1512
+ <timestamp>${(/* @__PURE__ */ new Date()).toISOString()}</timestamp>
1513
+ <status>success</status>
1514
+ </root>`,
1515
+ `<?xml version="1.0" encoding="UTF-8"?>
1516
+ <book>
1517
+ <title>The Great Gatsby</title>
1518
+ <author>F. Scott Fitzgerald</author>
1519
+ <year>1925</year>
1520
+ <publisher>Charles Scribner's Sons</publisher>
1521
+ <isbn>978-0-7432-7356-5</isbn>
1522
+ </book>`,
1523
+ `<?xml version="1.0" encoding="UTF-8"?>
1524
+ <users>
1525
+ <user id="1">
1526
+ <name>John Doe</name>
1527
+ <email>john@example.com</email>
1528
+ <role>admin</role>
1529
+ </user>
1530
+ <user id="2">
1531
+ <name>Jane Smith</name>
1532
+ <email>jane@example.com</email>
1533
+ <role>user</role>
1534
+ </user>
1535
+ </users>`,
1536
+ `<?xml version="1.0" encoding="UTF-8"?>
1537
+ <product>
1538
+ <id>12345</id>
1539
+ <name>Wireless Mouse</name>
1540
+ <description>Ergonomic wireless mouse with 3-year battery life</description>
1541
+ <price currency="USD">29.99</price>
1542
+ <stock>150</stock>
1543
+ <category>Electronics</category>
1544
+ </product>`,
1545
+ `<?xml version="1.0" encoding="UTF-8"?>
1546
+ <rss version="2.0">
1547
+ <channel>
1548
+ <title>Mock RSS Feed</title>
1549
+ <link>http://example.com/rss</link>
1550
+ <description>Sample RSS feed from MockHTTP</description>
1551
+ <item>
1552
+ <title>First Article</title>
1553
+ <link>http://example.com/article1</link>
1554
+ <description>This is the first article in our feed</description>
1555
+ <pubDate>${(/* @__PURE__ */ new Date()).toUTCString()}</pubDate>
1556
+ </item>
1557
+ </channel>
1558
+ </rss>`
1559
+ ];
1560
+ var randomJsonContent = [
1561
+ () => ({
1562
+ message: "Hello from MockHTTP",
1563
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1564
+ status: "success",
1565
+ code: 200
1566
+ }),
1567
+ () => ({
1568
+ user: {
1569
+ id: 1,
1570
+ name: "John Doe",
1571
+ email: "john@example.com",
1572
+ role: "admin",
1573
+ createdAt: "2024-01-15T10:30:00Z"
1574
+ },
1575
+ permissions: [
1576
+ "read",
1577
+ "write",
1578
+ "delete"
1579
+ ]
1580
+ }),
1581
+ () => ({
1582
+ products: [
1583
+ {
1584
+ id: 101,
1585
+ name: "Laptop",
1586
+ price: 999.99,
1587
+ stock: 50
1588
+ },
1589
+ {
1590
+ id: 102,
1591
+ name: "Mouse",
1592
+ price: 29.99,
1593
+ stock: 200
1594
+ }
1595
+ ],
1596
+ total: 2,
1597
+ page: 1
1598
+ }),
1599
+ () => ({
1600
+ config: {
1601
+ theme: "dark",
1602
+ language: "en",
1603
+ notifications: {
1604
+ email: true,
1605
+ push: false,
1606
+ sms: false
1607
+ },
1608
+ privacy: {
1609
+ profile: "public",
1610
+ activity: "friends"
1611
+ }
1612
+ }
1613
+ }),
1614
+ () => ({
1615
+ metrics: {
1616
+ cpu: 45.2,
1617
+ memory: 78.5,
1618
+ disk: 62.3,
1619
+ network: {
1620
+ inbound: "1.2MB/s",
1621
+ outbound: "0.8MB/s"
1622
+ },
1623
+ uptime: "15 days",
1624
+ services: [
1625
+ {
1626
+ name: "api",
1627
+ status: "healthy"
1628
+ },
1629
+ {
1630
+ name: "database",
1631
+ status: "healthy"
1632
+ },
1633
+ {
1634
+ name: "cache",
1635
+ status: "warning"
1636
+ }
1637
+ ]
1638
+ }
1639
+ })
1640
+ ];
1641
+ var responseFormatRoutes = /* @__PURE__ */ __name((fastify) => {
1642
+ const plainHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1643
+ const randomIndex = Math.floor(Math.random() * randomTexts.length);
1644
+ const text = randomTexts[randomIndex];
1645
+ reply.type("text/plain");
1646
+ return text;
1647
+ }, "plainHandler");
1648
+ fastify.get("/plain", {
1649
+ schema: plainSchema
1650
+ }, plainHandler);
1651
+ fastify.post("/plain", {
1652
+ schema: plainSchema
1653
+ }, plainHandler);
1654
+ fastify.put("/plain", {
1655
+ schema: plainSchema
1656
+ }, plainHandler);
1657
+ fastify.patch("/plain", {
1658
+ schema: plainSchema
1659
+ }, plainHandler);
1660
+ fastify.delete("/plain", {
1661
+ schema: plainSchema
1662
+ }, plainHandler);
1663
+ const textHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1664
+ const randomIndex = Math.floor(Math.random() * randomTexts.length);
1665
+ const text = randomTexts[randomIndex];
1666
+ reply.type("text/plain");
1667
+ return text;
1668
+ }, "textHandler");
1669
+ fastify.get("/text", {
1670
+ schema: textSchema
1671
+ }, textHandler);
1672
+ fastify.post("/text", {
1673
+ schema: textSchema
1674
+ }, textHandler);
1675
+ fastify.put("/text", {
1676
+ schema: textSchema
1677
+ }, textHandler);
1678
+ fastify.patch("/text", {
1679
+ schema: textSchema
1680
+ }, textHandler);
1681
+ fastify.delete("/text", {
1682
+ schema: textSchema
1683
+ }, textHandler);
1684
+ const htmlHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1685
+ const randomIndex = Math.floor(Math.random() * randomHtmlContent.length);
1686
+ const html = randomHtmlContent[randomIndex];
1687
+ reply.type("text/html");
1688
+ return html;
1689
+ }, "htmlHandler");
1690
+ fastify.get("/html", {
1691
+ schema: htmlSchema
1692
+ }, htmlHandler);
1693
+ fastify.post("/html", {
1694
+ schema: htmlSchema
1695
+ }, htmlHandler);
1696
+ fastify.put("/html", {
1697
+ schema: htmlSchema
1698
+ }, htmlHandler);
1699
+ fastify.patch("/html", {
1700
+ schema: htmlSchema
1701
+ }, htmlHandler);
1702
+ fastify.delete("/html", {
1703
+ schema: htmlSchema
1704
+ }, htmlHandler);
1705
+ const xmlHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1706
+ const randomIndex = Math.floor(Math.random() * randomXmlContent.length);
1707
+ const xml = randomXmlContent[randomIndex];
1708
+ reply.type("application/xml");
1709
+ return xml;
1710
+ }, "xmlHandler");
1711
+ fastify.get("/xml", {
1712
+ schema: xmlSchema
1713
+ }, xmlHandler);
1714
+ fastify.post("/xml", {
1715
+ schema: xmlSchema
1716
+ }, xmlHandler);
1717
+ fastify.put("/xml", {
1718
+ schema: xmlSchema
1719
+ }, xmlHandler);
1720
+ fastify.patch("/xml", {
1721
+ schema: xmlSchema
1722
+ }, xmlHandler);
1723
+ fastify.delete("/xml", {
1724
+ schema: xmlSchema
1725
+ }, xmlHandler);
1726
+ const jsonHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1727
+ const randomIndex = Math.floor(Math.random() * randomJsonContent.length);
1728
+ const jsonGenerator = randomJsonContent[randomIndex];
1729
+ const json = jsonGenerator();
1730
+ reply.type("application/json");
1731
+ return json;
1732
+ }, "jsonHandler");
1733
+ fastify.get("/json", {
1734
+ schema: jsonSchema
1735
+ }, jsonHandler);
1736
+ fastify.post("/json", {
1737
+ schema: jsonSchema
1738
+ }, jsonHandler);
1739
+ fastify.put("/json", {
1740
+ schema: jsonSchema
1741
+ }, jsonHandler);
1742
+ fastify.patch("/json", {
1743
+ schema: jsonSchema
1744
+ }, jsonHandler);
1745
+ fastify.delete("/json", {
1746
+ schema: jsonSchema
1747
+ }, jsonHandler);
1748
+ const denyHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1749
+ const denyMessages = [
1750
+ `<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
1751
+ <html><head>
1752
+ <title>403 Forbidden</title>
1753
+ </head><body>
1754
+ <h1>Forbidden</h1>
1755
+ <p>Access denied by robots.txt rules.</p>
1756
+ <p>The requested resource is disallowed by robots.txt.</p>
1757
+ </body></html>`,
1758
+ `<!DOCTYPE html>
1759
+ <html lang="en">
1760
+ <head>
1761
+ <meta charset="UTF-8">
1762
+ <title>403 - Access Denied</title>
1763
+ </head>
1764
+ <body>
1765
+ <h1>403 Forbidden</h1>
1766
+ <p>This page is blocked by robots.txt rules.</p>
1767
+ <p>User-agent: *<br>Disallow: ${_request.url}</p>
1768
+ </body>
1769
+ </html>`,
1770
+ `<!DOCTYPE html>
1771
+ <html>
1772
+ <head>
1773
+ <title>403 - Access Denied</title>
1774
+ <style>body { font-family: Arial, sans-serif; margin: 40px; }</style>
1775
+ </head>
1776
+ <body>
1777
+ <h2>403 - Access Denied by robots.txt</h2>
1778
+ <p>The robots.txt file prevents access to this resource.</p>
1779
+ <hr>
1780
+ <small>MockHTTP Server</small>
1781
+ </body>
1782
+ </html>`
1783
+ ];
1784
+ const randomIndex = Math.floor(Math.random() * denyMessages.length);
1785
+ const html = denyMessages[randomIndex];
1786
+ reply.code(403);
1787
+ reply.type("text/html");
1788
+ return html;
1789
+ }, "denyHandler");
1790
+ fastify.get("/deny", {
1791
+ schema: denySchema
1792
+ }, denyHandler);
1793
+ fastify.post("/deny", {
1794
+ schema: denySchema
1795
+ }, denyHandler);
1796
+ fastify.put("/deny", {
1797
+ schema: denySchema
1798
+ }, denyHandler);
1799
+ fastify.patch("/deny", {
1800
+ schema: denySchema
1801
+ }, denyHandler);
1802
+ fastify.delete("/deny", {
1803
+ schema: denySchema
1804
+ }, denyHandler);
1805
+ const gzipHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1806
+ const sampleData = [
1807
+ {
1808
+ message: "This is GZip compressed data from MockHTTP",
1809
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1810
+ compression: "gzip",
1811
+ originalSize: 0,
1812
+ compressedSize: 0
1813
+ },
1814
+ {
1815
+ title: "Sample Document",
1816
+ content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. ".repeat(50),
1817
+ metadata: {
1818
+ author: "MockHTTP Server",
1819
+ format: "gzip",
1820
+ version: "1.0"
1821
+ }
1822
+ },
1823
+ {
1824
+ data: Array.from({
1825
+ length: 100
1826
+ }, (_, i) => ({
1827
+ id: i + 1,
1828
+ value: `Item ${i + 1}`,
1829
+ description: `This is item number ${i + 1} in the dataset`
1830
+ })),
1831
+ info: "Large dataset compressed with GZip"
1832
+ }
1833
+ ];
1834
+ const randomIndex = Math.floor(Math.random() * sampleData.length);
1835
+ const data = sampleData[randomIndex];
1836
+ const jsonString = JSON.stringify(data);
1837
+ if (data.originalSize !== void 0) {
1838
+ data.originalSize = Buffer.byteLength(jsonString);
1839
+ }
1840
+ const compressed = gzipSync(jsonString);
1841
+ if (data.compressedSize !== void 0) {
1842
+ const updatedData = {
1843
+ ...data,
1844
+ compressedSize: compressed.length
1845
+ };
1846
+ const updatedJsonString = JSON.stringify(updatedData);
1847
+ const updatedCompressed = gzipSync(updatedJsonString);
1848
+ reply.header("Content-Encoding", "gzip");
1849
+ reply.header("Content-Type", "application/json");
1850
+ reply.type("application/octet-stream");
1851
+ return updatedCompressed;
1852
+ }
1853
+ reply.header("Content-Encoding", "gzip");
1854
+ reply.header("Content-Type", "application/json");
1855
+ reply.type("application/octet-stream");
1856
+ return compressed;
1857
+ }, "gzipHandler");
1858
+ fastify.get("/gzip", {
1859
+ schema: gzipSchema
1860
+ }, gzipHandler);
1861
+ fastify.post("/gzip", {
1862
+ schema: gzipSchema
1863
+ }, gzipHandler);
1864
+ fastify.put("/gzip", {
1865
+ schema: gzipSchema
1866
+ }, gzipHandler);
1867
+ fastify.patch("/gzip", {
1868
+ schema: gzipSchema
1869
+ }, gzipHandler);
1870
+ fastify.delete("/gzip", {
1871
+ schema: gzipSchema
1872
+ }, gzipHandler);
1873
+ const deflateHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1874
+ const sampleData = [
1875
+ {
1876
+ message: "This is Deflate compressed data from MockHTTP",
1877
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1878
+ compression: "deflate",
1879
+ originalSize: 0,
1880
+ compressedSize: 0
1881
+ },
1882
+ {
1883
+ title: "Deflate Compressed Document",
1884
+ content: "The deflate algorithm is used for compression. ".repeat(40),
1885
+ details: {
1886
+ algorithm: "DEFLATE",
1887
+ method: "zlib deflate",
1888
+ server: "MockHTTP"
1889
+ }
1890
+ },
1891
+ {
1892
+ items: Array.from({
1893
+ length: 50
1894
+ }, (_, i) => ({
1895
+ index: i,
1896
+ name: `Entry ${i}`,
1897
+ data: `This is test data for entry number ${i}`,
1898
+ timestamp: new Date(Date.now() - i * 1e6).toISOString()
1899
+ })),
1900
+ metadata: {
1901
+ compression: "deflate",
1902
+ count: 50
1903
+ }
1904
+ }
1905
+ ];
1906
+ const randomIndex = Math.floor(Math.random() * sampleData.length);
1907
+ const data = sampleData[randomIndex];
1908
+ const jsonString = JSON.stringify(data);
1909
+ if (data.originalSize !== void 0) {
1910
+ data.originalSize = Buffer.byteLength(jsonString);
1911
+ }
1912
+ const compressed = deflateSync(jsonString);
1913
+ if (data.compressedSize !== void 0) {
1914
+ const updatedData = {
1915
+ ...data,
1916
+ compressedSize: compressed.length
1917
+ };
1918
+ const updatedJsonString = JSON.stringify(updatedData);
1919
+ const updatedCompressed = deflateSync(updatedJsonString);
1920
+ reply.header("Content-Encoding", "deflate");
1921
+ reply.header("Content-Type", "application/json");
1922
+ reply.type("application/octet-stream");
1923
+ return updatedCompressed;
1924
+ }
1925
+ reply.header("Content-Encoding", "deflate");
1926
+ reply.header("Content-Type", "application/json");
1927
+ reply.type("application/octet-stream");
1928
+ return compressed;
1929
+ }, "deflateHandler");
1930
+ fastify.get("/deflate", {
1931
+ schema: deflateSchema
1932
+ }, deflateHandler);
1933
+ fastify.post("/deflate", {
1934
+ schema: deflateSchema
1935
+ }, deflateHandler);
1936
+ fastify.put("/deflate", {
1937
+ schema: deflateSchema
1938
+ }, deflateHandler);
1939
+ fastify.patch("/deflate", {
1940
+ schema: deflateSchema
1941
+ }, deflateHandler);
1942
+ fastify.delete("/deflate", {
1943
+ schema: deflateSchema
1944
+ }, deflateHandler);
1945
+ const brotliHandler = /* @__PURE__ */ __name(async (_request, reply) => {
1946
+ const sampleData = [
1947
+ {
1948
+ message: "This is Brotli compressed data from MockHTTP",
1949
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1950
+ compression: "br",
1951
+ algorithm: "Brotli",
1952
+ originalSize: 0,
1953
+ compressedSize: 0
1954
+ },
1955
+ {
1956
+ title: "Brotli Compression Example",
1957
+ description: "Brotli is a generic-purpose lossless compression algorithm that compresses data using a combination of a modern variant of the LZ77 algorithm, Huffman coding and 2nd order context modeling.",
1958
+ content: "Brotli compression typically achieves 20-26% better compression ratios than gzip. ".repeat(10),
1959
+ metadata: {
1960
+ encoding: "br",
1961
+ quality: 11,
1962
+ server: "MockHTTP"
1963
+ }
1964
+ },
1965
+ {
1966
+ benchmark: {
1967
+ title: "Compression Benchmark Data",
1968
+ results: Array.from({
1969
+ length: 75
1970
+ }, (_, i) => ({
1971
+ id: `test-${i}`,
1972
+ name: `Benchmark Test ${i}`,
1973
+ value: Math.random() * 1e3,
1974
+ unit: "ms",
1975
+ timestamp: new Date(Date.now() - i * 6e4).toISOString()
1976
+ })),
1977
+ summary: {
1978
+ compression: "brotli",
1979
+ totalTests: 75,
1980
+ encoding: "br"
1981
+ }
1982
+ }
1983
+ }
1984
+ ];
1985
+ const randomIndex = Math.floor(Math.random() * sampleData.length);
1986
+ const data = sampleData[randomIndex];
1987
+ const jsonString = JSON.stringify(data);
1988
+ if (data.originalSize !== void 0) {
1989
+ data.originalSize = Buffer.byteLength(jsonString);
1990
+ }
1991
+ const compressed = brotliCompressSync(jsonString);
1992
+ if (data.compressedSize !== void 0) {
1993
+ const updatedData = {
1994
+ ...data,
1995
+ compressedSize: compressed.length
1996
+ };
1997
+ const updatedJsonString = JSON.stringify(updatedData);
1998
+ const updatedCompressed = brotliCompressSync(updatedJsonString);
1999
+ reply.header("Content-Encoding", "br");
2000
+ reply.header("Content-Type", "application/json");
2001
+ reply.type("application/octet-stream");
2002
+ return updatedCompressed;
2003
+ }
2004
+ reply.header("Content-Encoding", "br");
2005
+ reply.header("Content-Type", "application/json");
2006
+ reply.type("application/octet-stream");
2007
+ return compressed;
2008
+ }, "brotliHandler");
2009
+ fastify.get("/brotli", {
2010
+ schema: brotliSchema
2011
+ }, brotliHandler);
2012
+ fastify.post("/brotli", {
2013
+ schema: brotliSchema
2014
+ }, brotliHandler);
2015
+ fastify.put("/brotli", {
2016
+ schema: brotliSchema
2017
+ }, brotliHandler);
2018
+ fastify.patch("/brotli", {
2019
+ schema: brotliSchema
2020
+ }, brotliHandler);
2021
+ fastify.delete("/brotli", {
2022
+ schema: brotliSchema
2023
+ }, brotliHandler);
2024
+ }, "responseFormatRoutes");
2025
+
2026
+ // src/routes/response-inspection/cache.ts
2027
+ var cacheGetSchema = {
2028
+ description: "Handles cache validation and retrieval.",
2029
+ tags: [
2030
+ "Response Inspection"
2031
+ ],
2032
+ response: {
2033
+ 200: {
2034
+ type: "string",
2035
+ description: "The cached content or resource."
2036
+ },
2037
+ 304: {
2038
+ type: "null",
2039
+ description: "Indicates the resource has not been modified."
2040
+ }
2041
+ }
2042
+ };
2043
+ var cacheSetSchema = {
2044
+ description: "Sets a Cache-Control header for n seconds.",
2045
+ tags: [
2046
+ "Response Inspection"
2047
+ ],
2048
+ params: {
2049
+ type: "object",
2050
+ properties: {
2051
+ value: {
2052
+ type: "integer",
2053
+ description: "Number of seconds to cache the resource."
2054
+ }
2055
+ },
2056
+ required: [
2057
+ "value"
2058
+ ]
2059
+ },
2060
+ response: {
2061
+ 200: {
2062
+ type: "string",
2063
+ description: "Confirmation message for setting cache."
2064
+ }
2065
+ }
2066
+ };
2067
+ var cacheRoutes = /* @__PURE__ */ __name((fastify) => {
2068
+ fastify.get("/cache", {
2069
+ schema: cacheGetSchema
2070
+ }, async (request, reply) => {
2071
+ const ifModifiedSince = request.headers["if-modified-since"];
2072
+ const ifNoneMatch = request.headers["if-none-match"];
2073
+ if (ifModifiedSince ?? ifNoneMatch) {
2074
+ await reply.status(304).send();
2075
+ return;
2076
+ }
2077
+ await reply.send("Cache content or resource response here.");
2078
+ });
2079
+ fastify.get("/cache/:value", {
2080
+ schema: cacheSetSchema
2081
+ }, async (request, reply) => {
2082
+ const { value } = request.params;
2083
+ await reply.header("Cache-Control", `max-age=${value}`).send(`Cache-Control set for ${value} seconds.`);
2084
+ });
2085
+ }, "cacheRoutes");
2086
+
2087
+ // src/routes/response-inspection/etag.ts
2088
+ var etagSchema = {
2089
+ description: "Handles ETag-based conditional requests.",
2090
+ tags: [
2091
+ "Response Inspection"
2092
+ ],
2093
+ params: {
2094
+ type: "object",
2095
+ properties: {
2096
+ etag: {
2097
+ type: "string",
2098
+ description: "The ETag value for the resource."
2099
+ }
1555
2100
  },
1556
- // biome-ignore lint/suspicious/noExplicitAny: reply
1557
- async (_request, reply) => {
1558
- const randomIndex = Math.floor(Math.random() * randomTexts.length);
1559
- const text = randomTexts[randomIndex];
1560
- reply.type("text/plain");
1561
- return text;
1562
- }
1563
- );
1564
- fastify.get(
1565
- "/text",
1566
- {
1567
- schema: textSchema
2101
+ required: [
2102
+ "etag"
2103
+ ]
2104
+ },
2105
+ response: {
2106
+ 200: {
2107
+ type: "string",
2108
+ description: "Resource content for matching ETag."
1568
2109
  },
1569
- // biome-ignore lint/suspicious/noExplicitAny: reply
1570
- async (_request, reply) => {
1571
- const randomIndex = Math.floor(Math.random() * randomTexts.length);
1572
- const text = randomTexts[randomIndex];
1573
- reply.type("text/plain");
1574
- return text;
1575
- }
1576
- );
1577
- fastify.get(
1578
- "/html",
1579
- {
1580
- schema: htmlSchema
2110
+ 304: {
2111
+ type: "null",
2112
+ description: "Indicates the resource has not been modified."
1581
2113
  },
1582
- // biome-ignore lint/suspicious/noExplicitAny: reply
1583
- async (_request, reply) => {
1584
- const randomIndex = Math.floor(Math.random() * randomHtmlContent.length);
1585
- const html = randomHtmlContent[randomIndex];
1586
- reply.type("text/html");
1587
- return html;
1588
- }
1589
- );
1590
- }, "plainRoute");
2114
+ 412: {
2115
+ type: "null",
2116
+ description: "Indicates a precondition failed due to mismatched ETag."
2117
+ }
2118
+ }
2119
+ };
2120
+ var etagRoutes = /* @__PURE__ */ __name((fastify) => {
2121
+ fastify.get("/etag/:etag", {
2122
+ schema: etagSchema
2123
+ }, async (request, reply) => {
2124
+ const { etag } = request.params;
2125
+ const ifNoneMatch = request.headers["if-none-match"];
2126
+ const ifMatch = request.headers["if-match"];
2127
+ if (ifNoneMatch === etag) {
2128
+ await reply.status(304).send();
2129
+ return;
2130
+ }
2131
+ if (ifMatch && ifMatch !== etag) {
2132
+ await reply.status(412).send();
2133
+ return;
2134
+ }
2135
+ await reply.header("ETag", etag).send("Resource content for matching ETag.");
2136
+ });
2137
+ }, "etagRoutes");
1591
2138
 
1592
2139
  // src/routes/response-inspection/response-headers.ts
1593
2140
  import { escape as escapeHtml } from "html-escaper";
@@ -1988,7 +2535,7 @@ import { fastifySwaggerUi } from "@fastify/swagger-ui";
1988
2535
  // package.json
1989
2536
  var package_default = {
1990
2537
  name: "@jaredwray/mockhttp",
1991
- version: "0.8.0",
2538
+ version: "0.9.0",
1992
2539
  description: "Mock Http - Easy way to mock http with httpbin replacement",
1993
2540
  type: "module",
1994
2541
  main: "dist/index.js",
@@ -2130,6 +2677,7 @@ var MockHttp = class extends Hookified {
2130
2677
  redirects: true,
2131
2678
  requestInspection: true,
2132
2679
  responseInspection: true,
2680
+ responseFormats: true,
2133
2681
  statusCodes: true,
2134
2682
  cookies: true,
2135
2683
  anything: true,
@@ -2272,7 +2820,7 @@ var MockHttp = class extends Hookified {
2272
2820
  if (this._apiDocs) {
2273
2821
  await this.registerApiDocs();
2274
2822
  }
2275
- const { httpMethods, redirects, requestInspection, responseInspection, statusCodes: statusCodes2, cookies, anything, auth } = this._httpBin;
2823
+ const { httpMethods, redirects, requestInspection, responseInspection, responseFormats, statusCodes: statusCodes2, cookies, anything, auth } = this._httpBin;
2276
2824
  if (httpMethods) {
2277
2825
  await this.registerHttpMethods();
2278
2826
  }
@@ -2285,6 +2833,9 @@ var MockHttp = class extends Hookified {
2285
2833
  if (responseInspection) {
2286
2834
  await this.registerResponseInspectionRoutes();
2287
2835
  }
2836
+ if (responseFormats) {
2837
+ await this.registerResponseFormatRoutes();
2838
+ }
2288
2839
  if (redirects) {
2289
2840
  await this.registerRedirectRoutes();
2290
2841
  }
@@ -2374,9 +2925,12 @@ var MockHttp = class extends Hookified {
2374
2925
  const fastify = fastifyInstance ?? this._server;
2375
2926
  await fastify.register(cacheRoutes);
2376
2927
  await fastify.register(etagRoutes);
2377
- await fastify.register(plainRoute);
2378
2928
  await fastify.register(responseHeadersRoutes);
2379
2929
  }
2930
+ async registerResponseFormatRoutes(fastifyInstance) {
2931
+ const fastify = fastifyInstance ?? this._server;
2932
+ await fastify.register(responseFormatRoutes);
2933
+ }
2380
2934
  /**
2381
2935
  * Register the redirect routes.
2382
2936
  * @param fastifyInstance - the server instance to register the routes on.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaredwray/mockhttp",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Mock Http - Easy way to mock http with httpbin replacement",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",