queryapigate 0.22.0__tar.gz → 0.22.1__tar.gz

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 (189) hide show
  1. {queryapigate-0.22.0/queryapigate.egg-info → queryapigate-0.22.1}/PKG-INFO +1 -1
  2. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/__init__.py +1 -1
  3. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/app.py +10 -2
  4. {queryapigate-0.22.0 → queryapigate-0.22.1/queryapigate.egg-info}/PKG-INFO +1 -1
  5. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_response_cache.py +5 -1
  6. {queryapigate-0.22.0 → queryapigate-0.22.1}/LICENSE +0 -0
  7. {queryapigate-0.22.0 → queryapigate-0.22.1}/README.md +0 -0
  8. {queryapigate-0.22.0 → queryapigate-0.22.1}/pyproject.toml +0 -0
  9. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/__main__.py +0 -0
  10. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/adminroles.py +0 -0
  11. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/admins.py +0 -0
  12. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/agentwrites.py +0 -0
  13. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/alerts.py +0 -0
  14. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/apikeys.py +0 -0
  15. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/broadcast.py +0 -0
  16. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/bundle.py +0 -0
  17. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/cache.py +0 -0
  18. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/cli.py +0 -0
  19. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/collection_admin.py +0 -0
  20. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/config.py +0 -0
  21. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console.py +0 -0
  22. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/AccessMapPage-CJHNlXPv.js +0 -0
  23. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/AdministratorsPage-BbYhO2eo.js +0 -0
  24. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/AgentsPage-DDCauW-7.js +0 -0
  25. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/AlertsPage-CazNtrHo.js +0 -0
  26. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/ApiKeysPage-DhK31mF7.js +0 -0
  27. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/ApprovalsPage-feItqvUh.js +0 -0
  28. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/AuditLogPage-Sv21w03B.js +0 -0
  29. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/CachingPage-DUyqx9Dg.js +0 -0
  30. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/CodeBox-DPiCVuYm.js +0 -0
  31. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/ConnectionsPage-B1FW0Sv-.js +0 -0
  32. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/DesignerPage-Da52fUjh.js +0 -0
  33. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/DestinationsPage-BvcXYIwC.js +0 -0
  34. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/Experimental-Cev0t6Ci.js +0 -0
  35. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/ExportsPage-Csyn3Ghf.js +0 -0
  36. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/HelpPage-C1cQioeI.js +0 -0
  37. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/HomePage-BRhhEL2z.js +0 -0
  38. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/MetricsPage-CgSxzDOE.js +0 -0
  39. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/RepositoryPage-xiZEg7f4.js +0 -0
  40. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/Results-CKzkIgXw.js +0 -0
  41. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/RolesPage-C9G0dlSf.js +0 -0
  42. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/SchemaBrowser-7JFHE2g9.js +0 -0
  43. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/SettingsPage-BFoHW1XP.js +0 -0
  44. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/StatTile-Dx6Azb_P.js +0 -0
  45. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/Time-GG1SZb8S.js +0 -0
  46. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/forms-BCfnOm9v.js +0 -0
  47. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/forms-C8ZdFl7Q.js +0 -0
  48. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/icons-plWox3cc.js +0 -0
  49. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/index-CBaM_ckR.css +0 -0
  50. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/index-k1HFugKb.js +0 -0
  51. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/maskRules-B0nXSvKz.js +0 -0
  52. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/reach-BKjZYR1f.js +0 -0
  53. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/shared-UtKm-F9c.js +0 -0
  54. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/state-O13cl7cO.js +0 -0
  55. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/assets/useMutation-CzHKbjEU.js +0 -0
  56. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/favicon.svg +0 -0
  57. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/console_dist/index.html +0 -0
  58. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/cors.py +0 -0
  59. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/databases.py +0 -0
  60. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/db.py +0 -0
  61. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/definitions.py +0 -0
  62. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/deprecations.py +0 -0
  63. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/descriptions.py +0 -0
  64. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/destinations.py +0 -0
  65. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/duckfiles.py +0 -0
  66. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/engine.py +0 -0
  67. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/errors.py +0 -0
  68. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/events.py +0 -0
  69. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/examples.py +0 -0
  70. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/experimental.py +0 -0
  71. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/exporting.py +0 -0
  72. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/exports.py +0 -0
  73. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/formats.py +0 -0
  74. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/governance.py +0 -0
  75. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/history.py +0 -0
  76. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/instances.py +0 -0
  77. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/jwtauth.py +0 -0
  78. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/lib/h2-2.2.224.jar +0 -0
  79. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/logging_setup.py +0 -0
  80. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/masking.py +0 -0
  81. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/mcp_server.py +0 -0
  82. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/metrics.py +0 -0
  83. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/mongotools.py +0 -0
  84. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/oidc.py +0 -0
  85. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/openapi.py +0 -0
  86. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/params.py +0 -0
  87. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/parquet.py +0 -0
  88. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/pool.py +0 -0
  89. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/postman.py +0 -0
  90. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/ratelimit.py +0 -0
  91. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/rediscache.py +0 -0
  92. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/rekey.py +0 -0
  93. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/runners.py +0 -0
  94. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/schema.py +0 -0
  95. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/__init__.py +0 -0
  96. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/access.py +0 -0
  97. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/administrators.py +0 -0
  98. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/audit.py +0 -0
  99. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/collections.py +0 -0
  100. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/connections.py +0 -0
  101. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/descriptions.py +0 -0
  102. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/destinations.py +0 -0
  103. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/exports.py +0 -0
  104. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/mcp.py +0 -0
  105. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/services/queries.py +0 -0
  106. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/sqlflow.py +0 -0
  107. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/sqltools.py +0 -0
  108. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/sso.py +0 -0
  109. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/store.py +0 -0
  110. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/tableguard.py +0 -0
  111. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/usage.py +0 -0
  112. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/v1.py +0 -0
  113. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate/v1_spec.py +0 -0
  114. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate.egg-info/SOURCES.txt +0 -0
  115. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate.egg-info/dependency_links.txt +0 -0
  116. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate.egg-info/entry_points.txt +0 -0
  117. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate.egg-info/requires.txt +0 -0
  118. {queryapigate-0.22.0 → queryapigate-0.22.1}/queryapigate.egg-info/top_level.txt +0 -0
  119. {queryapigate-0.22.0 → queryapigate-0.22.1}/setup.cfg +0 -0
  120. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_adhoc_history.py +0 -0
  121. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_adminroles.py +0 -0
  122. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_admins.py +0 -0
  123. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_agent_writes.py +0 -0
  124. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_alerts.py +0 -0
  125. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_api_administrators.py +0 -0
  126. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_api_keys.py +0 -0
  127. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_api_v1.py +0 -0
  128. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_audit_log.py +0 -0
  129. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_backup_restore.py +0 -0
  130. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_broadcast.py +0 -0
  131. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_cli.py +0 -0
  132. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_collection_bundle.py +0 -0
  133. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_collection_postman.py +0 -0
  134. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_collections.py +0 -0
  135. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_connection_encryption.py +0 -0
  136. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_console.py +0 -0
  137. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_cors_and_rate_limit.py +0 -0
  138. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_databases.py +0 -0
  139. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_db.py +0 -0
  140. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_dependency_floors.py +0 -0
  141. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_deprecations.py +0 -0
  142. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_descriptions.py +0 -0
  143. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_destinations.py +0 -0
  144. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_duckdb.py +0 -0
  145. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_duckdb_files.py +0 -0
  146. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_errors.py +0 -0
  147. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_events.py +0 -0
  148. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_events_server.py +0 -0
  149. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_examples.py +0 -0
  150. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_experimental.py +0 -0
  151. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_export_security.py +0 -0
  152. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_exporting.py +0 -0
  153. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_exports.py +0 -0
  154. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_history.py +0 -0
  155. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_howto.py +0 -0
  156. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_instances.py +0 -0
  157. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_integration.py +0 -0
  158. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_jdbc.py +0 -0
  159. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_jwt.py +0 -0
  160. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_key_rotation.py +0 -0
  161. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_masking.py +0 -0
  162. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_masking_requests.py +0 -0
  163. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_mcp.py +0 -0
  164. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_mcp_keycloak.py +0 -0
  165. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_mcp_oauth.py +0 -0
  166. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_mongotools.py +0 -0
  167. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_multinode.py +0 -0
  168. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_observability.py +0 -0
  169. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_oidc.py +0 -0
  170. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_params.py +0 -0
  171. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_parquet.py +0 -0
  172. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_pool.py +0 -0
  173. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_publishing.py +0 -0
  174. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_query_window.py +0 -0
  175. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_queryapigate.py +0 -0
  176. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_rekey.py +0 -0
  177. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_release_check.py +0 -0
  178. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_roles.py +0 -0
  179. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_rolling_upgrade.py +0 -0
  180. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_settings.py +0 -0
  181. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_shared_rate_limit.py +0 -0
  182. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_sql_guard_fuzz.py +0 -0
  183. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_sql_guard_writes.py +0 -0
  184. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_sqlflow.py +0 -0
  185. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_sso.py +0 -0
  186. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_sso_keycloak.py +0 -0
  187. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_tableguard.py +0 -0
  188. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_upgrades.py +0 -0
  189. {queryapigate-0.22.0 → queryapigate-0.22.1}/tests/test_usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: queryapigate
