cookie(self::NAME); $issued = ! is_string($token) || strlen($token) < 32 || strlen($token) > 256; if (! is_string($token) || strlen($token) < 32 || strlen($token) > 256) { $provided = $request->header('X-Simulation-Token'); $token = is_string($provided) && strlen($provided) >= 32 && strlen($provided) <= 256 ? $provided : Str::random(96); } $request->headers->set('X-Simulation-Token', $token); $response = $next($request); $forget = $request->isMethod('DELETE') && $request->path() === 'api/v1/simulation-drafts/current' && $response->getStatusCode() === 204; $activity = $response->isSuccessful() && $this->isExplicitDraftActivity($request, $response); $replay = $response->isSuccessful() && $this->isDraftActivityReplay($request, $response); if (! $issued && ! $activity && ! $replay && ! $forget) { return $response; } // Successful draft writes reset the server deadline to now + DAYS, so // refresh the cookie by the same duration. Routine reads never refresh it. $minutes = $forget ? 0 : self::DAYS * 24 * 60; if ($replay) { $payload = json_decode((string) $response->getContent(), true); $expiry = is_array($payload) ? ($payload['expires_at'] ?? null) : null; if (is_string($expiry)) { try { $secondsLeft = Carbon::parse($expiry)->getTimestamp() - now()->getTimestamp(); $minutes = max(1, (int) ceil($secondsLeft / 60)); } catch (\Throwable) { // Preserve the standard cookie lifetime if the response has no valid deadline. } } } $response->headers->setCookie(cookie( self::NAME, $forget ? '' : $token, $minutes, '/api/v1', null, $request->isSecure(), true, false, 'lax', )); return $response; } private function isExplicitDraftActivity(Request $request, Response $response): bool { if ($request->isMethod('POST') && $request->path() === 'api/v1/simulation-drafts') { return $response->getStatusCode() === 201; } return ($request->isMethod('PUT') && preg_match('#^api/v1/simulation-drafts/[0-9a-f-]{36}$#i', $request->path()) === 1) || ($request->isMethod('POST') && preg_match('#^api/v1/simulation-drafts/[0-9a-f-]{36}/(?:conversions|touch)$#i', $request->path()) === 1); } private function isDraftActivityReplay(Request $request, Response $response): bool { if (! $request->isMethod('POST') || $response->getStatusCode() !== 200) { return false; } if ($request->path() !== 'api/v1/simulation-drafts' && preg_match('#^api/v1/simulation-drafts/[0-9a-f-]{36}/conversions$#i', $request->path()) !== 1) { return false; } $payload = json_decode((string) $response->getContent(), true); return is_array($payload) && ($payload['data']['replayed'] ?? $payload['replayed'] ?? false) === true; } }