Установить элементы локального хранилища перед загрузкой страницы в кукольнике?

У нас есть некоторая логика маршрутизации, которая отправляет вас на домашнюю страницу, если у вас нет набора JWT_TOKEN ... Я хочу установить это до загрузки страницы / до вызова js.

Как мне это сделать ?

23
0
15 761
5

Ответы 5

Попробуйте и дополнительный тег скрипта. Пример:

Допустим, у вас есть сценарий main.js, в котором хранится ваша логика маршрутизации.

Затем сценарий setJWT.js, в котором хранится ваша логика токена.

Затем в вашем html, который загружает эти сценарии, упорядочьте их следующим образом:

<script src='setJWT.js'></script>
<script src='main.js'></script>

Это будет хорошо только для первоначального запуска страницы.

Однако большинство библиотек маршрутизации обычно имеют систему перехвата событий, к которой можно подключиться до того, как будет отрисован маршрут. Я бы сохранил логику setJWT где-нибудь в этом обратном вызове.

Этот ответ не имеет ничего общего с кукловодом :(

pmdarrow 03.01.2019 06:39

Вы должны зарегистрировать элемент localStorage следующим образом:

await page.evaluate(() => {
  localStorage.setItem('token', 'example-token');
});

Сделать это нужно после страницы page.goto - в браузере должен быть URL-адрес для регистрации на нем элемента локального хранилища. После этого снова войдите на ту же страницу, на этот раз токен должен быть здесь до загрузки страницы.

Вот полностью рабочий пример:

const puppeteer = require('puppeteer');
const http = require('http');

const html = `
<html>
  <body>
    <div id="element"></div>

    <script>
      document.getElementById('element').innerHTML = 
        localStorage.getItem('token') ? 'signed' : 'not signed';
    </script>
  </body>
</html>`;

http
  .createServer((req, res) => {
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.write(html);
    res.end();
  })
  .listen(8080);

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();

  await page.goto('http://localhost:8080/');

  await page.evaluate(() => {
    localStorage.setItem('token', 'example-token');
  });

  await page.goto('http://localhost:8080/');

  const text = await page.evaluate(
    () => document.querySelector('#element').textContent
  );

  console.log(text);
  await browser.close();

  process.exit(0);
})();

Это обсуждается в Проблемы с GitHub Puppeteer.

Вы можете загрузить страницу в домене, установить свой localStorage, а затем перейти к фактической странице, которую вы хотите загрузить, с готовым localStorage. Вы также можете перехватить загрузку первого URL-адреса для мгновенного возврата вместо фактической загрузки страницы, что потенциально сэкономит много времени.

const doSomePuppeteerThings = async () => {
  const url = 'http://example.com/';
  const browser = await puppeteer.launch();
  const localStorage = { storageKey: 'storageValue' };
  setDomainLocalStorage(browser, url, localStorage);

  const page = await browser.newPage();
  // do your actual puppeteer things now
};

const setDomainLocalStorage = async (browser, url, values) => {
  const page = await browser.newPage();
  await page.setRequestInterception(true);
  page.on('request', r => {
    r.respond({
      status: 200,
      contentType: 'text/plain',
      body: 'tweak me.',
    });
  });
  await page.goto(url);
  await page.evaluate(values => {
    for (const key in values) {
      localStorage.setItem(key, values[key]);
    }
  }, values);
  await page.close();
};

Большое спасибо за этот ответ, наверное, лучшее решение, которое я нашел. Меня также легко настроить для файлов cookie, изменив строку evaluate на await page.setCookie(...cookies). Приятно видеть, что этот ответ также исходит от одного из основных разработчиков кукловодов.

Chris Sandvik 05.03.2021 20:20

Не требуя удвоения goTo, это будет работать:

const browser = await puppeteer.launch();
browser.on('targetchanged', async (target) => {
  const targetPage = await target.page();
  const client = await targetPage.target().createCDPSession();
  await client.send('Runtime.evaluate', {
    expression: `localStorage.setItem('hello', 'world')`,
  });
});
// newPage, goTo, etc...

Адаптировано из документа Lighthouse для кукловода, который делает что-то подобное: https://github.com/GoogleChrome/lighthouse/blob/master/docs/puppeteer.md

Не могли бы вы подробнее рассказать, что это делает?

jayarjo 04.05.2020 07:03

@jayarjo Похоже, это добавляет прослушиватель событий targetchanged и запускает оценку при каждом переключении страницы

Pavlo Zhukov 13.06.2020 16:31

в 2021 году он будет работать со следующим кодом:

// store in localstorage the token
   await page.evaluateOnNewDocument (
     token => {
       localStorage.clear();
       localStorage.setItem('token', token);
     }, 'eyJh...9_8cw');
   // open the url
 await page.goto('http://localhost:3000/Admin', { waitUntil: 'load' });

Следующая строка из первого комментария, к сожалению, не работает

await page.evaluate(() => {
  localStorage.setItem('token', 'example-token'); // not work, produce errors :(
});

Спасибо за это решение. Обратите внимание, что для параметра waitUntil по умолчанию установлено значение load, поэтому { waitUntil: 'load' } является избыточным.

Tiago 09.04.2021 23:43

Другие вопросы по теме