Add content negotiation to content app for JSON distribution representation
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 598
- Forks
- 168
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 86
Description
Problem Statement
The pulpcore content app has no content negotiation — the Accept request header is never inspected. When a client requests a distribution's base path or content path, it always gets an HTML directory listing or a binary file stream. There is no standardized way for a client to request a JSON representation of a distribution or its contents.
Some plugins have worked around this with custom URL patterns (e.g., PythonDistribution.content_handler serves JSON at pypi/*/json), but this is ad-hoc and plugin-specific. There is no common mechanism that all distribution types can use.
Proposed Solution
1. Content negotiation in the content app
Handler._match_and_stream() should inspect the Accept request header. When a client sends Accept: application/json, the handler should call a new method on the resolved distribution to produce a JSON response instead of serving files or HTML directory listings.
2. New Distribution extension method
Add a method to the base Distribution model that plugin distributions can override:
class Distribution(MasterModel):
def content_handler_json(self, path):
"""
Return a JSON representation of the distribution's contents at the given path.
Plugin distributions override this to provide content-type-specific data.
Return None to fall through to default behavior.
"""
return None
3. Default behavior
The base Distribution could provide a minimal default JSON response with distribution metadata (name, base_path, repository info). Plugin distributions would enrich this with content-type-specific data. For example:
- Maven: list MavenPackage content (GAV coordinates, POM metadata)
- RPM: list packages by NEVRA
- Python: list Python packages by name/version
- File: list files by relative path
4. Integration with existing content_handler
The content negotiation check should happen in _match_and_stream (handler.py) after resolving the distribution but before calling the existing content_handler. When Accept: application/json is present:
- Call
distribution.content_handler_json(rel_path) - If it returns a response, serve it
- If it returns
None, fall through to existing behavior
This preserves backward compatibility — distributions that don't override the method behave exactly as before.
Use Cases
- CLI tools and automation scripts can query distribution contents programmatically
- Web UIs can fetch structured data about available packages without screen-scraping HTML
- Plugin distributions get a standardized extension point instead of inventing ad-hoc JSON endpoints
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with Handler._match_and_stream in handler.py and the base Distribution model, then trace how the existing content_handler resolves and streams content. Define the JSON negotiation and fallback behavior around content_handler_json, including the extension point for plugin distributions. Done means application/json requests can receive a distribution response while unsupported distributions retain their existing behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- backend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100