Site Tools


software:nginx:webdav

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
software:nginx:webdav [2015/05/12 16:50]
– [Проблема 3] root
software:nginx:webdav [2022/02/04 18:33]
– removed - external edit (Unknown date) 127.0.0.1
Line 1: Line 1:
-====== Nginx and Microsoft Windows WebClient (WebDav) ====== 
-В Microsoft Windows начиная с 2к встроен Веб Клиент, по сути это средство для монтирования сетевых дисков по протоколу WebDav, который ходит поверх HTTP/HTTPS.\\ 
-Клиент писался явно под себя (связка с IIS) и от того работает весьма <del>коряво</del>своеобразно.\\ 
-Это единственный способ "малой" кровью примонтировать диск через интернет не настраивая VPN для проброса SAMBA протокола.\\ 
-SAMB-у в принципе тоже без VPN можно пробросить, но это из области поиска приключений с последствиями.\\ 
- 
-Nginx в базовом функционале имеет не полную поддержку WebDav: PUT DELETE MKCOL COPY MOVE.\\ 
-Расширить его ещё двумя: PROPFIND и OPTIONS можно с помощью плагина: <a href="https://github.com/arut/nginx-dav-ext-module">dav-ext</a>\\ 
- 
- 
-Для работы потребуется Nginx собранный с поддержкой WebDav, dav-ext модулем и rewrite.\\ 
-<code>[x] HTTP_DAV              Enable http_webdav module 
-[x] HTTP_DAV_EXT          3rd party webdav_ext module 
-[x] HTTP_REWRITE          Enable http_rewrite module</code> 
- 
- 
- 
-===== Проблема 1 - Майкрософт нарушает стандарты и свои обещания ===== 
-{{:ru:software:nginx:webdav1.png|}} 
- 
-Перед тем как создать файл WebDav клиент проверяет наличие файла посылая запрос:\\ 
-<code>PROPFIND /!!!!/test.lnk HTTP/1.1 
-Connection: Keep-Alive 
-User-Agent: Microsoft-WebDAV-MiniRedir/6.1.7601 
-Depth: 0 
-translate: f 
-Content-Length: 0 
-Host: 172.16.0.254:8089</code> 
- 
-В ответ IIS ему выдаёт:\\ 
-<code>HTTP/1.1 404 Resource Not Found 
-Content-Length: 1635 
-Content-Type: text/html 
-Server: Microsoft-IIS/6.0 
-X-Powered-By: ASP.NET 
-Date: Sun, 10 Aug 2014 20:06:08 GMT 
- 
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> 
-...</code> 
- 
-Только это не правильно, должен быть код 207 и xml в котором описан элемент и код для него, те 404 должно быть в xml.\\ 
-с точки зрения стандартов: http://tools.ietf.org/html/rfc2518#page-24 \\ 
-с точки зрения доков мс: http://msdn.microsoft.com/en-us/library/aa142960(v=exchg.65).aspx \\ 
-У яндекса тоже в примерах xml: http://api.yandex.ru/disk/doc/dg/reference/propfind_property-request.xml \\ 
- 
-Ответ Nginx:\\ 
-<code>HTTP/1.1 207 Multi-Status 
-Server: nginx/1.7.4 
-Date: Sun, 10 Aug 2014 21:17:34 GMT 
-Transfer-Encoding: chunked 
-Connection: keep-alive 
-Keep-Alive: timeout=60 
- 
-47 
-<?xml version="1.0" encoding="utf-8" ?> 
-<D:multistatus xmlns:D="DAV:"> 
- 
-cc 
-<D:response> 
-<D:href>/Family/test.lnk</D:href> 
-<D:propstat> 
-<D:prop> 
-</D:prop> 
-<D:status>HTTP/1.1 404 Not Found</D:status> 
-</D:propstat> 
-</D:response> 
- 
-11 
-</D:multistatus> 
- 
-0</code> 
-Такой "неожиданный" ответ сносит голову WebDav клиенту винды.\\ 
- 
-Фиксим в конфиге (возможно это сведёт с ума остальные, порядочные WebDav клиенты, но лично мне нужен был только один не такой как все):\\ 
-**Фикс 1**: 
-<code>error_page 599 = @propfind_handler; 
-if ($request_method = PROPFIND) { 
- return 599; 
-} 
- 
-location @propfind_handler { 
- internal; 
- 
- open_file_cache off; 
- if (!-e $webdav_root/$uri) { # Microsoft specific handle. 
- return 404; 
- } 
- root $webdav_root; 
- dav_ext_methods PROPFIND; 
-}</code> 
- 
- 
- 
-===== Проблема 2 - PROPPATCH отсутствует в nginx ===== 
-{{:ru:software:nginx:webdav2.png|}} \\ 
-WebDav от мс очень хочет метод PROPPATCH, которого в Nginx и расширениях нет. Совсем нет.\\ 
-Я рассматривал два варианта решения:\\ 
-1. Написать плагин к Nginx или патч к dav-ext, короче Си код и пересборка Nginx.\\ 
-2. Положится на кривость виндовой реализации WebDav и скормить статический ответ.\\ 
- 
-Запрос:\\ 
-<code>PROPPATCH /Family/test.lnk HTTP/1.1 
-Cache-Control: no-cache 
-Connection: Keep-Alive 
-Pragma: no-cache 
-Content-Type: text/xml; charset="utf-8" 
-User-Agent: Microsoft-WebDAV-MiniRedir/6.1.7601 
-translate: f 
-Content-Length: 443 
-Host: xxx.xxx.net 
- 
-<?xml version="1.0" encoding="utf-8" ?><D:propertyupdate xmlns:D="DAV:" xmlns:Z="urn:schemas-microsoft-com:"><D:set><D:prop><Z:Win32CreationTime>Sun, 10 Aug 2014 21:30:21 GMT</Z:Win32CreationTime><Z:Win32LastAccessTime>Sun, 10 Aug 2014 21:30:22 GMT</Z:Win32LastAccessTime><Z:Win32LastModifiedTime>Sun, 10 Aug 2014 21:30:22 GMT</Z:Win32LastModifiedTime><Z:Win32FileAttributes>00000020</Z:Win32FileAttributes></D:prop></D:set></D:propertyupdate></pre></spoiler> 
- 
-<spoiler title="Ответ IIS"><pre>HTTP/1.1 207 Multi-Status 
-Date: Sun, 10 Aug 2014 12:24:47 GMT 
-Server: Microsoft-IIS/6.0 
-X-Powered-By: ASP.NET 
-Content-Type: text/xml 
-Transfer-Encoding: chunked 
- 
-<?xml version="1.0"?><a:multistatus xmlns:a="DAV:" xmlns:b="urn:schemas-microsoft-com:"><a:response><a:href>http://172.16.0.254:8088//!!!!/test.lnk</a:href><a:propstat><a:status>HTTP/1.1 200 OK</a:status><a:prop><b:Win32CreationTime/><b:Win32LastAccessTime/><b:Win32LastModifiedTime/><b:Win32FileAttributes/></a:prop></a:propstat></a:response></a:multistatus> 
-0</code> 
-"Пропритериарщина", - подумал я. Вот кому такое вообще надо? 
-И как эти все атрибуты писать в разных ОС и разных ФС?... 
- 
-Так появился второй фикс в конфиге: 
-Фикс 2:\\ 
-<code>if ($request_method = PROPPATCH) { # Unsupported, allways return OK. 
- add_header Content-Type 'text/xml'; 
- return 207 '<?xml version="1.0"?><a:multistatus xmlns:a="DAV:"><a:response><a:propstat><a:status>HTTP/1.1 200 OK</a:status></a:propstat></a:response></a:multistatus>'; 
-}</code> 
- 
-Из ответа IIS я выкинул всё что мне не понравилось и виндовый WebDav это проглотил.\\ 
-Теперь одиночные и группы файлов без проблем можно копировать на сетевой диск примонтированный по WebDav.\\ 
-Минусом - не выставляется оригинальная дата создания, модификации и атрибуты.\\ 
- 
- 
-===== Проблема 3 - создание папок ===== 
-{{:ru:software:nginx:webdav3.png|}} \\ 
-См п1 :) 
- 
-Приходит запрос:\\ 
-<code>MKCOL /Family/MR3020 HTTP/1.1 
-Connection: Keep-Alive 
-User-Agent: Microsoft-WebDAV-MiniRedir/6.1.7601 
-translate: f 
-Content-Length: 0 
-Host: xxx.xxx.net</code> 
- 
-Nginx на него отвечает (немного странно выбирая код, на мой взгляд, но в принципе правильно)\\ 
-Ответ:\\ 
-<code>HTTP/1.1 409 Conflict 
-Server: nginx/1.7.4 
-Date: Sun, 10 Aug 2014 21:43:15 GMT 
-Content-Type: text/html 
-Content-Length: 166 
-Connection: keep-alive 
-Keep-Alive: timeout=60 
- 
-<html> 
-<head><title>409 Conflict</title></head> 
-<body bgcolor="white"> 
-<center><h1>409 Conflict</h1></center> 
-<hr><center>nginx/1.7.4</center> 
-</body> 
-</html></code> 
- 
-IIS отвечает: "HTTP/1.1 201 Created", - смотреть там не на что.\\ 
- 
-Как должно быть описано:\\ 
-У майкрософта: http://msdn.microsoft.com/en-us/library/aa142923(v=exchg.65).aspx \\ 
-У яндекса: http://api.yandex.ru/disk/doc/dg/reference/mkcol.xml \\ 
-И даже в RFC: http://tools.ietf.org/html/rfc2518#page-33 \\ 
- 
-Во всех примерах URL оканчивается слешем. \\ 
-Но только не в запросе WebDav клиента от мс. \\ 
- 
-Вариантов опять было два: \\ 
-1. Поправить файл: http://lxr.nginx.org/source/src/http/modules/ngx_http_dav_module.c строчки 484 - 493, там как раз проверка наличия слеша и его отрезание. \\ 
-2. Пофиксить через конфиг.\\ 
- 
-Вариант 1 я оставляю на усмотрение програмеров nginx, может по стандарту оно и должно ругаться. Связываться с отсылкой патчей тоже не хотелось.\\ 
- 
-**Фикс 3**:\\ 
-<code>if ($request_method = MKCOL) { # Microsoft specific handle: add trailing slash. 
- rewrite ^(.*[^/])$ $1/; 
-}</code> 
-Вот для этого пустяка и потребовался REWRITE плагин.\\ 
- 
- 
-===== Проблема 4 - удаление папок ===== 
-Ноги тут те же что и в п3: отсутствие слеша на конце урла.\\ 
-Однако я столкнулся с тем, что nginx тоже ведёт себя несколько странно.\\ 
-1. Если слеш на конце отсутствует, то nginx считает что его просят удалить файл, и получает ошибку: 21: Is a directory при попытке удалить.\\ 
-2. Если слеш добавить то папку он почему то так и не удаляет. Подозреваю тут где то баг самого nginx.\\ 
- 
-Фикс в конфиге:\\ 
-**Фикс 4**: 
-<code>error_page 598 = @delete_handler; 
-if ($request_method = DELETE) { 
- return 598; 
-} 
- 
-location @delete_handler { 
- internal; 
- 
- open_file_cache off; 
- if (-d $webdav_root/$uri) { # Add trailing slash to dirs. 
- rewrite ^(.*[^/])$ $1/; 
- } 
- root $webdav_root; 
- dav_methods DELETE; 
-}</code> 
-Если кратко, то переносим обработку DELETE в отдельный локейшин (процедуру), дальше проверяем, если удаляется папка то добавляем слеш.\\ 
- 
- 
-===== Ещё немного о Nginx ===== 
-Не трудно заметить, что nginx не добавляет в ответы:\\ 
-<code>Content-Type: text/xml</code> 
-и хотя в данном случае это не создаёт проблем, но всё же это не правильно.\\ 
- 
-Это уже третий раз когда гибкость nginx позволила мне получить результат не используя языки программирования, Игорь - молодец!\\ 
-Прошлые разы я сделал кешируюший прокси с фильтрацией по урл и UPnP/DLNA сервер.\\ 
- 
- 
- 
-===== Конфиг nginx для WebDav ===== 
-WebDav для Nginx:\\ 
-<code># WebDAV 
-set $webdav_root "/mnt/WebDav_folder"; 
-location ^~ /Family { 
- 
- root $webdav_root; 
- error_page 599 = @propfind_handler; 
- error_page 598 = @delete_handler; 
- chunked_transfer_encoding on; 
- open_file_cache off; 
- client_max_body_size 50m; 
- add_header Allow 'OPTIONS, GET, HEAD, DELETE, PUT, COPY, MOVE, PROPFIND'; 
- 
- if ($request_method = PROPFIND) { 
- return 599; 
- } 
- if ($request_method = PROPPATCH) { # Unsupported, allways return OK. 
- add_header Content-Type 'text/xml'; 
- return 207 '<?xml version="1.0"?><a:multistatus xmlns:a="DAV:"><a:response><a:propstat><a:status>HTTP/1.1 200 OK</a:status></a:propstat></a:response></a:multistatus>'; 
- } 
- if ($request_method = MKCOL) { # Microsoft specific handle: add trailing slash. 
- rewrite ^(.*[^/])$ $1/; 
- } 
- if ($request_method = DELETE) { 
- return 598; 
- } 
- 
- dav_methods PUT MKCOL COPY MOVE; # 
- dav_ext_methods OPTIONS; 
- create_full_put_path on; 
- min_delete_depth 0; 
- dav_access user:rw group:rw all:rw; 
-} 
-location @propfind_handler { 
- internal; 
- 
- open_file_cache off; 
- if (!-e $webdav_root/$uri) { # Microsoft specific handle. 
- return 404; 
- } 
- root $webdav_root; 
- dav_ext_methods PROPFIND; 
-} 
-location @delete_handler { 
- internal; 
- 
- open_file_cache off; 
- if (-d $webdav_root/$uri) { # Add trailing slash to dirs. 
- rewrite ^(.*[^/])$ $1/; 
- } 
- root $webdav_root; 
- dav_methods DELETE; 
-}</code> 
- 
-open_file_cache off; - нужно потому что мы меняем файлы, если кеширование включено то можно будет долго гадать почему не видно файлы которые мы только что закинули на сервер.\\ 
- 
- 
-===== Немного о настройке клиента ===== 
-Он как капризный ребёнок, из коробки ему подавай SSL и никакой Basic аутентификации, файлы не больше 50 мегабайт, в папках не более 500-1000 файлов.\\ 
-Увы, но даже после всего файлы более 4гб передавать не получится. (Скорее всего из за кривой реализации, которая файлы при открытии скачивает в память/на диск чтобы получить более менее стандартный файловый дискриптор, это мои домыслы.)\\ 
- 
-Вот здесь собраны все настройки с описанием: http://blogs.msdn.com/b/robert_mcmurray/archive/2008/01/17/webdav-redirector-registry-settings.aspx \\ 
- 
-На данный момент мои настройки WebClient выглядят так:\\ 
-<code>Windows Registry Editor Version 5.00 
- 
-[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\WebClient\Parameters] 
-"SupportLocking"=dword:00000000 
-"InternetServerTimeoutInSec"=dword:0000001e 
-"ServiceDllUnloadOnStop"=dword:00000001 
-"ServerNotFoundCacheLifeTimeInSec"=dword:0000000a 
-"ClientDebug"=dword:00000000 
-"FileSizeLimitInBytes"=dword:ffffffff 
-"SendReceiveTimeoutInSec"=dword:0000003c 
-"LocalServerTimeoutInSec"=dword:0000000f 
-"FileAttributesLimitInBytes"=dword:00989680 
-"AcceptOfficeAndTahoeServers"=dword:00000001 
-"ServiceDebug"=dword:00000000 
-"BasicAuthLevel"=dword:00000002</code> 
- 
  
software/nginx/webdav.txt · Last modified: 2022/02/05 04:30 by root