3
- Version: 0.22.0
3
+ Version: 0.22.1
4
4
  Summary: Turn SQL into governed REST APIs over MySQL, PostgreSQL, ClickHouse, SQLite, DuckDB, H2, MongoDB, and Parquet/CSV/JSON files - JSON, CSV, Parquet or Excel out, with scoped keys, an admin Console and MCP for AI agents.
5
5
  Author-email: Anantha Raju C <arcswdev@gmail.com>
6
6
  License-Expression: FSL-1.1-MIT
@@ -1,5 +1,5 @@
1
1
  """QueryAPIGate - expose SQL databases as a REST API."""
2
- __version__ = '0.22.0'
2
+ __version__ = '0.22.1'
3
3
 
4
4
  from .app import create_app # noqa: E402 (app imports __version__)
5
5
 
@@ -607,6 +607,14 @@ def execute_mongo_endpoint():
607
607
  return render(result, output_format, page, limit)
608
608
 
609
609
 
610
+ def _client_cache_control(ttl):
611
+ """How long the *caller* may keep a cached response - `private`, so only the caller's own client may: a request
612
+ authenticates with X-API-Key, not Authorization, so HTTP's rule keeping authenticated responses out of shared
613
+ caches (RFC 9111 3.5) doesn't apply, and a CDN or caching proxy in front would otherwise keep one caller's rows -
614
+ masked for its key - and serve them to the next caller of that URL, with any key or none."""
615
+ return f'private, max-age={ttl}'
616
+
617
+
610
618
  def cache_lookup(cache_key, ttl):
