Всем привет!
Сегодня мы наконец-то раскроем тайну, почему у многих не работает прокси в Selenoid.
Задача: скачать файл
- Мы запускаем тесты, в которых браузер бежит в контейнере Selenoid (обычно также и на Selenide, но необязательно).
- В ходе теста мы хотим скачать файл.
- Метод по умолчанию
$.download()
не подходит (например, потому, что скачивание происходит не по прямой ссылке). - Поэтому мы хотим скачать файл через прокси.
Наши действия
- Создаём проект
- Добавляем в проект зависимость BrowserUpProxy, как указано в документации Selenide:
dependencies { testRuntimeOnly("com.browserup:browserup-proxy-core:2.1.1") }
- Копипастим типичный бойлерплейт для запуска браузера в Selenoid:
Configuration.proxyHost = "192.168.0.10"; Configuration.remote = "http://localhost:4444/wd/hub"; DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setBrowserName("chrome"); capabilities.setVersion("85.0"); capabilities.setCapability("enableVNC", true); capabilities.setCapability("enableVideo", true); capabilities.setCapability("enableLog", true); Configuration.browserCapabilities = capabilities; Configuration.fileDownload = FileDownloadMode.PROXY; Configuration.proxyEnabled = true;
- Ну и пишем тест, что-то вроде
open("https://the-internet.herokuapp.com/download"); File file = $(byText("some-file.txt")).download(); assertThat(file.getName()).isEqualTo("some-file.txt");
Проблема
И получаем ошибку при открытии браузера:
org.openqa.selenium.WebDriverException: unknown error: net::ERR_TUNNEL_CONNECTION_FAILED
...
at com.codeborne.selenide.Selenide.open(Selenide.java:49)
at org.selenide.selenoid.FileDownloadTest.download(FileDownloadTest.java:45)
ААА, паника!
На этом месте большинство людей паникует, перебирает кучу опций браузера и селенидовских настроек и в конце концов пишет в чатик автоматизаторов.
А ведь всего-то надо было почитать внимательно лог.
В логе чётко видна проблема:
[LittleProxy-0-ProxyToServerWorker-1] ERROR org.littleshoot.proxy.impl.ProxyToServerConnection
- (HANDSHAKING) [id: 0xc05a41d5, L:/10.10.10.145:56103
- R:the-internet.herokuapp.com/52.1.16.137:443]
: Caught an exception on ProxyToServerConnection
java.lang.NoSuchMethodError: 'int io.netty.buffer.ByteBuf.maxFastWritableBytes()'
at io.netty.handler.codec.ByteToMessageDecoder$1.cumulate(ByteToMessageDecoder.java:86)
Крутим зависимости
Ошибка NoSuchMethodError
недвусмысленно намекает на то, что у нас проблема с зависимостями:
в classpath оказались какие-то два JAR’а с несовместимыми версиями.
Против этого уже давно придумали прививку. Удивляюсь, почему так много людей до сих пор не в курсе.
Запускаем команду:
gradle dependencies
, илиmvn dependency:tree
И вуаля! - чётко видим, какие у нас JAR’ы и каких версий. Ищем там что-то похожее на “netty”.
\--- com.browserup:browserup-proxy-core:2.1.1
+--- io.netty:netty-codec:4.1.44.Final
+--- xyz.rogfam:littleproxy:2.0.0-beta-5
| +--- io.netty:netty-all:4.1.34.Final
Как видим, у нас есть два джарника с разными версиями: netty-codec:4.1.44.Final
и netty-all:4.1.34.Final
.
Лечим зависимости
Чтобы исправить проблему, достаточно явно прописать в build.gradle
или pom.xml
более новую версию Netty
:
testRuntimeOnly("io.netty:netty-all:4.1.54.Final")
testRuntimeOnly("io.netty:netty-codec:4.1.54.Final")
(на самом деле достаточно только одной из этих строк. Домашнее задание: какой и почему?)
Команда gradle dependencies
показывает, что теперь версии совпадают:
\--- com.browserup:browserup-proxy-core:2.1.1
+--- io.netty:netty-codec:4.1.44.Final -> 4.1.54.Final
+--- xyz.rogfam:littleproxy:2.0.0-beta-5
| +--- io.netty:netty-all:4.1.34.Final -> 4.1.54.Final
Тест запускается, прокси работает, файл скачивается. Всем щастье.
Мораль
Будьте внимательнее к логам, братьям нашим меньшим!
ru.selenide.org
17.11.20