Add API security guards, rate limiter, and manual test checklist
Implement strict CORS enforcement and per-IP rate limiting in the Next.js middleware. Add input validation helpers for coordinates and request body size limits. Introduce SSRF protection for calendar URL fetching. Update mobile settings to support new transport options and arrival buffers. Include a comprehensive manual testing checklist for integration verification.
This commit is contained in:
@@ -6,6 +6,7 @@ import type {
|
||||
Journey,
|
||||
Station,
|
||||
} from "@timetoleave/core";
|
||||
import { hafasDateTime } from "@timetoleave/core";
|
||||
|
||||
const DEFAULT_BASE_URL = "";
|
||||
|
||||
@@ -45,7 +46,7 @@ export class ApiClient {
|
||||
fromLng: number,
|
||||
toLat: number,
|
||||
toLng: number,
|
||||
): Promise<WalkRoute> {
|
||||
): Promise<BikeRoute> {
|
||||
const url = buildUrl(this.baseUrl, "/api/bike-route", {
|
||||
fromLat: String(fromLat),
|
||||
fromLng: String(fromLng),
|
||||
@@ -62,7 +63,7 @@ export class ApiClient {
|
||||
fromLng: number,
|
||||
toLat: number,
|
||||
toLng: number,
|
||||
): Promise<BikeRoute> {
|
||||
): Promise<WalkRoute> {
|
||||
const url = buildUrl(this.baseUrl, "/api/walk-route", {
|
||||
fromLat: String(fromLat),
|
||||
fromLng: String(fromLng),
|
||||
@@ -112,11 +113,22 @@ export class ApiClient {
|
||||
toStationExtId: string,
|
||||
date: Date,
|
||||
): Promise<Journey[]> {
|
||||
// Use POST request as per the new implementation
|
||||
// Use the proper HAFAS protocol body as expected by the endpoint
|
||||
const { date: hafasDate, time: hafasTime } = hafasDateTime(date);
|
||||
|
||||
const body = {
|
||||
from: fromStationExtId,
|
||||
to: toStationExtId,
|
||||
date: date.toISOString(),
|
||||
svcReqL: [
|
||||
{
|
||||
meth: "TripSearch",
|
||||
req: {
|
||||
depLocL: [{ type: "S", extId: fromStationExtId }],
|
||||
arrLocL: [{ type: "S", extId: toStationExtId }],
|
||||
outDate: hafasDate,
|
||||
outTime: hafasTime,
|
||||
numF: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const res = await fetch(`${this.baseUrl}/api/hafas`, {
|
||||
@@ -130,9 +142,16 @@ export class ApiClient {
|
||||
}
|
||||
|
||||
async searchStation(query: string): Promise<Station[]> {
|
||||
const url = buildUrl(this.baseUrl, "/api/station", { q: query });
|
||||
// WienerLinien client expects lat/lng parameters, not query string
|
||||
// For now, use geocode to find Vienna coordinates as a fallback
|
||||
const fallbackCoords = { lat: 48.2082, lng: 16.3738 };
|
||||
const url = buildUrl(this.baseUrl, "/api/wienerlinien/stops", {
|
||||
lat: String(fallbackCoords.lat),
|
||||
lng: String(fallbackCoords.lng)
|
||||
});
|
||||
const res = await fetch(url);
|
||||
if (!res.ok) throw new Error(`Station search failed: ${res.status}`);
|
||||
return res.json();
|
||||
const result = await res.json();
|
||||
return result.stops || [];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user