611
619
  """A live entry rendered as a response (304 if the client already has it), or None on a cache miss."""
612
620
  hit = current_app.extensions['queryapigate_cache'].get(cache_key)
@@ -621,7 +629,7 @@ def cache_lookup(cache_key, ttl):
621
629
  for name, value in headers:
622
630
  response.headers[name] = value
623
631
  response.headers['ETag'] = quoted
624
- response.headers['Cache-Control'] = f'max-age={ttl}'
632
+ response.headers['Cache-Control'] = _client_cache_control(ttl)
625
633
  response.headers['X-Cache'] = 'HIT'
626
634
  return response
627
635
 
@@ -635,7 +643,7 @@ def cache_store(cache_key, response, ttl, meta=None):
635
643
  etag = current_app.extensions['queryapigate_cache'].set(cache_key, response.get_data(), response.content_type,
636
644
  replay_headers, ttl, meta)
637
645
  response.headers['ETag'] = f'"{etag}"'
638
- response.headers['Cache-Control'] = f'max-age={ttl}'
646
+ response.headers['Cache-Control'] = _client_cache_control(ttl)
639
647
  response.headers['X-Cache'] = 'MISS'
640
648
  return response
641
649
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: queryapigate
3
- Version: 0.22.0
3
+ Version: 0.22.1
4
4
  Summary: Turn SQL into governed REST APIs over MySQL, PostgreSQL, ClickHouse, SQLite, DuckDB, H2, MongoDB, and Parquet/CSV/JSON files - JSON, CSV, Parquet or Excel out, with scoped keys, an admin Console and MCP for AI agents.
5
5
  Author-email: Anantha Raju C <arcswdev@gmail.com>
6
6
  License-Expression: FSL-1.1-MIT
@@ -371,9 +371,13 @@ class CacheHeaderTests(AppTestCase):
371
371
  first = self.client.get('/q/q?id=1')
372
372
  self.assertEqual(first.headers['X-Cache'], 'MISS')
373
373
  self.assertIn('ETag', first.headers)
374
- self.assertEqual(first.headers['Cache-Control'], 'max-age=60')
374
+ self.assertEqual(first.headers['Cache-Control'], 'private, max-age=60')
375
375
  second = self.client.get('/q/q?id=1')
376
376
  self.assertEqual(second.headers['X-Cache'], 'HIT')
377
+ # private on a hit and a 304 too: no shared cache in front may keep one caller's rows for the next caller
378
+ self.assertEqual(second.headers['Cache-Control'], 'private, max-age=60')
379
+ unchanged = self.client.get('/q/q?id=1', headers={'If-None-Match': first.headers['ETag']})
380
+ self.assertEqual((unchanged.status_code, unchanged.headers['Cache-Control']), (304, 'private, max-age=60'))
377
381
  self.assertEqual(second.get_data(), first.get_data())
378
382
  self.assertEqual(second.headers['ETag'], first.headers['ETag'])
379
383
 
File without changes
File without changes
File without changes