Repository: iterative/dvc

Issue:
url path for webdav push gets duplicated in dvc versions >=2.9.0
# Bug Report

<!--
## Issue name

Issue names must follow the pattern `command: description` where the command is the dvc command that you are trying to run. The description should describe the consequence of the bug. 

Example: `repro: doesn't detect input changes`
-->

## Description

We have identified a bug(?) introduced from version 2.8.3 to 2.9.0. When pushing dvc data to a webdav server the path of the url gets duplicated. For example: If we push to webdavs://servername.com/path/to/location it pushes to webdavs://servername.com/path/to/location/path/to/location (creating all folders of the second "path/to/location" on the server). As it works with dvc version 2.8.3 we think that this might be a bug within dvc version 2.9.0 and our setup might not be too interesting for you. However, here is a rough overview of the webdav server setup: We are running an apache2 webdav server as our remote storage for our dvc projects. This webdav server is behind a reverse proxy (nginx).

### Reproduce

Using dvc version <=2.8.3 everything works as expected. dvc version >=2.9.0 it does not work anymore.

### Expected

Version 2.9.* should work the same as 2.8.*

### Environment information

The environment information might not be too interesting, but I can add more information, if needed

**Output of `dvc doctor`:**

```console
$ dvc doctor
```
version 2.8.3 fails withtin wsl, as reported elsewhere (https://issueexplorer.com/issue/iterative/dvc/7012)

**Additional Information (if any):**

Hope the report is detailed enough. Will add information if necessary.


Discussion:
@conrad-stork Hello!
Could you provide some information on how to reproduce this particular problem?
@pared Yes I will try to explain it as accurate as possible. If something missing let me know. Concrete questions would help, because its not clear what you know anyways.

We are running a nginx server as a reverse proxy for all our web applications that we run in-house. This nginx server forwards the incoming requests to the web applications that are build in docker containers. The most important part of  the nginx config looks the following:
```
server {
        ... some authentication settings ...
        location /dvc {
                proxy_pass http://127.0.0.1:"port";
                proxy_set_header Host $host;

                client_max_body_size 100m;
        }
}
```
If you need more details regarding the nginx server configuration, please let me know what exactly you need.

So every request coming to out server/dvc is redirected to out locally running webdav within a docker container on port "port". Therefore we have set up an apache2 server (default settings except of the vhost) which provides the webdav server for our dvc storing location. The vhost config of the apache2 server is quiet easy:
```
DavLockDB /path to/DavLock

<VirtualHost *:80>
    ServerAdmin admin@localhost
    ServerName localhost
    ServerAlias localhost
    DocumentRoot /path to/webdav
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
    DirectorySlash Off

    <Directory /path to webdav>
        DAV On
        AuthType Basic
        AuthName "Restricted Files"
        AuthBasicProvider file
        AuthUserFile "path to passwd/passwds"
        Require user some_users
    </Directory>

</VirtualHost>
```
Pushing now data from somewhere in the network to our server/dvc/Path/To/Location works fine with version 2.8.3. From version on 2.9.0 the push works also fine, but the location on the server gets messed up to server/dvc/Path/To/Location/dvc/Path/To/Location (so everything behind server gets duplicated).

For me it looks like at some point where the server location is build (I am not familiar with any part of the code but the path on the server is given relatively and not absolute anymore?) something gets wrong. Might be that the forwarding of the request has something to do with it?

Let me know if I can help you somehow, also a short talk might be possible if it makes things easier.

Thanks in advance!
Best
Conrad
@conrad-stork ok, I've been playing with my own webdav account and it seems you are right, when I switch between different versions, the path on the server (for cache) is different. Investigating...
did a bit of bisecting and it seems our path change has been the culprit:
9aec8f1926bd1d08d370d12902b9ad9b55707cf5
@conrad-stork temporary workaround is to downgrade to `2.8.3`.
Did a brief research and the problem is that before 9aec8f1 `_strip_protocol` returned whole PathInfo for WebDav:
https://github.com/iterative/dvc/blob/4175f9ffa4948157436283bef11153a7233e90ca/dvc/fs/__init__.py#L116-L122

Before this change we used `fs.base` one:
https://github.com/iterative/dvc/blob/4175f9ffa4948157436283bef11153a7233e90ca/dvc/fs/base.py#L73-L74

In 9aec8f1 we introduce webdav-specific implementation:
https://github.com/iterative/dvc/blob/9aec8f1926bd1d08d370d12902b9ad9b55707cf5/dvc/fs/webdav.py#L38-L41

Before 9aec8f1 we used to provide the whole path to `transfer` method. Now the odb is partially responsible for building the path. Need to investigate it further.
Another part is that we don't use any webdav subpaths in our tests, only using root https://github.com/iterative/dvc-webdav/blob/main/dvc_webdav/tests/cloud.py#L11 , hence why we didn't catch it too.

Removing `release-blocker` for now, since it was broken for a few releases already, so no reason to block the current one.
For the record: @skshetry confirmed that we need to use full urls for webdav, so we need to adjust dvc/fs/webdav.py accordingly.

Resolving patch:
diff --git a/dvc/fs/webdav.py b/dvc/fs/webdav.py
--- a/dvc/fs/webdav.py
+++ b/dvc/fs/webdav.py
@@ -35,9 +35,11 @@ def __init__(self, **config):
 
     @classmethod
     def _strip_protocol(cls, path: str) -> str:
-        from fsspec.utils import infer_storage_options
-
-        return infer_storage_options(path)["path"].lstrip("/")
+        """
+        For WebDAVFileSystem, provided url is the base path itself, so it
+        should be treated as being a root path.
+        """
+        return ""
 
     def unstrip_protocol(self, path: str) -> str:
         return self.fs_args["base_url"] + "/" + path


Test patch: