Skip to content

Commit

Permalink
refactor: 将 Lock 提取到一个单独的类进行管理
Browse files Browse the repository at this point in the history
fix: 无法同时锁定多个资源
  • Loading branch information
SALTWOOD committed Aug 10, 2024
1 parent e2a1da8 commit 7a1e1a9
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 25 deletions.
41 changes: 18 additions & 23 deletions Network/WebDav/WebDavClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
using System.Threading.Tasks;
using System.Web;
using System.Xml.Linq;
using TeraIO.Runnable;

namespace TeraIO.Network.WebDav
{
public class WebDavClient
{
protected HttpClient httpClient;
public string? lockToken;

public WebDavClient(string baseUrl)
{
Expand All @@ -25,24 +25,24 @@ public void SetUser(string username, string password)
this.httpClient.DefaultRequestHeaders.Add("Authorization", $"Basic {Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{password}"))}");
}

public async Task<HttpResponseMessage> PutFile(string fileName, byte[] data)
public async Task<HttpResponseMessage> PutFile(string fileName, byte[] data, WebDavFileLock? fileLock = null)
{
HttpContent content = new ByteArrayContent(data);
if (!string.IsNullOrWhiteSpace(lockToken))
if (!string.IsNullOrWhiteSpace(fileLock?.LockToken))
{
content.Headers.Add("Lock-Token", lockToken);
content.Headers.Add("If", $"({lockToken})");
content.Headers.Add("Lock-Token", fileLock?.LockToken);
content.Headers.Add("If", $"({fileLock?.LockToken})");
}
return await this.httpClient.PutAsync(fileName, content);
}

public async Task<HttpResponseMessage> PutFile(string fileName, Stream stream)
public async Task<HttpResponseMessage> PutFile(string fileName, Stream stream, WebDavFileLock? fileLock = null)
{
HttpContent content = new StreamContent(stream);
if (!string.IsNullOrWhiteSpace(lockToken))
if (!string.IsNullOrWhiteSpace(fileLock?.LockToken))
{
content.Headers.Add("Lock-Token", lockToken);
content.Headers.Add("If", $"({lockToken})");
content.Headers.Add("Lock-Token", fileLock?.LockToken);
content.Headers.Add("If", $"({fileLock?.LockToken})");
}
return await this.httpClient.PutAsync(fileName, content);
}
Expand Down Expand Up @@ -142,16 +142,14 @@ public async Task<HttpResponseMessage> Delete(string name)
return await this.httpClient.DeleteAsync(name);
}

public async Task<HttpResponseMessage> Lock(string name, int timeout = 60)
public async Task<WebDavFileLock> Lock(string name, int timeout = 60)
{
HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("LOCK"), name)
{
Content = new StringContent("<D:lockinfo xmlns:D='DAV:'><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockinfo>")
};
message.Headers.Add("Timeout", $"Second-{timeout}");
var response = await this.httpClient.SendAsync(message);
this.lockToken = response.Headers.GetValues("Lock-Token").First();
return response;
WebDavFileLock fileLock = new WebDavFileLock(name);
fileLock.Client.BaseAddress = this.httpClient.BaseAddress;
fileLock.Client.DefaultRequestHeaders.Clear();
this.httpClient.DefaultRequestHeaders.ForEach(kvp => fileLock.Client.DefaultRequestHeaders.Add(kvp.Key, kvp.Value));
await fileLock.Lock();
return fileLock;
}

public async Task<byte[]> GetFile(string filename)
Expand All @@ -164,12 +162,9 @@ public async Task<Stream> GetFileStream(string filename)
return await (await this.httpClient.GetAsync(filename)).Content.ReadAsStreamAsync();
}

public async Task<HttpResponseMessage> Unlock(string name)
public async Task Unlock(WebDavFileLock fileLock)
{
HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("UNLOCK"), name);
message.Headers.Add("Lock-Token", this.lockToken);
this.lockToken = null;
return await this.httpClient.SendAsync(message);
await fileLock.Unlock();
}
}
}
72 changes: 72 additions & 0 deletions Network/WebDav/WebDavFileLock.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace TeraIO.Network.WebDav
{
public class WebDavFileLock : IDisposable
{
public string FileName { get; protected set; }
public string? LockToken { get; protected set; }
private bool disposed;

public HttpClient Client { get; protected set; }

public WebDavFileLock(string name)
{
this.FileName = name;
this.Client = new HttpClient();
}

public async Task Lock(int timeout = 60)
{
HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("LOCK"), this.FileName)
{
Content = new StringContent("<D:lockinfo xmlns:D='DAV:'><D:lockscope><D:exclusive/></D:lockscope><D:locktype><D:write/></D:locktype></D:lockinfo>")
};
message.Headers.Add("Timeout", $"Second-{timeout}");
var response = await this.Client.SendAsync(message);
string lockToken = response.Headers.GetValues("Lock-Token").First();
}

public async Task Unlock()
{
HttpRequestMessage message = new HttpRequestMessage(new HttpMethod("UNLOCK"), this.FileName);
message.Headers.Add("Lock-Token", this.LockToken);
this.LockToken = null;
await this.Client.SendAsync(message);
}

protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// TODO: 释放托管状态(托管对象)
}

this.Unlock().Wait();
disposed = true;
}
}

// TODO: 仅当“Dispose(bool disposing)”拥有用于释放未托管资源的代码时才替代终结器
~WebDavFileLock()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: false);
}

public void Dispose()
{
// 不要更改此代码。请将清理代码放入“Dispose(bool disposing)”方法中
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}
8 changes: 6 additions & 2 deletions TeraIO.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,18 @@
</PropertyGroup>

<ItemGroup>
<Compile Remove="Compression\**" />
<Compile Remove="Minecraft\**" />
<Compile Remove="TeraIO.Test\**" />
<EmbeddedResource Remove="Compression\**" />
<EmbeddedResource Remove="Minecraft\**" />
<EmbeddedResource Remove="TeraIO.Test\**" />
<None Remove="Compression\**" />
<None Remove="Minecraft\**" />
<None Remove="TeraIO.Test\**" />
</ItemGroup>

<ItemGroup>
<Folder Include="Compression\" />
<Folder Include="Minecraft\" />
<Folder Include=".github\" />
</ItemGroup>

Expand Down

0 comments on commit 7a1e1a9

Please sign in to comment.