mirror of
https://github.com/jlengrand/is-it-christmas.git
synced 2026-03-10 08:21:24 +00:00
371 lines
9.0 KiB
Markdown
371 lines
9.0 KiB
Markdown
# API Contract: Christmas Checker
|
|
|
|
**Date**: 2025-11-11
|
|
**Feature**: Christmas Checker Website
|
|
**Branch**: 001-christmas-checker
|
|
**Version**: 1.0
|
|
|
|
## Overview
|
|
|
|
This document defines the REST API contract for the Christmas Checker backend service. The API provides a single endpoint to check if today is Christmas Day.
|
|
|
|
**Base URL**: `http://localhost:8080` (development), configurable for production
|
|
|
|
**Protocol**: HTTP/1.1
|
|
|
|
**Authentication**: None (public API)
|
|
|
|
**Content-Type**: `application/json`
|
|
|
|
## Endpoints
|
|
|
|
### GET /api/christmas
|
|
|
|
Check if today is Christmas (December 25th or 26th).
|
|
|
|
**Description**: Returns a boolean indicating whether the current date is Christmas (December 25th or 26th), along with the date that was checked.
|
|
|
|
#### Request
|
|
|
|
**Method**: `GET`
|
|
|
|
**URL**: `/api/christmas`
|
|
|
|
**Headers**:
|
|
- None required
|
|
|
|
**Query Parameters**: None
|
|
|
|
**Request Body**: None
|
|
|
|
**Example Request**:
|
|
```http
|
|
GET /api/christmas HTTP/1.1
|
|
Host: localhost:8080
|
|
```
|
|
|
|
#### Response
|
|
|
|
**Success Response**:
|
|
|
|
**Status Code**: `200 OK`
|
|
|
|
**Headers**:
|
|
- `Content-Type: application/json`
|
|
- `Access-Control-Allow-Origin: *` (CORS support)
|
|
|
|
**Response Body Schema**:
|
|
```json
|
|
{
|
|
"isChristmas": boolean,
|
|
"date": "YYYY-MM-DD"
|
|
}
|
|
```
|
|
|
|
**Fields**:
|
|
- `isChristmas` (boolean, required): `true` if today is December 25th or 26th, `false` otherwise
|
|
- `date` (string, required): The current date in ISO 8601 format (YYYY-MM-DD)
|
|
|
|
**Example Response (Not Christmas)**:
|
|
```http
|
|
HTTP/1.1 200 OK
|
|
Content-Type: application/json
|
|
Access-Control-Allow-Origin: *
|
|
|
|
```
|
|
|
|
**Example Response (Christmas - Dec 25)**:
|
|
```http
|
|
HTTP/1.1 200 OK
|
|
Content-Type: application/json
|
|
Access-Control-Allow-Origin: *
|
|
|
|
```
|
|
|
|
**Example Response (Christmas - Dec 26)**:
|
|
```http
|
|
HTTP/1.1 200 OK
|
|
Content-Type: application/json
|
|
Access-Control-Allow-Origin: *
|
|
|
|
```
|
|
|
|
#### Error Responses
|
|
|
|
**500 Internal Server Error**:
|
|
|
|
Returned when the server cannot determine the current date or encounters an unexpected error.
|
|
|
|
**Status Code**: `500 Internal Server Error`
|
|
|
|
**Response Body**:
|
|
```json
|
|
{
|
|
"error": "Unable to determine current date",
|
|
"message": "string describing the error"
|
|
}
|
|
```
|
|
|
|
**Example**:
|
|
```http
|
|
HTTP/1.1 500 Internal Server Error
|
|
Content-Type: application/json
|
|
|
|
```
|
|
|
|
**405 Method Not Allowed**:
|
|
|
|
Returned when using any HTTP method other than GET.
|
|
|
|
**Status Code**: `405 Method Not Allowed`
|
|
|
|
**Allowed Methods**: GET
|
|
|
|
**Example**:
|
|
```http
|
|
HTTP/1.1 405 Method Not Allowed
|
|
Allow: GET
|
|
```
|
|
|
|
## CORS Policy
|
|
|
|
**Access-Control-Allow-Origin**: `*` (all origins allowed)
|
|
|
|
**Rationale**: This is a public API with no sensitive data. Allowing all origins enables the frontend to be hosted on any domain.
|
|
|
|
**Preflight Requests** (OPTIONS):
|
|
|
|
For CORS preflight requests, the server responds with:
|
|
|
|
```http
|
|
HTTP/1.1 204 No Content
|
|
Access-Control-Allow-Origin: *
|
|
Access-Control-Allow-Methods: GET, OPTIONS
|
|
Access-Control-Allow-Headers: Content-Type
|
|
```
|
|
|
|
## Response Timing
|
|
|
|
**Expected Response Time**: < 100ms (typically < 10ms)
|
|
|
|
**Rationale**: Simple date comparison with no I/O operations or external dependencies.
|
|
|
|
## Caching
|
|
|
|
**Cache-Control**: `no-cache, no-store, must-revalidate`
|
|
|
|
**Rationale**: The response changes daily at midnight, so aggressive caching would serve stale data. Clients should re-check the date on each page load.
|
|
|
|
**Alternative Strategy**: Could cache for up to 1 hour with:
|
|
```
|
|
Cache-Control: max-age=3600
|
|
```
|
|
|
|
But `no-cache` is safer to ensure users always see current date.
|
|
|
|
## Rate Limiting
|
|
|
|
**Rate Limit**: None
|
|
|
|
**Rationale**: The endpoint is stateless and computationally trivial. No rate limiting needed for this simple use case.
|
|
|
|
## API Versioning
|
|
|
|
**Version**: 1.0 (embedded in this document)
|
|
|
|
**Versioning Strategy**: For future changes:
|
|
- **Non-breaking changes** (e.g., adding optional fields): No version change needed
|
|
- **Breaking changes** (e.g., changing response schema): Introduce `/v2/api/christmas` endpoint
|
|
|
|
**Current Commitment**: No breaking changes planned. Schema is stable.
|
|
|
|
## Client Usage Examples
|
|
|
|
### JavaScript (Fetch API)
|
|
|
|
```javascript
|
|
// Check if it's Christmas
|
|
async function checkChristmas() {
|
|
try {
|
|
const response = await fetch('http://localhost:8080/api/christmas');
|
|
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP error! status: ${response.status}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
if (data.isChristmas) {
|
|
console.log("🎄 It's Christmas!");
|
|
// Show snow animation
|
|
} else {
|
|
console.log("☹️ Not Christmas yet...");
|
|
// Show sad smiley
|
|
}
|
|
|
|
console.log(`Checked date: ${data.date}`);
|
|
} catch (error) {
|
|
console.error('Failed to check Christmas status:', error);
|
|
// Fall back to client-side date check
|
|
}
|
|
}
|
|
|
|
checkChristmas();
|
|
```
|
|
|
|
### cURL
|
|
|
|
```bash
|
|
# Check Christmas status
|
|
curl -X GET http://localhost:8080/api/christmas
|
|
|
|
# Pretty-print JSON response
|
|
curl -X GET http://localhost:8080/api/christmas | jq
|
|
```
|
|
|
|
### Java (HttpClient)
|
|
|
|
```java
|
|
HttpClient client = HttpClient.newHttpClient();
|
|
HttpRequest request = HttpRequest.newBuilder()
|
|
.uri(URI.create("http://localhost:8080/api/christmas"))
|
|
.GET()
|
|
.build();
|
|
|
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
|
|
|
|
if (response.statusCode() == 200) {
|
|
// Parse JSON response
|
|
String json = response.body();
|
|
// Use JSON library or manual parsing
|
|
}
|
|
```
|
|
|
|
## Testing Contract
|
|
|
|
### Contract Tests
|
|
|
|
The following tests should verify contract compliance:
|
|
|
|
1. **Response Status**: GET /api/christmas returns 200 OK
|
|
2. **Response Content-Type**: Header is `application/json`
|
|
3. **Response Schema**: Body contains `isChristmas` (boolean) and `date` (string)
|
|
4. **Date Format**: `date` field matches ISO 8601 format (YYYY-MM-DD)
|
|
5. **Christmas Logic**: On December 25th or 26th, `isChristmas` is `true`
|
|
6. **Non-Christmas Logic**: On any other date, `isChristmas` is `false`
|
|
7. **CORS Headers**: Response includes `Access-Control-Allow-Origin: *`
|
|
8. **Method Not Allowed**: POST/PUT/DELETE return 405 or appropriate error
|
|
|
|
### Sample Contract Test (Pseudocode)
|
|
|
|
```
|
|
Test: ChristmasEndpointContract
|
|
Given: Server is running
|
|
When: GET /api/christmas
|
|
Then:
|
|
- Status code is 200
|
|
- Content-Type is application/json
|
|
- Response body has field "isChristmas" (boolean)
|
|
- Response body has field "date" (string matching YYYY-MM-DD)
|
|
- CORS header Access-Control-Allow-Origin is "*"
|
|
|
|
Test: ChristmasLogicOnChristmasDay
|
|
Given: Server system date is December 25th or 26th
|
|
When: GET /api/christmas
|
|
Then:
|
|
- Response isChristmas is true
|
|
- Response date ends with "-12-25" or "-12-26"
|
|
|
|
Test: ChristmasLogicOnNonChristmasDay
|
|
Given: Server system date is NOT December 25th or 26th
|
|
When: GET /api/christmas
|
|
Then:
|
|
- Response isChristmas is false
|
|
- Response date does NOT end with "-12-25" or "-12-26"
|
|
```
|
|
|
|
## OpenAPI Specification (Swagger)
|
|
|
|
```yaml
|
|
openapi: 3.0.3
|
|
info:
|
|
title: Christmas Checker API
|
|
description: Check if today is Christmas Day
|
|
version: 1.0.0
|
|
servers:
|
|
- url: http://localhost:8080
|
|
description: Development server
|
|
paths:
|
|
/api/christmas:
|
|
get:
|
|
summary: Check if today is Christmas
|
|
description: Returns whether the current date is December 25th or 26th
|
|
operationId: checkChristmas
|
|
responses:
|
|
'200':
|
|
description: Successful response
|
|
headers:
|
|
Access-Control-Allow-Origin:
|
|
schema:
|
|
type: string
|
|
example: "*"
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required:
|
|
- isChristmas
|
|
- date
|
|
properties:
|
|
isChristmas:
|
|
type: boolean
|
|
description: True if today is December 25th or 26th
|
|
example: false
|
|
date:
|
|
type: string
|
|
format: date
|
|
description: Current date in ISO 8601 format
|
|
example: "2025-11-11"
|
|
'500':
|
|
description: Internal server error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
error:
|
|
type: string
|
|
example: "Unable to determine current date"
|
|
message:
|
|
type: string
|
|
example: "System clock unavailable"
|
|
```
|
|
|
|
## Change Log
|
|
|
|
| Version | Date | Changes |
|
|
|---------|------|---------|
|
|
| 1.0 | 2025-11-11 | Initial API contract definition |
|
|
|
|
## Notes
|
|
|
|
- **Client-Side Alternative**: Frontend can check the date client-side using JavaScript `Date()` object, making this API endpoint optional for core functionality
|
|
- **Timezone Handling**: Server uses its local timezone. For production, consider UTC or accepting timezone parameter
|
|
- **Future Enhancements**: Could add query parameter `?tz=America/New_York` to check Christmas in specific timezone
|