Przejdź do głównej zawartości

NextPDF — rozwiązywanie problemów z Gotenberg

Mostek zgłasza błędy jawnie i wcześnie. Każda awaria kończy się typowanym wyjątkiem z komunikatem wskazującym przyczynę. Traktuj tę stronę jako katalog takich przypadków. Przy każdej awarii znajdziesz typ wyjątku, fragment komunikatu, który zobaczysz, dokładny moment wyzwolenia w ścieżce kodu oraz sposób naprawy.

Rodziny wyjątków to:

  • GotenbergConvertException — błąd warstwy konwersji (konfiguracja, transport lub odpowiedź).
  • RuntimeException — błąd warstwy walidacji zgłoszony przez politykę bezpieczeństwa przed jakimkolwiek ruchem sieciowym.
  • ValueError — nierozpoznane rozszerzenie pliku.
  • InvalidSpkiPinException — niepoprawny ciąg pinu SubjectPublicKeyInfo (SPKI) protokołu Transport Layer Security (TLS).

„Invalid Gotenberg configuration: apiUrl is empty”

Dział zatytułowany „„Invalid Gotenberg configuration: apiUrl is empty””
  • Typ: GotenbergConvertException
  • Wyzwalacz: Wywołano convertFile() lub convertString(), gdy GotenbergConfig::isValid() ma wartość false. Dzieje się tak, gdy apiUrl jest pustym ciągiem.
  • Naprawa: Podaj niepusty adres URL ze schematem HTTPS. Jeśli budujesz konfigurację za pomocą fromArray(), pamiętaj, że po cichu podstawia ona '' za brakującą albo niebędącą ciągiem wartość api_url. Waliduj źródło konfiguracji podczas uruchamiania.

Te awarie pochodzą z polityki bezpieczeństwa, która chroni przed atakiem typu server-side request forgery (SSRF). Mostek zgłasza je przed wysłaniem jakiegokolwiek żądania. Każda z nich jest zwykłym RuntimeException.

  • Wyzwalacz: Schemat skonfigurowanego adresu URL nie jest https. Sprawdzenie nie rozróżnia wielkości liter, więc HTTPS:// jest akceptowane.
  • Naprawa: Umieść Gotenberg za TLS i skonfiguruj punkt końcowy HTTPS. Zwykły protokół HTTP jest odrzucany nawet w środowisku programistycznym.
  • Wyzwalacz: Adresu URL nie da się sparsować na schemat i host.
  • Naprawa: Podaj poprawny składniowo bezwzględny adres URL, na przykład https://gotenberg.example.com:3000.

„Gotenberg API URL must not resolve to a private or reserved IP address”

Dział zatytułowany „„Gotenberg API URL must not resolve to a private or reserved IP address””
  • Wyzwalacz: Host jest prywatnym lub zarezerwowanym literałem adresu Internet Protocol (IP) lub nazwą hosta, która rozwiązuje się (z uwzględnieniem wszystkich rekordów A/AAAA) na dowolny adres prywatny lub zarezerwowany. Blokuje to zakresy prywatne z Request for Comments (RFC) 1918, adresy pętli zwrotnej oraz adresy link-local.
  • Naprawa: Skieruj mostek na rutowalny adres publiczny lub odpowiednio wydzielony adres usługi. Jeśli Gotenberg celowo działa w sieci prywatnej, zabezpieczenie SSRF mostka odrzuca go z założenia. Udostępnij go pod adresem akceptowanym przez to zabezpieczenie, a następnie chroń tę ścieżkę za pomocą mechanizmów kontroli sieci i uwierzytelniania. Zobacz /integrations/gotenberg/security-and-operations/.

„Gotenberg API URL DNS answer changed since validation — possible DNS rebinding attack”

Dział zatytułowany „„Gotenberg API URL DNS answer changed since validation — possible DNS rebinding attack””
  • Wyzwalacz: Między początkową walidacją a żądaniem ponowne rozwiązanie Domain Name System (DNS) zwróciło adres, którego nie było w pierwotnie zwalidowanym zbiorze.
  • Naprawa: Zadziałało zabezpieczenie time-of-check/time-of-use. Zbadaj DNS dla tego hosta. Nieszkodliwą przyczyną może być moduł równoważenia obciążenia rotujący adresy. Złośliwą przyczyną jest atak typu rebinding. Użyj stabilnego adresu lub nazwy ze stabilnym zestawem rekordów dla punktu końcowego Gotenberg.

Polityka bezpieczeństwa zgłasza te awarie przed wysłaniem żądania. Każda z nich jest zwykłym RuntimeException, o ile nie zaznaczono inaczej.

„File not found or not readable: ” — plik nie został znaleziony lub nie można go odczytać

Dział zatytułowany „„File not found or not readable: ” — plik nie został znaleziony lub nie można go odczytać”
  • Typ: GotenbergConvertException
  • Wyzwalacz: convertFile() nie mógł uzyskać kanonicznej postaci ścieżki albo rozwiązana ścieżka nie jest zwykłym plikiem możliwym do odczytu. Taki sam błąd wywoła również katalog.
  • Naprawa: Przekaż ścieżkę do istniejącego, możliwego do odczytu pliku. Ścieżka jest najpierw kanonizowana za pomocą realpath(), co także blokuje przechodzenie po katalogach.

„File size ( bytes) exceeds maximum allowed size ( bytes)”

Dział zatytułowany „„File size ( bytes) exceeds maximum allowed size ( bytes)””
  • Wyzwalacz: Dane wejściowe są większe niż maxFileSize (domyślnie 52 428 800 bajtów = 50 MiB).
  • Naprawa: Zwiększ maxFileSize, jeśli dokument rzeczywiście tego wymaga, albo odrzuć przesyłanie wcześniej w potoku. Utrzymuj limit tak niski, jak pozwalają na to rzeczywiste dokumenty. Jest to jedyne wbudowane ograniczenie zasobów mostka.

Mostek sprawdza poprawność nazwy pliku. W przypadku konwersji plików nazwą pliku jest bazowa nazwa rozwiązanej ścieżki; w przypadku convertString() jest to nazwa, którą przekazujesz. Każdy z tych przypadków to RuntimeException:

Fragment komunikatuWyzwalacz
must not be emptypusta nazwa pliku
path traversal sequences (..)nazwa zawiera ..
forward slashesnazwa zawiera /
backslashesnazwa zawiera \
null bytesnazwa zawiera bajt NUL
control charactersnazwa zawiera znak sterujący ASCII (0–31)
  • Naprawa: Przekaż czystą nazwę bazową. W przypadku convertString() podaj zwykłą nazwę, taką jak report.docx. Służy ona do wykrywania formatu oraz jako nazwa pliku w przesyłaniu wieloczęściowym, a nie jako ścieżka.
  • Typ: ValueError
  • Wyzwalacz: Rozszerzenie pliku nie jest jednym z: docx, xlsx, pptx, odt, ods, odp (bez rozróżniania wielkości liter; początkowa kropka jest tolerowana).
  • Naprawa: Konwertuj tylko sześć rozpoznawanych formatów. Mostek nie rozpoznaje starszych formatów binarnych (.doc, .xls, .ppt), .rtf, .csv, zwykłego tekstu ani obrazów. Takie dane wejściowe przekonwertuj na rozpoznawany format przed wywołaniem mostka albo skieruj je inną ścieżką.

Wszystkie poniższe awarie to GotenbergConvertException.

  • Wyzwalacz: Klient PHP Standard Recommendation 18 (PSR-18) (lub transport z przypiętym certyfikatem cURL) zgłosił wyjątek podczas wysyłania żądania. Przyczyną może być odrzucenie połączenia, przekroczenie limitu czasu, niepowodzenie uzgadniania TLS lub niezgodność pinu.
  • Kod wyjątku: kod bazowego wyjątku klienta.
  • Przyczyna: oryginalny wyjątek klienta PSR-18 jest dołączony jako poprzedni wyjątek.
  • Naprawa: Sprawdź cztery rzeczy: osiągalność usługi za pomocą isAvailable(), ścieżkę sieciową, łańcuch certyfikatów TLS oraz, jeśli skonfigurowano przypinanie, zgodność bieżącego SubjectPublicKeyInfo (SPKI) serwera ze skonfigurowanym pinem. Typową przyczyną jest niezgodność pinu po rotacji certyfikatu. Zobacz procedurę rotacji w /integrations/gotenberg/security-and-operations/.
  • Wyzwalacz: curl_exec transportu z przypiętym certyfikatem cURL zakończył się niezerowym numerem błędu cURL albo zwrócił treść, która nie jest ciągiem.
  • Naprawa: Numer błędu cURL wskazuje przyczynę (TLS, rozwiązywanie nazw, przekroczenie limitu czasu, pin). Niepowodzenie przypinania ujawnia się tutaj, gdy CURLOPT_PINNEDPUBLICKEY odrzuca certyfikat. Potwierdź, że skonfigurowane piny oraz rozwiązany adres są aktualne.
  • Wyzwalacz: Status odpowiedzi był inny niż 200. Treść jest dołączona, obcięta do pierwszych 500 znaków, z dodanym wielokropkiem, jeśli jest dłuższa.
  • Naprawa: Przeczytaj dołączoną treść. Komunikat błędu Gotenberg wyjaśnia, dlaczego konwersja została odrzucona: nieobsługiwana zawartość dokumentu, wewnętrzna awaria LibreOffice lub odrzucenie uwierzytelniania przy 401 albo 403. 401/403 oznacza, że brakuje apiKey albo jest on błędny. 5xx to awaria po stronie usługi i może kwalifikować się do ograniczonej liczby ponowień.

