Park4Night Proxy Wrapper
Relevant source files
The following files were used as context for generating this wiki page:
The Park4Night Proxy Wrapper is a server-side architectural component designed to interface with the private Park4Night API. It acts as a bridge between the frontend application and the upstream Park4Night services, handling authentication via session cookies, request retries, data normalization, and durable caching.
The wrapper ensures that sensitive session information, such as the PHPSESSID cookie, remains on the server and is never exposed to the client-side browser environment. It also provides a layer of resilience by implementing a file-backed cache to minimize upstream API calls for static location data.
Sources: src/lib/p4n.ts:1-10, README.md:15-20
Architecture and Authentication Flow
The system utilizes a Node.js backend to perform authenticated requests to https://park4night.com. Authentication is managed through a session cookie named PHPSESSID, which is typically obtained via a headless or headed browser login process using Playwright to bypass reCAPTCHA protections.
Authentication Sequence
The following diagram illustrates the process of establishing a session and proxying requests.
Core Components
Request Handling and Normalization
The system implements a robust fetch utility that handles specific Park4Night requirements, such as custom headers and base64-encoded response bodies.
- Base Headers: Includes a fixed User-Agent,
axios-ajax: true, and thePHPSESSIDcookie. - parseMaybeBase64: Park4Night endpoints often return base64-encoded JSON strings; this utility transparently decodes them.
- normalizePlace: Coerces inconsistent API responses (e.g., services as objects vs. strings) into a reliable string array format.
Sources: src/lib/p4n.ts:15-70, src/lib/p4n.ts:98-115
Durable Caching Strategy
To improve performance and reduce upstream load, the wrapper employs a durable, refresh-only cache. This is particularly used for the /places/around endpoint, where results are effectively static.
| Feature | Description |
|---|---|
| Storage | In-memory Map mirrored to a JSON file (p4n-cache.json). |
| Keying | Rounded grid cells (lat/lng to 3 decimals) + radius to collapse overlapping queries. |
| Persistence | Uses debounced writes to the filesystem to survive process restarts. |
| Capacity | Limits storage to 20,000 entries with a 25% cleanup on overflow. |
Sources: src/lib/cache.ts:15-50, src/lib/p4n.ts:285-300
API Proxy Implementation
The wrapper exposes several internal API routes that map to upstream Park4Night functionality.
Bookmark Management
These endpoints allow the application to read and write to the user's Park4Night favorites and folders.
| Endpoint | Method | Upstream URI | Purpose |
|---|---|---|---|
/api/me | GET | /api/user | Fetches account details and folder list. |
/api/bookmarks | POST | /api/user/bookmarks | Adds a place to favorites. |
/api/bookmarks | DELETE | /api/user/bookmarks | Removes a place from favorites. |
/api/folders | POST | /api/user/folder | Creates a new bookmark folder. |
Sources: src/lib/p4n.ts:138-175, src/app/api/bookmarks/route.ts:15-55, src/lib/client.ts:50-80
Security Gate
A middleware "proxy" function provides an optional HTTP Basic Authentication layer. When the APP_GATE_SECRET environment variable is set, all requests (except static assets) are blocked unless the correct credentials are provided in the Authorization header.
export function proxy(req: NextRequest) {
const secret = process.env.APP_GATE_SECRET?.trim();
if (!secret) return NextResponse.next();
const user = process.env.APP_GATE_USER?.trim() || "me";
const header = req.headers.get("authorization");
if (header?.startsWith("Basic ")) {
const decoded = Buffer.from(header.slice(6), "base64").toString("utf-8");
// ... validation logic
}
}
Sources: src/proxy.ts:10-25
Conclusion
The Park4Night Proxy Wrapper provides a secure and efficient abstraction layer over the Park4Night private API. By centralizing session management, implementing durable caching, and providing data normalization, it enables the complex planning features of the application while maintaining a clean separation between the client and the upstream service provider.