feat: Complete Phase 2.4 - HTTP Content Negotiation

Implements HTTP content negotiation for feed format selection.

Phase 2.4 Deliverables:
- Content negotiation via Accept header parsing
- Quality factor support (q= parameter)
- 5 feed endpoints with format routing
- 406 Not Acceptable responses with helpful errors
- Comprehensive test coverage (63 tests)

Endpoints:
- /feed - Content negotiation based on Accept header
- /feed.rss - Explicit RSS 2.0
- /feed.atom - Explicit ATOM 1.0
- /feed.json - Explicit JSON Feed 1.1
- /feed.xml - Backward compatibility (→ RSS)

MIME Type Mapping:
- application/rss+xml → RSS 2.0
- application/atom+xml → ATOM 1.0
- application/feed+json or application/json → JSON Feed 1.1
- */* → RSS 2.0 (default)

Implementation:
- Simple quality factor parsing (StarPunk philosophy)
- Not full RFC 7231 compliance (minimal approach)
- Reuses existing feed generators
- No breaking changes

Quality Metrics:
- 132/132 tests passing (100%)
- Zero breaking changes
- Full backward compatibility
- Standards compliant negotiation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-27 20:46:49 -07:00
parent 59e9d402c6
commit 8fbdcb6e6f
9 changed files with 1951 additions and 43 deletions

View File

@@ -9,9 +9,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.1.2-dev] - 2025-11-26
### Added - Phase 2: Feed Formats (Partial - RSS Fix, ATOM, JSON Feed)
### Added - Phase 2: Feed Formats (Complete - RSS Fix, ATOM, JSON Feed, Content Negotiation)
**Multi-format feed support with ATOM and JSON Feed**
**Multi-format feed support with ATOM, JSON Feed, and content negotiation**
- **Content Negotiation** - Smart feed format selection via HTTP Accept header
- New `/feed` endpoint with HTTP content negotiation
- Supports Accept header quality factors (e.g., `q=0.9`)
- MIME type mapping:
- `application/rss+xml` → RSS 2.0
- `application/atom+xml` → ATOM 1.0
- `application/feed+json` or `application/json` → JSON Feed 1.1
- `*/*` → RSS 2.0 (default)
- Returns 406 Not Acceptable with helpful error message for unsupported formats
- Simple implementation (StarPunk philosophy) - not full RFC 7231 compliance
- Comprehensive test coverage (63 tests for negotiation + integration)
- **Explicit Format Endpoints** - Direct access to specific feed formats
- `/feed.rss` - Explicit RSS 2.0 feed
- `/feed.atom` - Explicit ATOM 1.0 feed
- `/feed.json` - Explicit JSON Feed 1.1
- `/feed.xml` - Backward compatibility (redirects to `/feed.rss`)
- All endpoints support streaming and caching
- **ATOM 1.0 Feed Support** - RFC 4287 compliant ATOM feeds
- Full ATOM 1.0 specification compliance with proper XML namespacing
@@ -20,7 +39,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- XML escaping using standard library (xml.etree.ElementTree approach)
- Business metrics integration for feed generation tracking
- Comprehensive test coverage (11 tests)
- Endpoint: `/feed.atom` (Phase 2.4 will add content negotiation)
- **JSON Feed 1.1 Support** - Modern JSON-based syndication format
- JSON Feed 1.1 specification compliance
@@ -30,13 +48,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Custom _starpunk extension with permalink_path and word_count
- Business metrics integration
- Comprehensive test coverage (13 tests)
- Endpoint: `/feed.json` (Phase 2.4 will add content negotiation)
- **Feed Module Restructuring** - Organized feed code for multiple formats
- New `starpunk/feeds/` module with format-specific files
- `feeds/rss.py` - RSS 2.0 generation (moved from feed.py)
- `feeds/atom.py` - ATOM 1.0 generation (new)
- `feeds/json_feed.py` - JSON Feed 1.1 generation (new)
- `feeds/negotiation.py` - Content negotiation logic (new)
- Backward compatible `feed.py` shim for existing imports
- All formats support both streaming and non-streaming generation
- Business metrics integrated into all feed generators