HTTP-клиент Laravel: Войдите на веб-сайт, затем загрузите файл

#php #laravel #http

Вопрос:

Мне нужно программно загрузить CSV-файл, который доступен только после того, как вы вошли на веб-сайт.

Когда я пытаюсь сделать это в Insomnia / Postman, это отлично работает, но я не могу понять, как это сделать в Laravel. Я подозреваю, что неправильно обрабатываю / использую файл cookie сеанса.

Это то, что я делаю при бессоннице / Почтальон:

  1. Я отправляю запрос на публикацию на страницу входа в систему веб-сайта вместе с именем пользователя и паролем в виде составных данных/данных формы.
  2. Я отправляю запрос на получение URL-адреса CSV-файла и получаю длинную строку CSV (тип содержимого: приложение/vnd.ms-excel)

Это ИМЕННО то, что мне нужно сделать в Laravel, но я просто не могу этого понять…

Это мой код:

 public static function getCSVFeed()
{
    $login = Http::withHeaders([
        "Content-Type" => "multipart/form-data",
    ])->post(config("csvfeed_login_url"), [
        "_username" => config("csvfeed_username"),
        "_password" => config("csvfeed_password"),
    ]);

    $sessionCookie = $login
        ->cookies()
        ->getCookieByName("PHPSESSID")
        ->toArray();

    $sessionCookieName = $sessionCookie["Name"];
    $sessionCookieValue = $sessionCookie["Value"];

    $response = Http::withHeaders([
        "Cookie" => $sessionCookieName . "=" . $sessionCookieValue,
    ])->get(config("csvfeed_url"));

    return $response;
}
 

Когда я выполняю этот код, он возвращает не строку CSV, а HTML-код страницы 404 веб-сайта, что предполагает, что я не вошел в систему.

Редактировать:

Я провел еще несколько поисков и устранений неполадок. Я вошел в систему вручную в своем браузере, скопировал файл cookie «PHPSESSID» и жестко закодировал его в своем запросе GET, и я действительно получил ответ, содержащий CSV!

Это означает, что часть входа в мой код не работает, хотя я делаю то же самое, что и в Insomnia / Postman.

Когда я отправляюсь в Бессонницу и копирую свой запрос как Curl, я получаю следующее:

 curl --request POST 
  --url **login URL** 
  --header 'Content-Type: multipart/form-data; boundary=---011000010111000001101001' 
  --form _username=**username** 
  --form '_password=**password**'
 

Единственное различие, которое я могу заметить,-это часть «граница=— — 011000010111000001101001», но я не знаю, что это такое и как это реализовать в PHP.

Комментарии:

1. Вы отправляете неправильный заголовок, касающийся файлов cookie. Set-Cookie это заголовок ответа , с помощью которого сервер отвечает, чтобы установить файл cookie. Заголовок запроса , который клиент использует для отправки этих файлов cookie обратно, таков Cookie . developer.mozilla.org/en-US/docs/Web/HTTP/…

2. Большое вам спасибо за совет! Я изменил заголовок на Cookie , и теперь он действительно работает, когда я жестко кодирую файл cookie сеанса известного качества, поэтому я могу сделать вывод, что в части входа в мой код находится проблема. Я отредактировал свой вопрос с более подробной информацией.

3. Вероятно multipart/form-data , для начала это не обязательно (на самом деле это для загрузки файлов), вероятно, подойдет «нормальный» application/x-www-form-urlencoded . Попробуйте синтаксис laravel.com/docs/8.x/…

4. @CBroe Вы были правы, сейчас все работает так, как ожидалось. Спасибо!

Ответ №1:

Кредит идет @CBroe

Оказывается, я неправильно вошел в систему. multipart/form-data Заголовок не нужен. Вместо этого я должен был поставить префикс метода post asForm() .

Это рабочий код:

 public static function getCSVFeed(): array
{
    $login = Http::asForm()->post(config("csvfeed.login_url"), [
        "_username" => config("csvfeed.username"),
        "_password" => config("csvfeed.password"),
    ]);

    $sessionCookie = $login
        ->cookies()
        ->getCookieByName("PHPSESSID")
        ->toArray();

    $sessionCookieName = $sessionCookie["Name"];
    $sessionCookieValue = $sessionCookie["Value"];

    $response = Http::withHeaders([
        "Cookie" => $sessionCookieName . "=" . $sessionCookieValue,
    ])->get(config("csvfeed.url"));

    return str_getcsv($response, PHP_EOL);
}