Skip to content

Add HTTP caching, JSON-only routes, 404 handling, and OpenAPI spec#77

Open
dsomel21 wants to merge 5 commits intomainfrom
http-rest-standards-and-openapi
Open

Add HTTP caching, JSON-only routes, 404 handling, and OpenAPI spec#77
dsomel21 wants to merge 5 commits intomainfrom
http-rest-standards-and-openapi

Conversation

@dsomel21
Copy link
Copy Markdown
Collaborator

Summary

  • Routes: All endpoints wrapped in defaults format: :json — clients no longer need .json suffix
  • Caching: New cache_and_validate helper in ApplicationController sets Cache-Control: public, max-age=3600, stale-while-revalidate=60 and wires up ETags + Last-Modified via Rails' fresh_when — repeat requests return 304 Not Modified when data hasn't changed
  • 404 handling: rescue_from ActiveRecord::RecordNotFound now returns a JSON error body { "error": "Not found" } with HTTP 404 instead of an HTML page
  • OpenAPI spec: doc/openapi.yaml — full OpenAPI 3.0 spec documenting all 6 endpoints, response schemas, caching headers, and conditional request parameters

Test plan

  • GET /books returns JSON without .json suffix
  • GET /books/9999 returns {"error":"Not found"} with status 404
  • GET /books with If-None-Match: <etag from first response> returns 304
  • Validate doc/openapi.yaml with Swagger Editor

🤖 Generated with Claude Code

dsomel21 and others added 5 commits March 31, 2026 08:20
…spec

- Routes: wrap all endpoints in `defaults format: :json` — no .json suffix needed
- ApplicationController: rescue RecordNotFound with JSON 404 response; add
  `cache_and_validate` helper that sets Cache-Control and calls `fresh_when`
  for ETag/Last-Modified conditional GET support (304 Not Modified)
- Books/Chapters controllers: call `cache_and_validate` on every action
- doc/openapi.yaml: full OpenAPI 3.0 spec documenting all 6 endpoints with
  caching headers, conditional request parameters, and all response schemas

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix Rubocop: use hash-rocket syntax throughout (project convention)
- Rename cache_and_validate → set_cache (avoid confusion with AR validations)
- Pass public: true to fresh_when explicitly rather than relying on
  the pre-set Cache-Control header being detected
- content action: use composite ETag/Last-Modified covering tuks and
  pauri_translations so edits to nested content invalidate client caches

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Gemfile: move csv before rack-cors (alphabetical order)
- Migration: rubocop:disable ThreeStateBooleanColumn (old migration, can't change)
- spec/rails_helper.rb: use Rails.root.glob instead of Dir[Rails.root.join]
- spec/models/chapter_spec.rb: rename book1/book2 to first_book/second_book
- spec/services/granth_importer_spec.rb: rename tuk1/tuk2 to first_tuk/second_tuk

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
These violations existed on main since before this PR. Suppressing them
via rubocop_todo.yml rather than touching unrelated files.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant