Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Middle: питання на співбесіді з теми «HTTP-клієнт»

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

2 питання

$response = Http::connectTimeout(3)
    ->timeout(10)
    ->retry([200, 500, 1000], when: fn (Throwable $e) => $e instanceof ConnectionException
        || ($e instanceof RequestException && $e->response->serverError()))
    ->get($url);

Таймаути:

  • connectTimeout() - скільки чекати з'єднання (за замовчуванням 10 с);
  • timeout() - скільки чекати відповідь (за замовчуванням 30 с).

30 секунд у веб-запиті - це заблокований воркер PHP. Коли сторонній сервіс зависає, такі запити швидко займають усі воркери, і падає весь сайт. Тому таймаут ставлять під реальну очікувану швидкість сервісу.

Повтори:

  • retry(3, 100) - три спроби з паузою 100 мс; масив задає паузи окремо (наростання);
  • третій аргумент when - що повторювати: збої з'єднання й 5xx так, 4xx - ні (помилка в запиті не виправиться повтором);
  • після вичерпаних спроб - RequestException, або остання відповідь з throw: false.

Обережно з не ідемпотентними запитами: повтор POST /payments після таймауту може створити другий платіж - перший міг пройти. Для таких - ключ ідемпотентності, якщо API його підтримує, або без автоматичних повторів.

У черзі повторами зручніше керувати рівнем завдання (tries, backoff, release() на 429), ніж всередині HTTP-клієнта.

Докладніше в документації: Повторні спроби

Через Http::fake() - запити не йдуть у мережу, а отримують задані відповіді.

it('imports exchange rates', function () {
    Http::preventStrayRequests();
    Http::fake([
        'api.rates.example/*' => Http::response(['usd' => 41.2, 'eur' => 44.9]),
    ]);

    app(RatesImporter::class)->import();

    expect(Rate::where('code', 'usd')->value('value'))->toBe(41.2);
    Http::assertSent(fn (Request $r) => $r->hasHeader('Authorization'));
});

Що підміняють:

  • конкретні адреси шаблонами з *;
  • послідовності: Http::sequence()->push(...)->pushStatus(500) - перша відповідь успішна, друга з помилкою;
  • збій з'єднання: Http::failedConnection();
  • логіку: замикання, що повертає відповідь залежно від запиту.

Перевірки запитів: assertSent, assertNotSent, assertSentCount, assertNothingSent.

preventStrayRequests() - будь-який непідмінений запит кидає виняток. Його ставлять у базовому TestCase чи Pest.php: тест, що випадково ходить у справжній API, стає повільним, нестабільним і може щось змінити в чужій системі.

Що обов'язково покрити: не лише успіх, а й 500, таймаут, 429, неочікуваний формат відповіді - саме ці гілки ламаються в продакшені.

Докладніше в документації: Підміна відповідей