Upload Modules
This commit is contained in:
22
ngx_dav_ext_module/LICENSE
Normal file
22
ngx_dav_ext_module/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright (C) 2012-2018 Roman Arutyunyan
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
188
ngx_dav_ext_module/README.rst
Normal file
188
ngx_dav_ext_module/README.rst
Normal file
@@ -0,0 +1,188 @@
|
||||
********************
|
||||
nginx-dav-ext-module
|
||||
********************
|
||||
|
||||
nginx_ WebDAV_ PROPFIND,OPTIONS,LOCK,UNLOCK support.
|
||||
|
||||
.. contents::
|
||||
|
||||
|
||||
About
|
||||
=====
|
||||
|
||||
The standard ngx_http_dav_module_ provides partial WebDAV_ implementation and
|
||||
only supports GET,HEAD,PUT,DELETE,MKCOL,COPY,MOVE methods.
|
||||
|
||||
For full WebDAV_ support in nginx_ you need to enable the standard
|
||||
ngx_http_dav_module_ as well as this module for the missing methods.
|
||||
|
||||
|
||||
Build
|
||||
=====
|
||||
|
||||
Building nginx_ with the module:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# static module
|
||||
$ ./configure --with-http_dav_module --add-module=/path/to/nginx-dav-ext-module
|
||||
|
||||
# dynamic module
|
||||
$ ./configure --with-http_dav_module --add-dynamic-module=/path/to/nginx-dav-ext-module
|
||||
|
||||
Trying to compile nginx_ with this module but without ngx_http_dav_module_ will
|
||||
result in compilation error.
|
||||
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
- nginx_ version >= 1.13.4
|
||||
- ``libxml2`` + ``libxslt``
|
||||
|
||||
The ``libxslt`` library is technically redundant and is only required since this
|
||||
combination is supported by nginx_ for the xslt module.
|
||||
Using builtin nginx mechanisms for linking against third-party libraries
|
||||
brings certain compatibility benefits.
|
||||
However this redundancy can be easily eliminated in the ``config`` file.
|
||||
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
The module tests require standard nginx-tests_ and Perl ``HTTP::DAV`` library.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ export PERL5LIB=/path/to/nginx-tests/lib
|
||||
$ export TEST_NGINX_BINARY=/path/to/nginx
|
||||
$ prove t
|
||||
|
||||
|
||||
Locking
|
||||
=======
|
||||
|
||||
- Only the exclusive write locks are supported, which is the only type of locks
|
||||
described in the WebDAV_ specification.
|
||||
|
||||
- All currently held locks are kept in a list.
|
||||
Checking if an object is constrained by a lock requires O(n) operations.
|
||||
A huge number of simultaneously held locks may degrade performance.
|
||||
Thus it is not recommended to have a large lock timeout which would increase
|
||||
the number of locks.
|
||||
|
||||
|
||||
Directives
|
||||
==========
|
||||
|
||||
dav_ext_methods
|
||||
---------------
|
||||
|
||||
========== ====
|
||||
*Syntax:* ``dav_ext_methods [PROPFIND] [OPTIONS] [LOCK] [UNLOCK]``
|
||||
*Context:* http, server, location
|
||||
========== ====
|
||||
|
||||
Enables support for the specified WebDAV methods in the current scope.
|
||||
|
||||
dav_ext_lock_zone
|
||||
-----------------
|
||||
|
||||
========== ====
|
||||
*Syntax:* ``dav_ext_lock_zone zone=NAME:SIZE [timeout=TIMEOUT]``
|
||||
*Context:* http
|
||||
========== ====
|
||||
|
||||
Defines a shared zone for WebDAV locks with specified NAME and SIZE.
|
||||
Also, defines a lock expiration TIMEOUT.
|
||||
Default lock timeout value is 1 minute.
|
||||
|
||||
|
||||
dav_ext_lock
|
||||
------------
|
||||
|
||||
========== ====
|
||||
*Syntax:* ``dav_ext_lock zone=NAME``
|
||||
*Context:* http, server, location
|
||||
========== ====
|
||||
|
||||
Enables WebDAV locking in the specified scope.
|
||||
Locks are stored in the shared zone specified by NAME.
|
||||
This zone must be defined with the ``dav_ext_lock_zone`` directive.
|
||||
|
||||
Note that even though this directive enables locking capabilities in the
|
||||
current scope, HTTP methods LOCK and UNLOCK should also be explicitly specified
|
||||
in the ``dav_ext_methods``.
|
||||
|
||||
|
||||
Example 1
|
||||
=========
|
||||
|
||||
Simple lockless example::
|
||||
|
||||
location / {
|
||||
root /data/www;
|
||||
|
||||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||||
dav_ext_methods PROPFIND OPTIONS;
|
||||
}
|
||||
|
||||
|
||||
Example 2
|
||||
=========
|
||||
|
||||
WebDAV with locking::
|
||||
|
||||
http {
|
||||
dav_ext_lock_zone zone=foo:10m;
|
||||
|
||||
...
|
||||
|
||||
server {
|
||||
...
|
||||
|
||||
location / {
|
||||
root /data/www;
|
||||
|
||||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||||
dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
|
||||
dav_ext_lock zone=foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Example 3
|
||||
=========
|
||||
|
||||
WebDAV with locking which works with MacOS client::
|
||||
|
||||
http {
|
||||
dav_ext_lock_zone zone=foo:10m;
|
||||
|
||||
...
|
||||
|
||||
server {
|
||||
...
|
||||
|
||||
location / {
|
||||
root /data/www;
|
||||
|
||||
# enable creating directories without trailing slash
|
||||
set $x $uri$request_method;
|
||||
if ($x ~ [^/]MKCOL$) {
|
||||
rewrite ^(.*)$ $1/;
|
||||
}
|
||||
|
||||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||||
dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
|
||||
dav_ext_lock zone=foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.. _ngx_http_dav_module: http://nginx.org/en/docs/http/ngx_http_dav_module.html
|
||||
.. _nginx-tests: http://hg.nginx.org/nginx-tests
|
||||
.. _nginx: http://nginx.org
|
||||
.. _WebDAV: https://tools.ietf.org/html/rfc4918
|
||||
.. _`RFC4918 If Header`: https://tools.ietf.org/html/rfc4918#section-10.4
|
||||
17
ngx_dav_ext_module/config
Normal file
17
ngx_dav_ext_module/config
Normal file
@@ -0,0 +1,17 @@
|
||||
ngx_addon_name=ngx_http_dav_ext_module
|
||||
|
||||
ngx_module_type=HTTP
|
||||
ngx_module_name=ngx_http_dav_ext_module
|
||||
|
||||
# nginx has robust builtin support for linking against
|
||||
# libxml2+libxslt. This is definitelty the right way to go if
|
||||
# building nginx with the xslt module, in which case libxslt will
|
||||
# be linked anyway. In other cases libxslt is just redundant.
|
||||
# If that's a big deal, libxml2 can be linked directly:
|
||||
# ngx_module_libs=-lxml2
|
||||
|
||||
ngx_module_libs=LIBXSLT
|
||||
|
||||
ngx_module_srcs="$ngx_addon_dir/ngx_http_dav_ext_module.c"
|
||||
|
||||
. auto/module
|
||||
2181
ngx_dav_ext_module/ngx_http_dav_ext_module.c
Normal file
2181
ngx_dav_ext_module/ngx_http_dav_ext_module.c
Normal file
File diff suppressed because it is too large
Load Diff
141
ngx_dav_ext_module/t/dav_ext.t
Normal file
141
ngx_dav_ext_module/t/dav_ext.t
Normal file
@@ -0,0 +1,141 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# (C) Roman Arutyunyan
|
||||
|
||||
# Tests for nginx-dav-ext-module.
|
||||
|
||||
###############################################################################
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
use Test::More;
|
||||
|
||||
BEGIN { use FindBin; chdir($FindBin::Bin); }
|
||||
|
||||
use lib 'lib';
|
||||
use Test::Nginx;
|
||||
use HTTP::DAV
|
||||
|
||||
###############################################################################
|
||||
|
||||
select STDERR; $| = 1;
|
||||
select STDOUT; $| = 1;
|
||||
|
||||
my $t = Test::Nginx->new()->has(qw/http dav/)->plan(20);
|
||||
|
||||
$t->write_file_expand('nginx.conf', <<'EOF');
|
||||
|
||||
%%TEST_GLOBALS%%
|
||||
|
||||
daemon off;
|
||||
|
||||
events {
|
||||
}
|
||||
|
||||
http {
|
||||
%%TEST_GLOBALS_HTTP%%
|
||||
|
||||
dav_ext_lock_zone zone=foo:10m timeout=10s;
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:8080;
|
||||
server_name localhost;
|
||||
|
||||
location / {
|
||||
dav_methods PUT DELETE MKCOL COPY MOVE;
|
||||
dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
|
||||
dav_ext_lock zone=foo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EOF
|
||||
|
||||
$t->write_file('foo', 'foo');
|
||||
|
||||
$t->run();
|
||||
|
||||
###############################################################################
|
||||
|
||||
my $url = "http://127.0.0.1:8080";
|
||||
|
||||
my $content;
|
||||
|
||||
my $d = HTTP::DAV->new();
|
||||
$d->open($url);
|
||||
|
||||
my $d2 = HTTP::DAV->new();
|
||||
$d2->open($url);
|
||||
|
||||
#debug:
|
||||
#$d->DebugLevel(3);
|
||||
#see /tmp/perldav_debug.txt.
|
||||
|
||||
my $p = $d->propfind('/', 1);
|
||||
is($p->is_collection, 1, 'propfind dir collection');
|
||||
is($p->get_property('displayname'), '/', 'propfind dir displayname');
|
||||
is($p->get_uri(), 'http://127.0.0.1:8080/', 'propfind dir uri');
|
||||
|
||||
$p = $d->propfind('/foo');
|
||||
is($p->is_collection, 0, 'propfind file collection');
|
||||
is($p->get_property('displayname'), 'foo', 'propfind file displayname');
|
||||
is($p->get_uri(), 'http://127.0.0.1:8080/foo', 'propfind file uri');
|
||||
is($p->get_property('getcontentlength'), '3', 'propfind file size');
|
||||
|
||||
$d->lock('/foo');
|
||||
is($d->lock('/foo'), 0, 'prevent double lock');
|
||||
|
||||
$d->unlock('/foo');
|
||||
is($d->lock('/foo'), 1, 'relock');
|
||||
|
||||
$d->lock('/bar');
|
||||
$p = $d->propfind('/bar');
|
||||
is($p->get_property('displayname'), 'bar', 'lock creates a file');
|
||||
|
||||
$d->get('/bar', \$content) or $content = 'none';
|
||||
is($content, '', 'lock creates an empty file');
|
||||
|
||||
$content = "bar";
|
||||
$d->put(\$content, '/bar');
|
||||
$d->get('/bar', \$content) or $content = '';
|
||||
is($content, 'bar', 'put lock');
|
||||
|
||||
$content = "qux";
|
||||
$d2->put(\$content, '/bar');
|
||||
$d2->get('/bar', \$content) or $content = '';
|
||||
isnt($content, 'qux', 'prevent put lock');
|
||||
|
||||
$d->mkcol('/d/');
|
||||
$d->lock('/d/');
|
||||
$d->copy('/bar', '/d/bar');
|
||||
$d->get('/d/bar', \$content) or $content = '';
|
||||
is($content, 'bar', 'copy lock');
|
||||
|
||||
$d2->copy('/bar', '/d/qux');
|
||||
$d2->get('/d/qux', \$content) or $content = '';
|
||||
isnt($content, 'bar', 'prevent copy lock');
|
||||
|
||||
$d2->delete('/d/bar');
|
||||
$d2->get('/d/bar', \$content) or $content = '';
|
||||
is($content, 'bar', 'prevent delete lock');
|
||||
|
||||
$d->delete('/d/bar');
|
||||
$d->get('/d/bar', \$content) or $content = '';
|
||||
is($content, '', 'delete lock');
|
||||
|
||||
$d->mkcol('/d/c/');
|
||||
$p = $d->propfind('/d/c/');
|
||||
is($p->is_collection, 1, 'mkcol lock');
|
||||
|
||||
$d2->mkcol('/d/e/');
|
||||
is($d2->propfind('/d/e/'), 0, 'prevent mkcol lock');
|
||||
|
||||
$d->unlock('/d/');
|
||||
$d->lock('/d/', -depth=>"0");
|
||||
$content = 'qux';
|
||||
$d2->put(\$content, '/d/c/qux');
|
||||
$d2->get('/d/c/qux', \$content) or $content = '';
|
||||
is($content, 'qux', 'put to a depth-0-locked subdirectory');
|
||||
|
||||
###############################################################################
|
||||
Reference in New Issue
Block a user