skazantsev / WebDavClient

Asynchronous cross-platform WebDAV client for .NET Core
MIT License
158 stars 30 forks source link

Strange work with DestLockToken in Copy() #55

Open Chebura opened 4 years ago

Chebura commented 4 years ago

Hi, I try to use Copy with DestLockToken (with overwrite option). Firstly, I create lock token for destination file (via Lock, that creates new empty locked file) and then specify this in DestLockToken, call Copy(), then obtain Precondition Failed 412. It is strange, because I have actual lock token for file. Same trick works for PutFile(), where I lock rewritable file (even it is does not exists) and use this lock token for writing data. My WebDAV server bytemark/webdav logs that header "If:" was received but resource not found. .net core 3.1 Thank you for attention

Chebura commented 4 years ago

Update: I tried to use IIS 10 + WebDAV with settings by default. I received same issue (snapshot):

image

It is difficult to make error with, but seems that something works wrong with lock token.

And yet another problem was deleting locked file with proper lock token in bytemark/webdav (with default settings), same error was occured, but IIS WebDAV worked fine.

skazantsev commented 4 years ago

Hi @Chebura , I reviewed the implementation of the library when it comes to passing lock tokens in write requests and I could unfortunately conclude that it's a bug in the library.

The lib supports only a subset of the spec which is not enough to make lock tokens work for the COPY method and maybe in some other cases.

The only work around is to set the correct value in the If header according to the spec. This is an example of constructing CopyParameters with an If header of the tagged form which hopefully should be enough to make it work:

var copyParams = new CopyParameters
{
    Headers = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>(
            "If",
            $"<absolute_uri_to_dest_resource> (<opaquelocktoken>)"
        )
    }
};

The library supports only passing a token in the no-tag form (If: (<opaquelocktoken>)) which doesn't work for COPY requests.

I'll consider re-visiting the implementation of lock tokens in the lib to support everything that is currently left out: tagged-list form, multiple tokens, etags, negation etc.

Thanks for submitting the issue it reveals quite important overlook in the implementation.

Chebura commented 4 years ago

Hi @Chebura , I reviewed the implementation of the library when it comes to passing lock tokens in write requests and I could unfortunately conclude that it's a bug in the library.

The lib supports only a subset of the spec which is not enough to make lock tokens work for the COPY method and maybe in some other cases.

The only work around is to set the correct value in the If header according to the spec. This is an example of constructing CopyParameters with an If header of the tagged form which hopefully should be enough make it work:

var copyParams = new CopyParameters
{
    Headers = new List<KeyValuePair<string, string>>
    {
        new KeyValuePair<string, string>(
            "If",
            $"<absolute_uri_to_dest_resource> (<opaquelocktoken>)"
        )
    }
};

The library supports only passing a token in the no-tag form (If: (<opaquelocktoken>)) which doesn't work for COPY requests.

I'll consider re-visiting the implementation of lock tokens in the lib to support everything that is currently left out: tagged-list form, multiple tokens entity tags, multiple etags, negation etc.

Thanks for submitting the issue it reveals quite important overlook in the implementation.

Hi, this approach with manually setting of header "If" works well! Thank you, I hope your library will be improved!