Category: URI Design
Description
URI paths should not include file extensions (e.g., .json, .xml, .html). Representation formats should be negotiated through HTTP headers (Accept/Content-Type) rather than being embedded in the URI structure.
What It Checks
This rule validates that URI path segments do not end with file extensions. It checks:
- All path segments in the URI for file extension patterns (e.g.,
.json,.xml,.pdf) - Uses regex pattern matching to detect extensions:
\.(\w+)$ - Applies to all HTTP methods on paths containing file extensions
- Flags violations on any operation defined for a path with a file extension
Why It Matters
Keeping file extensions out of URIs is fundamental to RESTful design:
- Resource Identity: URIs should identify resources, not representations. The same resource can be represented in multiple formats (JSON, XML, HTML) without changing its identity.
- Content Negotiation: HTTP provides built-in mechanisms (Accept/Content-Type headers) specifically designed for format negotiation, making extensions redundant.
- URI Stability: Changing supported formats shouldn't require URI changes. A URI like
/users/123.jsonbecomes problematic if you later want to support XML or other formats. - API Evolution: Adding or removing support for formats doesn't break existing URI structures when using header-based negotiation.
Examples
Good ✅
paths:
/users:
get:
summary: List all users
produces:
- application/json
- application/xml
responses:
'200':
description: Array of users
/users/{userId}:
get:
summary: Get a specific user
produces:
- application/json
- application/xml
responses:
'200':
description: User details
/reports/{reportId}:
get:
summary: Get report
produces:
- application/json
- application/pdf
responses:
'200':
description: Report data
Client request with content negotiation:
GET /users/123 HTTP/1.1
Accept: application/json
GET /users/123 HTTP/1.1
Accept: application/xml
Bad ❌
paths:
/users.json: # File extension in URI
get:
summary: List users in JSON format
responses:
'200':
description: JSON array of users
/users/{userId}.xml: # File extension in URI
get:
summary: Get user in XML format
/reports/{reportId}.pdf: # File extension in URI
get:
summary: Get report as PDF
/api/v1/data.json: # File extension in URI
get:
summary: Get data
Anti-pattern examples:
# Wrong - format in URI
GET /users/123.json HTTP/1.1
# Wrong - limits flexibility
GET /reports/456.pdf HTTP/1.1
# Wrong - violates resource identity principle
GET /api/data.xml HTTP/1.1
Configuration
This rule has no configuration options. It is either enabled or disabled.
How to Fix
-
Remove file extensions from URIs:
# Before /users.json → /users /users/{userId}.xml → /users/{userId} /reports/{id}.pdf → /reports/{id} # After /users /users/{userId} /reports/{id} -
Implement content negotiation using HTTP headers:
paths: /users/{userId}: get: summary: Get user parameters: - name: Accept in: header description: Desired response format schema: type: string enum: - application/json - application/xml produces: - application/json - application/xml responses: '200': description: User data -
Update client code to use Accept headers:
// Before fetch('/users/123.json') // After fetch('/users/123', { headers: { 'Accept': 'application/json' } }) -
Configure server to handle content negotiation:
- Inspect the
Acceptheader to determine response format - Set appropriate
Content-Typeheader in responses - Support multiple formats from the same endpoint
- Return
406 Not Acceptableif requested format is unsupported
- Inspect the
-
Document supported formats in API specification:
responses: '200': description: Successful response content: application/json: schema: $ref: '#/components/schemas/User' application/xml: schema: $ref: '#/components/schemas/User' '406': description: Requested format not supported
Related Rules
- Rule 28: Lowercase Letters - URI formatting and casing standards
- Rule 26: Hyphens vs Underscores - URI naming conventions
- Rule 75: Consistent Naming Conventions - Overall API naming patterns