利用Nginx架设Webdav服务并用Python的requests使用

WebDAV(Web Distributed Authoring and Versioning)是在RFC 4918中定义的一种HTTP协议的扩展,实现了Web文件的远程管理。 虽然最近一次更新,已经是2009年的事了,但它确实影响深远。 Apache httpd、Nginx等Web服务器,默认提供支持;Git、SVN等版本控制系统,在协议上深受影响。

当然,把这老古董翻出来,还是因为它自有独到之处。 基于HTTP默认的动词GET、PUT、DELETE等,它能简单实现文件的读、写、删除功能。 此外,还有扩展的动词,实现特殊的文件远程操作功能,如复制、移动、加锁等。

这些功能,可以用简单的HTTP扩展协议,实现一个远程版本控制系统。 即使是一个子集,也可以实现一个简单高效、网络共享的文件存取系统。 这在微服务架构的容器化集群中,可以起到意想不到的简化效果。

Nginx

Nginx自带的ngx_http_dav_module,就实现了WebDAV的基本文件操作功能——PUT、DELETE、MKCOL、COPY和MOVE。 而第三方的arut/nginx-dav-ext-module,则实现了加锁等高级功能——PROPFIND、OPTIONS、LOCK和UNLOCK。

使用用官方的Nginx镜像,则自带ngx_http_dav_module功能。

Nginx容器配置

version: "3"

services:
  nginx:
    image: nginx:1.14.2-alpine
    ports:
      - 8080:80
    volumes:
      - ./conf.d:/etc/nginx/conf.d:ro

Nginx配置

./conf.d/default.conf写入以下配置:

server {
    listen      80;
    listen      [::]:80;
    server_name _;

    location / {
        root    /tmp/;
        autoindex on;
        autoindex_format json;
        dav_methods  PUT DELETE MKCOL COPY MOVE;
        create_full_put_path  on;
        client_max_body_size  8M;
        allow all;
    }
}

启动服务

配置完成后,用docker-compose up -d,即可启动一个带WebDAV支持的Nginx。

示例代码

以下以curl命令和Python的[requests]为例,展示如何使用[Nginx]的webdav服务。

PUT

import os
from urllib.parse import urljoin

import requests

BASE_URL = 'http://localhost:8080'


def put(name):
    url = urljoin(BASE_URL, name)
    response = requests.put(url, data=open(name, 'rb'))
    response.raise_for_status()


if __name__ == '__main__':
    import sys
    put(sys.argv[1])

执行检查:

$ ./put.py put.py
$ curl -s localhost:8080 | jq
[
  {
    "name": "put.py",
    "type": "file",
    "mtime": "Sat, 02 Mar 2019 14:06:17 GMT",
    "size": 347
  }
]

可见put.py文件已成功上传。

./put.py put.py,相当于:

curl -X PUT -F put.py=@put.py localhost:8080/put.py

GET

def get(name):
    url = urljoin(BASE_URL, name)
    response = requests.get(url)
    response.raise_for_status()
    print(response.text)

这个函数可以获取文件内容,并打印。

curl的形式如下:

curl -X GET localhost:8080/put.py

DELETE

def delete(name):
    url = urljoin(BASE_URL, name)
    response = requests.delete(url)
    response.raise_for_status()

这个函数可以删除指定文件。

curl删除put.py的示例如下:

curl -X DELETE localhost:8080/put.py

list files

列出文件,是一个常用的浏览操作。 仍然是用GET来实现,但URL确是指向目录。

>>> import requests
>>> r = requests.get('http://localhost:8080/')
>>> r.json()
[{'mtime': 'Sat, 02 Mar 2019 07:58:12 GMT',
  'name': 'a.txt',
  'size': 6,
  'type': 'file'},
 {'mtime': 'Sat, 02 Mar 2019 07:58:20 GMT',
  'name': 'b.txt',
  'size': 7,
  'type': 'file'}]

命令行的形式如下:

$ curl -s localhost:8080 | jq
[
  {
    "name": "a.txt",
    "type": "file",
    "mtime": "Sat, 02 Mar 2019 07:58:12 GMT",
    "size": 6
  },
  {
    "name": "b.txt",
    "type": "file",
    "mtime": "Sat, 02 Mar 2019 07:58:20 GMT",
    "size": 7
  }
]

其它

此外,还有WebDAV独特的动词,需要使用[requests]的高级功能,自定义HTTP动词。 例如:

>>> r = requests.request('MKCOL', url, data=data)
>>> r.status_code
200 # Assuming your call was correct

这里不再详细介绍。

参考


相关笔记