[WebDav] WebDav基础知识

文章目录

  • 什么是WebDav
  • WebDav常用命令
  • WebDav常用命令的测试(代码)
    • PROPFIND 方法测试
    • PUT 方法测试
    • GET 方法测试
    • PROPPATCH方法
  • WebDav缓存
    • Cache-Control
    • Etag
      • 测试
    • 强制重新验证
    • 不需要缓存
  • WebDav的锁
  • WebDav的状态码
  • WebDav身份验证
  • WebDav版本控制
  • WebDav和FTP的区别
  • 参考

什么是WebDav

What is WebDAV?
Briefly: WebDAV stands for “Web-based Distributed Authoring and Versioning”. It is a set of extensions to the HTTP protocol which allows users to collaboratively edit and manage files on remote web servers.
WebDAV Resources

WebDav是基于HTTP的协议,他可以允许客户端远程编辑Web内容。

WebDAV的特性和优势
支持创建、修改、复制、移动、移除、查询、列举文件
文件锁
版本控制
支持修改文件属性
安全完善的身份验证机制
支持https加密
支持proxy
客户端缓存
方便的客户端工具:和局域网中的文件共享一样简单使用。
来源:学习WebDav

WebDav常用命令

WebDav在HTTP的基础上扩展了自己的命令,例如:
PROPFIND 用于获取文件夹列表、文件夹内的文件列表、文件夹和文件的属性;
MKCOL 用于创建空文件夹;
PUT 用于上传文件;
GET 用于下载文件;
COPY 用于复制文件;
MOVE 用于移动文件;

WebDav常用命令的测试(代码)

我在坚果云网盘中,创建了几个文件夹,上传了几个文件。并按照如何在Zotero中设置webdav连接到坚果云?进行了网盘的WebDav服务配置,生成了WebDav密码。
在这里插入图片描述
根据学习WebDav ,直接在windows cmd使用curl命令就可以一定程度测试WebDav,我这里是在VS 2022中,通过libcurl库,向坚果云发送请求。
关于VS中如何导入libcurl库,可以看[libcurl] windows visual studio 导入libcurl库。

PROPFIND 方法测试

代码:

#include <curl/curl.h>
#include <iostream>
#include <fstream>using std::cout;
using std::endl;
using std::ios;#define ERROR(X) (cout << __FUNCDNAME__ <<  " " << (X) << " " << "error" << endl, -1)
#define ERROR2(X,Y) (cout << __FUNCDNAME__ <<  " " << (X) << " " << (Y) << " " << "error" << endl, -1)#if 1 // WebDav
size_t write_callback(char* ptr, size_t size, size_t nmemb, void* userdata);
int My_PROPFIND();
FILE* fp;int main()
{//打开一个文件,用于输出WebDav响应char filename[256];sprintf_s(filename, 256, "%s.%s", "WebDav-Test", "xml");errno_t err = fopen_s(&fp, filename, "wb");if (err)return ERROR2("fopen_s", err);//初始化curlcurl_global_init(CURL_GLOBAL_WIN32);//WebDav请求函数My_PROPFIND();curl_global_cleanup();cout << "program end." << endl;
}int My_PROPFIND()
{const char* host = "https://dav.jianguoyun.com";const char* url = "https://dav.jianguoyun.com/dav/box1";CURL* curl = curl_easy_init();if (curl) {//设置HTTP头		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PROPFIND"); //修改HTTP方法curl_easy_setopt(curl, CURLOPT_URL, url); //设置URL		curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_1_1); //指定HTTP版本curl_easy_setopt(curl, CURLOPT_USERNAME, "这里隐藏掉邮箱地址@qq.com"); //设置访问WebDav账号和密码curl_easy_setopt(curl, CURLOPT_PASSWORD, "axs5pyhc2j6n7q");struct curl_slist* list = NULL; //设置HTTP头部字段list = curl_slist_append(list, "Connection: close"); //不要长连接list = curl_slist_append(list, "Accept: */*");curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);//指定用于SSL证书验证的证书CURLcode err = curl_easy_setopt(curl, CURLOPT_CAINFO, "D:\\SourceCode\\cert\\_.jianguoyun.com.crt");if (err != CURLE_OK) {cout << "CURLOPT_CAPATH err:" << err << endl;}//如果不设置,会出现:unable to get local issuer certificate的错误//设定HTTP响应的处理方法curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)fp);//设定控制台回显调试信息curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);//执行HTTP请求CURLcode ret = curl_easy_perform(curl);if (ret != CURLE_OK) {curl_easy_cleanup(curl);fclose(fp);return ERROR2("curl_easy_perform", ret);}}else {fclose(fp);return ERROR("curl_easy_init");}fclose(fp);curl_easy_cleanup(curl);return 0;
}size_t write_callback(char* ptr, size_t size, size_t nmemb, void* userdata)
{int realsize = size * nmemb;fwrite(ptr, 1, realsize, fp);return realsize;
}
#endif

控制台输出:

* Host dav.jianguoyun.com:443 was resolved.
* IPv6: (none)
* IPv4: 36.155.116.36, 36.155.116.35
*   Trying 36.155.116.36:443...
* Connected to dav.jianguoyun.com (36.155.116.36) port 443
* ALPN: curl offers http/1.1
*  CAfile: D:\SourceCode\cert\_.jianguoyun.com.crt
*  CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 / [blank] / UNDEF
* ALPN: server accepted http/1.1
* Server certificate:
*  subject: CN=*.jianguoyun.com
*  start date: Jan 23 00:00:00 2024 GMT
*  expire date: Feb 19 23:59:59 2025 GMT
*  subjectAltName: host "dav.jianguoyun.com" matched cert's "*.jianguoyun.com"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=Sectigo Limited; CN=Sectigo RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
*   Certificate level 0: Public key type ? (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* using HTTP/1.x
* Server auth using Basic with user ‘这里隐藏掉邮箱地址@qq.com'
> PROPFIND /dav/box1 HTTP/1.1
Host: dav.jianguoyun.com
Authorization: Basic MjgwMjAzNzEyN这里隐藏掉B5aGMyajZuN3F0eg==
Connection: close
Accept: */*< HTTP/1.1 207 Multi-Status
< Server: nginx
< Date: Mon, 19 Feb 2024 04:14:58 GMT
< Content-Type: text/xml; charset=UTF-8
< Content-Length: 2882
< Connection: close
< Pragma: no-cache
< Cache-Control: no-cache
<
* Closing connection
program end.

可以看到,发出的请求是:

> PROPFIND /dav/box1 HTTP/1.1
Host: dav.jianguoyun.com
Authorization: Basic MjgwMjAzNzEyN这里隐藏掉B5aGMyajZuN3F0eg==
Connection: close
Accept: */*

收到的响应HTTP头是:

< HTTP/1.1 207 Multi-Status
< Server: nginx
< Date: Mon, 19 Feb 2024 04:14:58 GMT
< Content-Type: text/xml; charset=UTF-8
< Content-Length: 2882
< Connection: close
< Pragma: no-cache
< Cache-Control: no-cache

输出到文件中的XML内容是:

<d:multistatus>
<d:response><d:href>/dav/box1/</d:href>
<d:propstat>
<d:prop><d:getcontenttype>httpd/unix-directory</d:getcontenttype><d:displayname>box1</d:displayname><d:owner>这里隐藏掉邮箱地址@qq.com</d:owner>
<d:resourcetype><d:collection/></d:resourcetype><d:getcontentlength>0</d:getcontentlength><d:getlastmodified>Mon, 19 Feb 2024 04:14:58 GMT</d:getlastmodified>
<d:current-user-privilege-set>
<d:privilege><d:read/></d:privilege>
<d:privilege><d:write/></d:privilege>
<d:privilege><d:all/></d:privilege>
<d:privilege><d:read_acl/></d:privilege>
<d:privilege><d:write_acl/></d:privilege></d:current-user-privilege-set></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response>
<d:response><d:href>/dav/box1/WeatherWS.xml</d:href>
<d:propstat>
<d:prop><d:getetag>UsZ7ybf73r39UXEEPQs5qA</d:getetag><d:getcontenttype>text/xml</d:getcontenttype><d:displayname>WeatherWS.xml</d:displayname><d:owner>这里隐藏掉邮箱地址@qq.com</d:owner><d:getcontentlength>29712</d:getcontentlength><d:getlastmodified>Fri, 29 Dec 2023 09:02:10 GMT</d:getlastmodified><d:resourcetype/>
<d:current-user-privilege-set>
<d:privilege><d:read/></d:privilege>
<d:privilege><d:write/></d:privilege>
<d:privilege><d:all/></d:privilege>
<d:privilege><d:read_acl/></d:privilege>
<d:privilege><d:write_acl/></d:privilege></d:current-user-privilege-set></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response>
<d:response><d:href>/dav/box1/box1_1</d:href>
<d:propstat>
<d:prop><d:getetag/><d:getcontenttype>httpd/unix-directory</d:getcontenttype><d:displayname>box1_1</d:displayname><d:owner>这里隐藏掉邮箱地址@qq.com</d:owner><d:getcontentlength>0</d:getcontentlength><d:getlastmodified>Tue, 13 Feb 2024 04:29:51 GMT</d:getlastmodified>
<d:resourcetype><d:collection/></d:resourcetype>
<d:current-user-privilege-set>
<d:privilege><d:read/></d:privilege>
<d:privilege><d:write/></d:privilege>
<d:privilege><d:all/></d:privilege>
<d:privilege><d:read_acl/></d:privilege>
<d:privilege><d:write_acl/></d:privilege></d:current-user-privilege-set></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response>
<d:response><d:href>/dav/box1/box1file.pdf</d:href>
<d:propstat>
<d:prop><d:getetag>rlLyz4SUXar-UNmip-F5Qw</d:getetag><d:getcontenttype>application/pdf</d:getcontenttype><d:displayname>box1file.pdf</d:displayname><d:owner>这里隐藏掉邮箱地址@qq.com</d:owner><d:getcontentlength>2422816</d:getcontentlength><d:getlastmodified>Wed, 15 Nov 2023 08:43:08 GMT</d:getlastmodified><d:resourcetype/>
<d:current-user-privilege-set>
<d:privilege><d:read/></d:privilege>
<d:privilege><d:write/></d:privilege>
<d:privilege><d:all/></d:privilege>
<d:privilege><d:read_acl/></d:privilege>
<d:privilege><d:write_acl/></d:privilege></d:current-user-privilege-set></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>

我对Dav中的box1文件夹发送了PROPDIND请求,在响应回来的XML内容中,列出了box1中的每个文件夹和文件(包括box1自己)。每个<d:response>节点都包含了一个文件夹或者文件,<d:response>节点,是文件夹或者文件的属性信息。

PUT 方法测试

只保留方法部分,其余代码省略。

int My_PUT()
{//这里需要指明需要在Dav上创建的文件的路径“box1”和名字“Upload_test.txt”const char* url = "https://dav.jianguoyun.com/dav/box1/Upload_test.txt";CURL* curl = curl_easy_init();if (curl) {		//设置HTTP头		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT"); //修改HTTP方法curl_easy_setopt(curl, CURLOPT_URL, url); //设置URL		curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_1_1); //指定HTTP版本curl_easy_setopt(curl, CURLOPT_USERNAME, "2xxxxxxxx4@qq.com"); //设置访问WebDav账号和密码curl_easy_setopt(curl, CURLOPT_PASSWORD, "axs5pyhc2j6n7q");struct curl_slist* list = NULL; //设置HTTP头部字段list = curl_slist_append(list, "Connection: close"); //不要长连接list = curl_slist_append(list, "Accept: */*");curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);//设置要上传的文件信息//打开文件curl_off_t fsize = 0;FILE* src = nullptr;errno_t ferr = fopen_s(&src, "D:\\SourceCode\\TransFILE1.txt", "rb");if (ferr)return -1;//获取文件大小fseek(src, 0, SEEK_END);	fsize = ftell(src);fseek(src, 0, SEEK_SET);curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb); //设置读取文件的回调函数curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); //启动Upload服务curl_easy_setopt(curl, CURLOPT_READDATA, src);//设置传入回调函数的文件句柄curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize);//设置文件大小//指定用于SSL证书验证的证书CURLcode err = curl_easy_setopt(curl, CURLOPT_CAINFO, "D:\\SourceCode\\cert\\_.jianguoyun.com.crt");if (err != CURLE_OK) {cout << "CURLOPT_CAPATH err:" << err << endl;}//如果不设置,会出现:unable to get local issuer certificate的错误//设定HTTP响应的处理方法curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)fp);//设定控制台回显调试信息curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);//执行HTTP请求CURLcode ret = curl_easy_perform(curl);if (ret != CURLE_OK) {curl_easy_cleanup(curl);fclose(fp);return ERROR2("curl_easy_perform", ret);}}else {fclose(fp);return ERROR("curl_easy_init");}fclose(fp);curl_easy_cleanup(curl);return 0;
}
static size_t read_cb(char* ptr, size_t size, size_t nmemb, void* userdata)
{FILE* src = (FILE*)userdata;/* copy as much data as possible into the 'ptr' buffer, but no more than'size' * 'nmemb' bytes */size_t retcode = fread(ptr, size, nmemb, src);return retcode;
}

控制台回显信息(部分):

> PUT /dav/box1/Upload_test.txt HTTP/1.1
Host: dav.jianguoyun.com
Authorization: Basic MjgwMjAzNzEyNEB---------------aGMyajZuN3F0eg==
Connection: close
Accept: */*
Content-Length: 1844* We are completely uploaded and fine
< HTTP/1.1 204 No Content
< Server: nginx
< Date: Mon, 19 Feb 2024 05:59:17 GMT
< Connection: close
< X-File-Version: 3
< Pragma: no-cache
< Cache-Control: no-cache
<
* Closing connection

WebDav查看:
在这里插入图片描述

GET 方法测试

int My_GET()
{const char* url = "https://dav.jianguoyun.com/dav/box1/Upload_test.txt";CURL* curl = curl_easy_init();if (curl) {//设置HTTP头		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET"); //修改HTTP方法curl_easy_setopt(curl, CURLOPT_URL, url); //设置URL		curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_1_1); //指定HTTP版本curl_easy_setopt(curl, CURLOPT_USERNAME, "2--------4@qq.com"); //设置访问WebDav账号和密码curl_easy_setopt(curl, CURLOPT_PASSWORD, "axs5pyhc2j6n7q");struct curl_slist* list = NULL; //设置HTTP头部字段list = curl_slist_append(list, "Connection: close"); //不要长连接list = curl_slist_append(list, "Accept: */*");curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);//指定用于SSL证书验证的证书CURLcode err = curl_easy_setopt(curl, CURLOPT_CAINFO, "D:\\SourceCode\\cert\\_.jianguoyun.com.crt");if (err != CURLE_OK) {cout << "CURLOPT_CAPATH err:" << err << endl;}//如果不设置,会出现:unable to get local issuer certificate的错误//设定HTTP响应的处理方法curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)fp);//设定控制台回显调试信息curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);//执行HTTP请求CURLcode ret = curl_easy_perform(curl);if (ret != CURLE_OK) {curl_easy_cleanup(curl);fclose(fp);return ERROR2("curl_easy_perform", ret);}}else {fclose(fp);return ERROR("curl_easy_init");}fclose(fp);curl_easy_cleanup(curl);return 0;
}

控制台回显结果(部分):

> GET /dav/box1/Upload_test.txt HTTP/1.1
Host: dav.jianguoyun.com
Authorization: Basic MjgwMjAzNzEyNEBxc--------------GMyajZuN3F0eg==
Connection: close
Accept: */*< HTTP/1.1 200 OK
< Server: nginx
< Date: Mon, 19 Feb 2024 06:13:18 GMT
< Content-Type: text/plain
< Content-Length: 1844
< Connection: close
< Etag: 8sKBsnMc5tH71U67xjQTCQ
< Pragma: public
< Cache-Control: max-age=5
< Content-Disposition: attachment
<
* Closing connection
program end.

下载的文件内容保存在以下代码绑定的文件中了:

		//设定HTTP响应的处理方法curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)fp);

PROPPATCH方法

PROPPATCH方法用于修改文件的属性。
WebDav方法的HTTP Body是XML格式,前面尝试的几个请求都没有添加Body。
PROPPATCH需要在Body中添加需要修改的属性指令。

以刚才PUT的文件Upload_test.txt为目标,把它的<d:displayname>修改为Upload_test_1.txt。
但是没有效果,坚果云给的响应中消息中,也没有显示失败信息。

我咨询了坚果云的客服,客服联系技术给出了回复,目前坚果云不支持PROPPATCH方法
因此,无法验证我的代码是否正确,但是还是记录一下代码,期待以后有机会验证。

代码:

int My_PROPPATCH()
{const char* url = "https://dav.jianguoyun.com/dav/box1/Upload_test.txt";CURL* curl = curl_easy_init();if (curl) {//设置HTTP头		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PROPPATCH"); //修改HTTP方法curl_easy_setopt(curl, CURLOPT_URL, url); //设置URL		curl_easy_setopt(curl, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_1_1); //指定HTTP版本curl_easy_setopt(curl, CURLOPT_USERNAME, "2802037124@qq.com"); //设置访问WebDav账号和密码curl_easy_setopt(curl, CURLOPT_PASSWORD, "axs5pyhc2j6n7qtz");struct curl_slist* list = NULL; //设置HTTP头部字段//list = curl_slist_append(list, "Connection: close"); //不要长连接list = curl_slist_append(list, "Accept: */*");list = curl_slist_append(list, "Content-Type:application/xml; charset= 'utf-8'");curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list);//指定用于SSL证书验证的证书CURLcode err = curl_easy_setopt(curl, CURLOPT_CAINFO, "D:\\SourceCode\\cert\\_.jianguoyun.com.crt");if (err != CURLE_OK) {cout << "CURLOPT_CAPATH err:" << err << endl;}//如果不设置,会出现:unable to get local issuer certificate的错误//设定HTTP响应的处理方法curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)fp);//设定控制台回显调试信息curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);//使用TinyXML库,添加Http BodyTiXmlDocument* tinyXmlDoc = new TiXmlDocument();TiXmlDeclaration* tinyXmlDeclare = new TiXmlDeclaration("1.0", "utf-8", "");  // xml的声明tinyXmlDoc->LinkEndChild(tinyXmlDeclare);TiXmlElement* Library = new TiXmlElement("D:propertyupdate");Library->SetAttribute(" xmlns:D", "DAV");Library->SetAttribute(" xmlns:S", "http://ns.jianguoyun.com");tinyXmlDoc->LinkEndChild(Library);	TiXmlElement* Set = new TiXmlElement("D:set");Library->LinkEndChild(Set);TiXmlElement* Prop = new TiXmlElement("D:prop");Set->LinkEndChild(Prop);TiXmlElement* Displayname2 = new TiXmlElement("S:publish");TiXmlText* newname = new TiXmlText("Upload_test_1.txt");	Displayname2->LinkEndChild(newname);	Prop->LinkEndChild(Displayname2);TiXmlPrinter printer;tinyXmlDoc->Accept(&printer);printf("%s\n", printer.CStr());char body[1024] = { 0x00 };strcpy_s(body, (rsize_t)1024, printer.CStr());curl_off_t size = strlen(body);curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_cb_patch); //设置读取文件的回调函数curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); //启动Upload服务curl_easy_setopt(curl, CURLOPT_READDATA, body);//设置传入回调函数的文件句柄curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)size);//设置文件大小//执行HTTP请求CURLcode ret = curl_easy_perform(curl);if (ret != CURLE_OK) {curl_easy_cleanup(curl);/*fclose(fp);*/return ERROR2("curl_easy_perform", ret);}}else {//fclose(fp);return ERROR("curl_easy_init");}//fclose(fp);curl_easy_cleanup(curl);return 0;
}

