#1966 closed defect (duplicate)

MKCOL refuses creation without trailing slash

Reported by: chrysn Owned by:
Priority: minor Milestone:
Component: nginx-module Version: 1.16.x
Keywords: webdav Cc: chrysn
uname -a: Linux poseidon-sid 4.19.0-0.bpo.8-amd64 #1 SMP Debian 4.19.98-1~bpo9+1 (2020-03-09) x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.16.1
built with OpenSSL 1.1.1d 10 Sep 2019 (running with OpenSSL 1.1.1g 21 Apr 2020)
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-RdAWlx/nginx-1.16.1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_flv_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_mp4_module --with-http_perl_module=dynamic --with-http_random_index_module --with-http_secure_link_module --with-http_sub_module --with-http_xslt_module=dynamic --with-mail=dynamic --with-mail_ssl_module --with-stream=dynamic --with-stream_ssl_module --with-stream_ssl_preread_module --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-headers-more-filter --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-auth-pam --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-cache-purge --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-dav-ext --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-ndk --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-echo --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-fancyindex --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/nchan --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-lua --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/rtmp --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-uploadprogress --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-upstream-fair --add-dynamic-module=/build/nginx-RdAWlx/nginx-1.16.1/debian/modules/http-subs-filter


Some WebDAV clients that create collections do that without including the trailing slash. The logs offer no further explanation, and to a casual user the 409 error is confusing (as it indicates that the parent collection is absent).

RFC4918 recommends them to have a trailing slash, but given that several applications don't send a trailing slash, it stands to reason that it's common for servers to accept it. Section 5.2 even gives concrete guidance that in such a case, the server should accept and send a Content-Location header ("There is a standing convention").

Example clients that don't are webdav-js (https://github.com/dom111/webdav-js) and Stratospherix FileBrowser for Business; some examples are around for other clients that employ workarounds (eg. https://github.com/laurent22/joplin/issues/523).

Change History (3)

comment:1 by Maxim Dounin, 18 months ago

This was previously discussed in #604 (mostly in Russian, unfortunately).

Section 5.2 says:

   There is a standing convention that when a collection is referred to
   by its name without a trailing slash, the server MAY handle the
   request as if the trailing slash were present. 

That is, the server MAY handle it as if the trailing slash were present. It is, however, not required to. And this is not what nginx normally does: for example, for normal GET requests it used to return a redirect instead. That is, clearly nginx does not follow this convention.

Clients not using trailing "/", in contrast, are violating the SHOULD clause in the same paragraph:

   In general, clients SHOULD use the trailing slash form of
   collection names.  If clients do not use the trailing slash form the
   client needs to be prepared to see a redirect response.

It is believed that returning a redirect to MKCOL requests without a trailing "/" might not be a good idea, hence the error is returned. We can consider, however, returning a redirect instead if the affected clients are known to handle redirects.

If you think that 409 is confusing here, feel free to suggest a better code. I don't think there is one which fits significantly better though.

comment:2 by chrysn, 18 months ago

If nginx wants to be strict here I'm perfectly fine with it and appreciate it. Then I can refer problematic client implementations to the SHOULD and tell them that there *are* widespread servers out there that insist.

For error codes, I'd suggest 405 on MKCOL-without-slash (as PUT would be acceptable where MKCOL isn't), and 404 for DELETE-without-slash on a collection (as a resource with that precise name does not exist).

Either way, I'm no expert in those methods and the suitable codes can be discussed a lot and still not help users. It would help if a clarifying text like "Path does not describe a collection" would be shown somewhere in those two cases, but it appears to me that neither the log format (which only logs codes) nor the error pages (which are generated solely on the code) is a viable candidate there.

comment:3 by Maxim Dounin, 18 months ago

Resolution: duplicate
Status: newclosed

Ok, thanks for your feedback. The clarifying text is available in the error log, and can be seen by the server administrator.

404 looks completely wrong to me, as certainly there is a resource available with the name requested - the one which returns a redirect. 405 might be indeed a better option, though I don't think it worth the change.

Either way, the only real solution is to fix clients which break the SHOULD.

Closing this as a duplicate of #604.

Note: See TracTickets for help on using tickets.