getBody()->write($body); return $response->withHeader('Content-Type', 'application/json; charset=utf-8') ->withHeader('Cache-Control', 'no-store') ->withStatus($status); } public static function error(Response $response, string $message, int $status): Response { return self::write($response, ['error' => $message], $status); } /** Schreibt einen bereits von n8n gelieferten JSON-Rumpf unveraendert durch. */ public static function passthrough(Response $response, string $body, int $status = 200): Response { $response->getBody()->write($body === '' ? '{}' : $body); return $response->withHeader('Content-Type', 'application/json; charset=utf-8') ->withHeader('Cache-Control', 'no-store') ->withStatus($status); } /** Dekodiert einen n8n-Rumpf defensiv: kaputtes JSON wird zu einem leeren Array. */ public static function decode(string $body): array { $decoded = json_decode($body, true); return is_array($decoded) ? $decoded : []; } /** * n8n liefert Listen mal als {"tickets":[...]}, mal als nacktes Array. * Diese Helferin nimmt beide Formen an. */ public static function listFrom(array $decoded, string $key): array { if (isset($decoded[$key]) && is_array($decoded[$key])) { return array_values($decoded[$key]); } return array_is_list($decoded) ? $decoded : []; } }