控制台回显:

> PROPPATCH /dav/box1/Upload_test.txt HTTP/1.1
Host: dav.jianguoyun.com
Authorization: Basic MjgwMjAzNzEyNEBxcS5jb206YXhzNXB5aGMyajZuN3F0eg==
Accept: */*
Content-Type:application/xml; charset= 'utf-8'
Content-Length: 243* We are completely uploaded and fine
< HTTP/1.1 207 Multi-Status
< Server: nginx
< Date: Mon, 19 Feb 2024 09:23:56 GMT
< Content-Type: text/xml; charset=UTF-8
< Content-Length: 524
< Connection: keep-alive
< Keep-Alive: timeout=60
< Pragma: no-cache
< Cache-Control: no-cache

Response的正文:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<d:multistatus xmlns:d="DAV:" xmlns:s="http://ns.jianguoyun.com">
<d:response>
<d:href>/dav/box1/Upload_test.txt</d:href>
<d:propstat>
<d:prop>
<m:Win32LastModifiedTime xmlns:m="urn:schemas-microsoft-com:"/>
<m:Win32FileAttributes xmlns:m="urn:schemas-microsoft-com:"/>
<m:Win32CreationTime xmlns:m="urn:schemas-microsoft-com:"/>
<m:Win32LastAccessTime xmlns:m="urn:schemas-microsoft-com:"/>
</d:prop><d:status>HTTP/1.1 200 OK</d:status>
</d:propstat></d:response></d:multistatus>

WebDav缓存

在上面的PROPFIND等请求的响应头中,能看到以下字段:

< Etag: 8sKBsnMc5tH71U67xjQTCQ
< Cache-Control: max-age=5

Cache-Control

Cache-Control: max-age=5 就是控制缓存的过期时间,这里是5秒后缓存过期。

Cache-Control也可以用来设置缓存类型,Cache-Control: private //私有缓存
Cache-Control: public //贡献缓存。

Etag

他们是用于HTTP缓存控制的字段。

Etag响应头,是HTTP中资源的特定版本标识符。
Etag相当于资源的指纹, URL 中的资源更改了,就一定要生成新的 ETag 值。
Etag由服务器生成,在客户端请求资源时通过Etag响应头发给客户端。

客户端下次请求同一个资源时,如果资源已经过期,客户端请求通过If-None-Match请求头,把Etag的值发给服务器,服务器可以通过If-None-Match的值,判断资源是否已经改变(这个过程叫做重新验证)。如果客户端的If-None-Match和服务器资源当前的Etag一致,服务器就不需要发送完整数据了,返回一个 304 Not Modified 状态即可。

测试

首先我用PROPFIND获取了WebDav中,一个文件的属性,它的Etag是:

<d:getetag>uLR1Dl0O-2f8uVxiMCSTGQ</d:getetag>

我在GET方法的请求头中,添加了If-None_Match字段,值就是刚才获取的文件Etag。

list = curl_slist_append(list, "If-None-Match: uLR1Dl0O-2f8uVxiMCSTGQ");

发送GET方法请求后,服务器返回304 Not Modified,即文件没有变动,无需重新获取数据。
在这里插入图片描述

强制重新验证

如果服务器想要客户端在资源没有过期的时候,也要获取最新的资源。
可以在 存在Etag或者Last-Modified头的同时,指定Cache-Control: no-cache或Cache-Control: max-age=0, must-revalidate

不需要缓存

指定Cache-Control: no-cache

GET、HEAD、OPTIONS 方法是幂等的,不会改变服务器资源的状态,是可以缓存的。
其余的方法是不建议缓存,或者不可以缓存的。

完整的缓存控制可以参考:【HTTP完全注解】看了还搞不懂缓存你直接来打我

WebDav的锁

WebDav 规范中存在排他锁、共享锁。
WebDav规范中只规定了写入锁(Write),不同的服务器可能实现了不同类型的锁。
在不同的服务器中,可能不支持锁,或者支持一种锁,或者支持多种锁。

WebDav中的每一个锁都会生成一个锁令牌(lock token),在对被锁住的对象进行操作室,HTTP头必须提交锁令牌信息。

有LOCK和UNLOCK方法来进行枷锁和解锁。

WebDav的状态码

WebDav扩展了以下状态码:
207:多状态,查看响应正文来获取详细状态。
422:请求URL存在,但是请求正文的XML内容不正确
423:请求的文件对象已被锁定
424:依赖失败,比如PROPPATCH中的一个属性修改命令失败,其余的命令也会失败。
507:服务器暂时无法提供存储空间

WebDav身份验证

通过TLS确保Basic验证信息安全。

WebDav版本控制

TODO.
参考:Versioning Extensions to WebDAV

WebDav和FTP的区别

WebDav提供了缓存功能,FTP没有;
WebDav一般通过HTTPS的443端口通信,FTP需要用20和21端口通信。
WebDav提供了锁,FTP没有。

参考

WebDAV Resources
WebDAV 规范文档
WebDAV 规范文档-Gitee
学习WebDav
如何在Zotero中设置webdav连接到坚果云?
【HTTP完全注解】看了还搞不懂缓存你直接来打我
http 三种认证方式 Basic Session Token 简介
Versioning Extensions to WebDAV

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/696701.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

思考:如何写出让同事难以维护的代码?

本文从【程序命名&注释】【数据类型&类&对象】【控制执行流程】和【程序/结构设计】四个方面梳理了一些真实案例&#xff0c;相信通过这些案例你能迅速get技能&#xff1a;如何写出让同事难以维护的代码doge。 比起什么程序员删库跑路&#xff0c;我更喜欢「写出让…

高校学科竞赛平台|基于springboot高校学科竞赛平台设计与实现(源码+数据库+文档)

高校学科竞赛平台目录 目录 基于springboot高校学科竞赛平台设计与实现 一、前言 二、系统功能设计 三、系统实现 1、竞赛题库管理 2、竞赛信息管理 3、晋级名单管理 4、往年成绩管理 5、参赛申请管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最…

Flask框架:用Python打造精巧而强大的Web应用

在当今数字化时代&#xff0c;Web应用的需求不断增长&#xff0c;而对于开发者来说&#xff0c;选择一个适合的框架来构建Web应用是至关重要的。Flask框架作为一个简洁而灵活的Python微型框架&#xff0c;以其优雅的设计和丰富的可扩展性&#xff0c;为开发者提供了一个强大而精…

HAT论文详解:Activating More Pixels in Image Super-Resolution Transformer

code&#xff1a;https://github.com/XPixelGroup/HAT paper: https://arxiv.org/abs/2309.05239 1. 概述 本文是对Swinir的改进&#xff0c;目前很多图像超分Benchmark的SOTA。相对于SwinIR的改进主要有三个地方&#xff1a;1. 引入Channel Attention,以获得更好的全局能力&…

通过OCR实现纯数字识别

基于飞浆paddle训练框架 照这个改的 https://www.paddlepaddle.org.cn/documentation/docs/zh/practices/cv/image_ocr.html 训练不到10分钟 10epoch cpu&#xff1a;inter i5 8250 U 脚本生成的图10000 验证训练&#xff1a;3:7 预测结果 chatgpt写的代码&#xff0c;生成数…

PLC_博图系列☞基本指令“异或“运算

PLC_博图系列☞基本指令“异或“运算 文章目录 PLC_博图系列☞基本指令“异或“运算背景介绍X&#xff1a;“异或”运算说明参数示例真值表 关键字&#xff1a; PLC、 西门子、 博图、 Siemens 、 异或 背景介绍 这是一篇关于PLC编程的文章&#xff0c;特别是关于西门子的…

shell脚本实现Mysql分库分表备份

一.数据库的分库分表&#xff1f; 12张图把分库分表讲的明明白白&#xff01;阿里面试&#xff1a;我们为什么要分库分表https://mp.weixin.qq.com/s?__bizMzU0OTE4MzYzMw&mid2247547792&idx2&sn91a10823ceab0cb9db26e22783343deb&chksmfbb1b26eccc63b784879…

PCIE1—快速实现PCIE接口上下位机通信(一)

1.简介 PCI Express&#xff08;PCIE&#xff09;是一种高速串行总线标准&#xff0c;广泛应用于计算机系统中&#xff0c;用于连接主板和外部设备。在FPGA领域中&#xff0c;PCIE也被广泛应用于实现高速数据传输和通信。FPGA是一种灵活可编程的集成电路&#xff0c;可以根据需…

猫头虎分享已解决Bug || Web服务故障:WebServiceUnavailable, HTTPServerError

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

ubuntu常见配置

ubuntu各个版本的安装过程大差小不差&#xff0c;可以参考&#xff0c;ubuntu20.04 其它版本换一下镜像版本即可 安装之后需要配置基本的环境&#xff0c;我的话大概就以下内容&#xff0c;后续可能有所删改 sudo apt-get update sudo apt-get install gcc sudo apt-get inst…

vulnhub靶场之Deathnote

一.环境搭建 1.靶场描述 Level - easy Description : dont waste too much time thinking outside the box . It is a Straight forward box . This works better with VirtualBox rather than VMware 2.靶场下载 https://www.vulnhub.com/entry/deathnote-1,739/ 3.启动环…

网络安全“降本增笑”的三大帮手

在网络安全这个快速变化和危机四伏的领域中&#xff0c;通过使用正确的工具和方法&#xff0c;我们可以在工作中取得更高的效率&#xff0c;并降低相关成本。 雷池社区版 雷池社区版—开源Web应用防火墙。这款产品凭借强大的规则引擎&#xff0c;它允许用户自定义安全策略&…

洛谷p1002过河卒

[NOIP2002 普及组] 过河卒 题目描述 棋盘上 A A A 点有一个过河卒&#xff0c;需要走到目标 B B B 点。卒行走的规则&#xff1a;可以向下、或者向右。同时在棋盘上 C C C 点有一个对方的马&#xff0c;该马所在的点和所有跳跃一步可达的点称为对方马的控制点。因此称之为…

三防平板丨三防工业平板电脑丨三防平板电脑有哪些优势?

三防平板电脑通常使用特殊材料和制造工艺来达到防水、防尘、防摔的目的&#xff0c;这样可以在极端条件下使用&#xff0c;并保证设备的稳定性和可靠性。因此&#xff0c;三防平板电脑适用于各种恶劣环境&#xff0c;如户外野营、物流、工业制造等应用场景。那么相比于普通消费…

Pregnostic®–PE IIp ELISA,用于测量人源ESM-1水平

Pregnostic PE Pregnostic是由IQ Products公司开发的重点关注女性健康的产品线。其中的Pregnostic -PE项目&#xff0c;旨在开发有助于筛查孕期先兆子痫风险的产品&#xff0c;可用于区分早发性和晚发性先兆子痫。 ESM-1 内皮细胞特异性分子&#xff08;ESM-1&#xff09;&am…

BabylonJS 6.0文档 Deep Dive 动画(一):动画介绍

1. 动画介绍 无论动画如何实现&#xff0c;它都必须考虑所需的动作、时间、产生所需流动性所需的帧数以及序列中的关键点。这个介绍应该有助于理解Babylon.js是如何进行动画的&#xff0c;以及它们是如何实现的。 动画由一系列图像、帧生成&#xff0c;这些图像、帧一个接一个地…

【Spring底层原理高级进阶】基于Spring Boot和Spring WebFlux的实时推荐系统的核心:响应式编程与 WebFlux 的颠覆性变革

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《Spring 狂野之旅&#xff1a;底层原理高级进阶》 &#x1f680…

QT_day2

1.思维导图 2.使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff…

幻兽帕鲁1.4.1单机畅玩教程

文章目录 游戏简介游戏背景游戏玩法资源安装和配置教程游戏包的下载和安装Steam客户端下载和配置 毕业存档使用教程第一步&#xff1a;个人存档备份第二步&#xff1a;毕业存档导入 游戏简介 Palworld&#xff1a;一款由日本独立游戏工作室Pocketpair制作发行的动作角色扮演游…

LaunchPad 市场的复苏,Penpad 成新兴生力军

以 Fair Launch 为主要启动方式的铭文市场的爆发&#xff0c;推动了 LaunchPad 市场的复苏&#xff0c;绝多数所铭文项目都能通过 Fairr Launch 的方式筹集资金实现启动&#xff0c;该赛道的爆发不仅推动了数百亿美元的热钱开始在链上不断涌动&#xff0c;同时也进一步形成了新…