aerokube / selenoid

Selenium Hub successor running browsers within containers. Scalable, immutable, self hosted Selenium-Grid on any platform with single binary.
https://aerokube.com/selenoid/latest/
Apache License 2.0
2.59k stars 323 forks source link

File upload doesn't work #1079

Closed VitaliiDolotov closed 2 years ago

VitaliiDolotov commented 3 years ago

🐛 Bug Report

File upload is not working using RemoteWebDriver. It is working fine running locally but fails on Remote.

Last compatible WebDriver version 4.0.0-alpha05 Stop working since 4.0.0-alpha07 Still not working in 4.0.0-beta2

Unable to upload file: System.NotImplementedException: unknown command: unknown command: session/eaee033d03861677627f084357ea877a/se/file
   at OpenQA.Selenium.Remote.RemoteWebDriver.UnpackAndThrowOnError(Response errorResponse)
   at OpenQA.Selenium.Remote.RemoteWebDriver.Execute(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.Remote.RemoteWebDriver.InternalExecute(String driverCommandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.Remote.RemoteWebElement.Execute(String commandToExecute, Dictionary`2 parameters)
   at OpenQA.Selenium.Remote.RemoteWebElement.UploadFile(String localFile)
   at OpenQA.Selenium.Remote.RemoteWebElement.SendKeys(String text)
   at SeleniumExtras.PageObjects.WebElementProxy.SendKeys(String text)

To Reproduce

driver.FindElement(By.Id("upload")).SendKeys(file);

Expected behavior

File uploaded successfully

Test script or set of commands reproducing this issue

                var chromeOptions = new ChromeOptions();

                chromeOptions.AddArguments("headless", "--window-size=1920,1080", "--safebrowsing-disable-download-protection");

                chromeOptions.AddUserProfilePreference("download.default_directory", "/home/selenium/Downloads");
                chromeOptions.AddUserProfilePreference("download.prompt_for_download", false);
                chromeOptions.AddUserProfilePreference("download.directory_upgrade", true);
                chromeOptions.AddUserProfilePreference("safebrowsing.enabled", false);

                chromeOptions.SetLoggingPreference(LogType.Browser, LogLevel.All);
                var driver = new RemoteWebDriver(new Uri(Browser.HubUri), chromeOptions);

                driver.Navigate().GoToUrl("<URL>");

                IAllowsFileDetection fileDetectionDriver = (IAllowsFileDetection)driver;
                fileDetectionDriver.FileDetector = new LocalFileDetector();

                var file = "<File_Path>";

                driver.FindElement(By.Id("upload")).SendKeys(file);

Environment

Selenoid: 1.10.3 Browser: Chrome Browser version: 89.0.4389.114 Browser Driver version: Selenium.WebDriver.ChromeDriver -Version 89.0.4389.2300 Language Bindings version: C#

Notes

Related bug for WebDriver https://github.com/SeleniumHQ/selenium/issues/9350

vania-pooh commented 3 years ago

@VitaliiDolotov there is no such API /se/file defined in the W3C standard. Selenoid proxies all HTTP requests directly to respective webdriver binary. So that means e.g. that there is no such API in webdriver binary. Respective commit where everything was broken: https://github.com/SeleniumHQ/selenium/commit/824617b75181f0cb8a83025d8acfb70b37038f6b

VitaliiDolotov commented 3 years ago

Hi @vania-pooh , thanks for the replay. File upload is working fine locally but stops working using RemoteWebDriver. That why I assumed that issue with Selenoid. Am I right saying that this fix should be done in WebDriver?

vania-pooh commented 3 years ago

@VitaliiDolotov that's a complicated question because this API is not standard. But so far as Selenoid simply proxies such requests to the web driver binary, it seems that trying to fix this on Selenoid side does not seem to be a good idea (it will decrease overall performance).

StanislavKharchenko commented 3 years ago

Faced with the same issue on selenoid. However, this works ok using selenium 4 grid, so, looks like issue directly referred to Selenoid.

@vania-pooh Could we expect to have fixed this defect on Selenoid side? Selenium guys closed their issue with refer to selenoid.

aandryashin commented 3 years ago

Hello! I am runnig tests without Selenoud, and faced the same issue:

$ docker run -it --rm -p 4444:4444 quay.io/browsers/chrome:91.0
20
Waiting X server...
2021/06/28 18:58:12 [INIT] [Listening on :7070]
Logging to: /dev/null
Waiting X server...
Waiting X server...
Starting ChromeDriver 91.0.4472.101 (af52a90bf87030dd1523486a1cd3ae25c5d76c9b-refs/branch-heads/4472@{#1462}) on port 4444
All remote connections are allowed. Use an allowlist instead!
Please see https://chromedriver.chromium.org/security-considerations for suggestions on keeping ChromeDriver safe.
ChromeDriver was started successfully.
$ curl http://localhost:4444/session -d '{"capabilities":{"alwaysMatch":{"browserName":"chrome", "goog:chromeOptions":{"args": ["--no-sandbox"]}}}}'
{"value":{"capabilities":{"acceptInsecureCerts":false,"browserName":"chrome","browserVersion":"91.0.4472.106","chrome":{"chromedriverVersion":"91.0.4472.101 (af52a90bf87030dd1523486a1cd3ae25c5d76c9b-refs/branch-heads/4472@{#1462})","userDataDir":"/tmp/.com.google.Chrome.78FeG9"},"goog:chromeOptions":{"debuggerAddress":"localhost:39313"},"networkConnectionEnabled":false,"pageLoadStrategy":"normal","platformName":"linux","proxy":{},"setWindowRect":true,"strictFileInteractability":false,"timeouts":{"implicit":0,"pageLoad":300000,"script":30000},"unhandledPromptBehavior":"dismiss and notify","webauthn:extension:largeBlob":true,"webauthn:virtualAuthenticators":true},"sessionId":"b129a875c224aa2b431637a444f1f305"}}
$ curl -X POST http://localhost:4444/session/b129a875c224aa2b431637a444f1f305/se/file
{"value":{"error":"unknown command","message":"unknown command: unknown command: session/b129a875c224aa2b431637a444f1f305/se/file","stacktrace":"#0 0x55d75918d949 \u003Cunknown>\n"}}

There is no api implemented on /se/file in chromedriver, but there is on /file.

aandryashin commented 3 years ago

Test code receives error:

INFO: Detected dialect: W3C

org.openqa.selenium.UnsupportedCommandException: unknown command: unknown command: session/c6d981124b6ec773f82df7c6eb73da7d/se/file
Build info: version: '4.0.0-beta-4', revision: '29f46d02dd'
System info: host: 'macbook', ip: '2002:a25:2cd5:0:3199:f90c:1c14:f04e%en0', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.16', java.version: '1.8.0_292'
Driver info: org.openqa.selenium.remote.RemoteWebDriver
Command: [c6d981124b6ec773f82df7c6eb73da7d, uploadFile {file=UEsDBBQACAgIAKW43FIAAAAAAAAAAAAAAAAEAAAAZmlsZQMAUEsHCAAAAAACAAAAAAAAAFBLAQIUABQACAgIAKW43FIAAAAAAgAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAABmaWxlUEsFBgAAAAABAAEAMgAAADQAAAAAAA==}]
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 91.0.4472.106, chrome: {chromedriverVersion: 91.0.4472.101 (af52a90bf870..., userDataDir: /tmp/.com.google.Chrome.1iSLX3}, goog:chromeOptions: {debuggerAddress: localhost:40547}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: LINUX, platformName: LINUX, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:extension:largeBlob: true, webauthn:virtualAuthenticators: true}
Element: [[RemoteWebDriver: chrome on LINUX (c6d981124b6ec773f82df7c6eb73da7d)] -> id: uploadfile_0]
Session ID: c6d981124b6ec773f82df7c6eb73da7d

As you can see there is no Selenoid there is standard cromedriver, so I suppose that is client side issue.

kndani commented 3 years ago

I got this issue and reported https://github.com/SeleniumHQ/selenium/issues/9696

vania-pooh commented 3 years ago

@kndani they will reject saying that on Selenium server it works.

kndani commented 3 years ago

@vania-pooh they had the same issue (#8524) in an alpha version which they fixed but somehow it appears again, I will also check on the selenium server and will update

titusfortner commented 3 years ago

there is no such API /se/file defined in the W3C standard

This is true! Except there is also no /file defined in the w3c spec. For endpoints that selenium needs but aren't defined in the spec, they get vendor namespaced (hence /se/file).

For Firefox & Safari, they need an intermediary node to handle the behavior (like Selenium Server), but Chrome implemented /file directly for some reason, so if you are just directing everything to Chrome, a quick answer (that is not guaranteed to keep working) is to redirect /se/file to /file.

jimevans commented 3 years ago

Folks, here's the situation. The W3C WebDriver Specification governs how the Element Send Keys command handles <input type="file"> elements. To wit, it says that for such elements, the key sequence sent to the driver will be treated as a path to a local file. Clearly, in the distributed case, where the machine running the WebDriver code (the so-called "local end," in spec language) and the machine where the browser and its driver are running (the so-called "remote end"), the path on the local end likely won't exist on the remote end.

To allow for this distributed execution, the Selenium team created an extension command as allowed by the specification. To wit, the extension command follows the URL /session/{sessionId}/se/file*, where the se designation is the vendor-specific prefix. This command will take the local file and transmit it to the remote end so that when the local file path is executed on the remote machine, the file to be uploaded can be found. The Selenium remote implementation understands the extension command; other projects that purport to replace the Selenium grid implementation and maintain full feature compatibility must also implement this end point.

*As a historical note, it used to be just file, but when the spec was finalized, the se prefix was added to make the command spec compliant. Prior versions of other browser drivers that implemented the legacy OSS dialect of the WebDriver protocol (sometimes called the "JSON Wire Protocol") implemented the old /file end point, even though there was no need for them to do so, as it only applies in the remote case.

vania-pooh commented 3 years ago

Currently we fixed this stuff in recent Moon version by supporting /se/ prefix.

phyt3r commented 3 years ago

Still no workaround this problem with Selenoid? Using: Selenium 4.0.0-rc-1 Selenoid 1.10.5

Skoggtroll commented 3 years ago

@vania-pooh I have same issue on my project using Selenium 4.0.0-rc-1 and selenoid 1.10.4

Can I expect the problem to be fixed for selenoid?

cogitovirus commented 3 years ago

@vania-pooh - I'm stuck on the same issue. Me and my team were excited to implement selenoid in our project, but we have a bunch of test cases failing because of the inability to upload files. With that we are unable to go beyond beta with this new grid.

I would appreciate if someone could look into it.

aandryashin commented 3 years ago

Hello, selenoid was not designed like moon, it is not possible to fix the issue on selenoid side, because it just proxy to browser container. The issue should be fixed in browser images, like it done for firefox with selenoid binary packed to the image. Unfortunately we have not enough resources to fix it in all images, or maintain images especially for selenoid. Images are opensourced and you can easily build your own with needed functionality.

For us it is overhead to rebuild all images for selenoid at the moment, thank you for understanding.

Also take a look to our new product called Moon, there issue has been easily fixed because of different architecture.

Alexander Andryashin.

чт, 7 окт. 2021 г., 15:02 wzolni @.***>:

@vania-pooh https://github.com/vania-pooh - I'm stuck on the same issue. Me and my team were excited to implement selenoid in our project, but we have a bunch of test cases failing because of the inability to upload files. With that we are unable to go beyond beta with this new grid.

I would appreciate if someone could look into it.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/aerokube/selenoid/issues/1079#issuecomment-937725810, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAKY23IRE7W6AUOIA2NEMYDUFWD6DANCNFSM42HHH5RQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

BorisOsipov commented 3 years ago

@aandryashin thank you for clarification. To recap: From now official aerokube selenoid\browser images are not compatible with official selenium v4 client bindings? Am I right?

aandryashin commented 3 years ago

Images in selenoid repo for performance reason, contain only drivers and not selenium-node, most drivers implement upload under /file and everything is working if client send request to /file, new selenium client send requests to /se/file and selenoid just proxy request to unexistent in driver handler...

That is the reason. Where it should be fixed big question. We have already raised issue on selenium repo please check it.

It is possible to workaround the issue:

setup nginx in front of selenoid an modify urls like this:

/se/file => /file That can be done by additional running container. We will consider that way to fix the issue. пт, 8 окт. 2021 г., 00:00 Boris Osipov ***@***.***>: > @aandryashin thank you for clarification. > To recap: > From now official aerokube selenoid\browser images are not compatible with > official selenium v4 client bindings? Am I right? > > — > You are receiving this because you were mentioned. > Reply to this email directly, view it on GitHub > , > or unsubscribe > > . > Triage notifications on the go with GitHub Mobile for iOS > > or Android > . > >
dbudim commented 2 years ago

Hi colleagues! Any updates about it? Will it be fixed for Selenoid? Or nginx workaround only?

vania-pooh commented 2 years ago

@dbudim we are thinking about possible implementation.

vania-pooh commented 2 years ago

Applied a fix. Please try with aerokube/selenoid:latest.

aandryashin commented 2 years ago

Fixed by d6fc603e4c50338d929f4a8bd285cee514d91fb7

vania-pooh commented 2 years ago

You guys were asking a lot of times about this fix. Without a confirmation that this has been fixed on your side - we will not release.

phyt3r commented 2 years ago

@vania-pooh it worked for me with aerokube/selenoid:latest and selenium:4.0.0. Thanks

vania-pooh commented 2 years ago

@phyt3r ok, will release this soon.

cogitovirus commented 2 years ago

I can confirm. It has worked for me as well. 👍 Great job.

tyge68 commented 2 years ago

Any idea if that will it also then impact selenoid/vnc images or is that a totally different project ? since that are the images we are using via webdrivermanager -> https://github.com/bonigarcia/webdrivermanager

vania-pooh commented 2 years ago

@tyge68 this can only impact Firefox images (other images don't contain Selenoid inside). Starting from next Firefox version - we'll use latest Selenoid there.

tyge68 commented 2 years ago

@vania-pooh thanks, so it's not really clear what is wrong with chromedriver / selenoid/vnc images, as the gile upload is indeed broken there too with the same error pattern.

vania-pooh commented 2 years ago

@tyge68 this is because in all webdriver binaries file upload API is still at /file whereas Selenium client starting from version 4.0.0 is using /se/file. This is why we consider this modification a strange idea, because it breaks things. And I don't think this will be fixed in webdriver binaries in nearest future.

tyge68 commented 2 years ago

@vania-pooh I see, it works indeed if I use docker selenium/standalone-chrome image instead of selenoid/vnc:chrome_95.0 image. But then I miss the video recording for some reasons, but eventually I will dig in to this to see if we can use then official image instead of selenoid ones.

vania-pooh commented 2 years ago

@tyge68 this is probably because there is Selenium Java inside this image.

tyge68 commented 2 years ago

@vania-pooh you mean on the selenium/standalone-chrome ? what do you think would be required to make selenoid/vnc:chrome_95.0 works ?

vania-pooh commented 2 years ago

@tyge68 yes, official images are certainly Java based. Our images are using Chromedriver directly as WebDriver API. Either Selenium guys should support both paths in their client or Chromedriver should start supporting /se/file API.

tyge68 commented 2 years ago

@vania-pooh I still don't understand why it passed locally with chromedriver and not via the docker image then, at the end it uses the same chromedriver for chrome 95 (although locally I already have chrome browser 96), as in both case the code that execute the test uses the same selenium client library. Also it's odd that selenium 4.x api had once without /se/file/ and then it got added back before the official release.

tyge68 commented 2 years ago

@vania-pooh I have suggested a PR(1) on selenium project , let see if that can get merged (1) https://github.com/SeleniumHQ/selenium/pull/10046

tyge68 commented 2 years ago

@vania-pooh it got rejected, but finally it was easy to solve, since docker also have api to copy file from/to container, so it was easy to create a "uploadFile(file, seleniumElement)" kind of helper, and so that based on context to copy the file to the docker or not if executed locally, in the case of selenoid/vnc:chrome_95.0 I could then copy the file under /home/selenium/Downloads folder, and use the new location when doing the sendKeys action on the targeted element.

So finally all those /se/file or /file endpoints are useless, which might explain it's not in the w3c definition, as it doesn't really help, it is simpler to do it ourself in context.

motine commented 1 year ago

this may be a little off topic, but it would have been super helpful earlier. i needed to work around this issue for ruby, so i made a workaround for in the capybara gem