„Unexpected Content-Type from Gotenberg: (expected application/pdf)”

Dział zatytułowany „„Unexpected Content-Type from Gotenberg: (expected application/pdf)””
  • Wyzwalacz: Status był równy 200, ale Content-Type odpowiedzi nie zawierał application/pdf.
  • Naprawa: Zwykle oznacza to, że serwer proxy lub brama zwróciły stronę błędu HTML albo stronę przekierowania ze statusem 200. Mostek celowo wyłącza podążanie za przekierowaniami w transporcie z przypiętym certyfikatem, więc odpowiedź 3xx nie jest po cichu śledzona do niezweryfikowanego hosta. Treść przychodząca z błędnym Content-Type sygnalizuje, że coś między aplikacją a Gotenberg ingeruje w ruch. Sprawdź ścieżkę sieciową.

„Response body does not start with %PDF header — invalid PDF data” — treść odpowiedzi nie zaczyna się od sygnatury %PDF

Dział zatytułowany „„Response body does not start with %PDF header — invalid PDF data” — treść odpowiedzi nie zaczyna się od sygnatury %PDF”
  • Wyzwalacz: Status 200, Content-Type akceptowalny, ale treść nie zaczyna się od sygnatury %PDF.
  • Naprawa: Usługa nadrzędna zwróciła coś, co mimo nagłówków nie jest plikiem Portable Document Format (PDF). Potraktuj odpowiedź jako niezaufaną i zbadaj usługę. Nie zapisuj treści na dysku. Mostek odmawia zwrócenia jej jako wyniku.
  • Typ: InvalidSpkiPinException
  • Wyzwalacz: Skonfigurowany ciąg pinu nie zaczyna się od sha256/ ani sha256//.
  • Naprawa: Sformatuj każdy pin jako sha256/<base64-encoded-spki-hash>. Transport akceptuje także postać natywną dla cURL: sha256//<base64>. Wygeneruj wartość z pola SubjectPublicKeyInfo certyfikatu serwera, a nie z całego certyfikatu.

„It says unavailable but the service is up” — usługa działa, ale jest zgłaszana jako niedostępna

Dział zatytułowany „„It says unavailable but the service is up” — usługa działa, ale jest zgłaszana jako niedostępna”

isAvailable() zwraca false bez wykonywania wywołania sieciowego, gdy adres URL jest pusty, nie jest HTTPS albo rozwiązuje się na adres private/reserved. Zwraca także false przy każdym błędzie sieciowym lub gdy /health zwraca 500 lub więcej; w takich przypadkach przechwytuje błąd, zamiast go zgłaszać. Sprawdź kolejno:

  1. Skonfigurowany adres URL nie jest pusty i używa HTTPS.
  2. Host nie rozwiązuje się na adres private/reserved (zabezpieczenie SSRF odrzuca go nawet dla sondy).
  3. <apiUrl>/health jest osiągalny z hosta aplikacji i zwraca status poniżej 500.
  • /integrations/gotenberg/configuration/ — wszystkie opcje i reguły wyboru transportu.
  • /integrations/gotenberg/production-usage/ — polityka ponowień i kontrakt obsługi awarii.
  • /integrations/gotenberg/security-and-operations/ — model SSRF i rotacja pinów.
  • /integrations/gotenberg/quickstart/ — pełna kolejność przechwytywania wyjątków w kontekście.