1<?php 2 3namespace Sabre\DAV; 4 5use Sabre\DAVServerTest; 6use Sabre\HTTP; 7 8/** 9 * Tests related to the PUT request. 10 * 11 * @copyright Copyright (C) 2007-2015 fruux GmbH (https://fruux.com/). 12 * @author Evert Pot (http://evertpot.com/) 13 * @license http://sabre.io/license/ Modified BSD License 14 */ 15class HttpPutTest extends DAVServerTest { 16 17 /** 18 * Sets up the DAV tree. 19 * 20 * @return void 21 */ 22 function setUpTree() { 23 24 $this->tree = new Mock\Collection('root', [ 25 'file1' => 'foo', 26 ]); 27 28 } 29 30 /** 31 * A successful PUT of a new file. 32 */ 33 function testPut() { 34 35 $request = new HTTP\Request('PUT', '/file2', [], 'hello'); 36 37 $response = $this->request($request); 38 39 $this->assertEquals(201, $response->getStatus(), 'Incorrect status code received. Full response body:' . $response->getBodyAsString()); 40 41 $this->assertEquals( 42 'hello', 43 $this->server->tree->getNodeForPath('file2')->get() 44 ); 45 46 $this->assertEquals( 47 [ 48 'X-Sabre-Version' => [Version::VERSION], 49 'Content-Length' => ['0'], 50 'ETag' => ['"' . md5('hello') . '"'] 51 ], 52 $response->getHeaders() 53 ); 54 55 } 56 57 /** 58 * A successful PUT on an existing file. 59 * 60 * @depends testPut 61 */ 62 function testPutExisting() { 63 64 $request = new HTTP\Request('PUT', '/file1', [], 'bar'); 65 66 $response = $this->request($request); 67 68 $this->assertEquals(204, $response->getStatus()); 69 70 $this->assertEquals( 71 'bar', 72 $this->server->tree->getNodeForPath('file1')->get() 73 ); 74 75 $this->assertEquals( 76 [ 77 'X-Sabre-Version' => [Version::VERSION], 78 'Content-Length' => ['0'], 79 'ETag' => ['"' . md5('bar') . '"'] 80 ], 81 $response->getHeaders() 82 ); 83 84 } 85 86 /** 87 * PUT on existing file with If-Match: * 88 * 89 * @depends testPutExisting 90 */ 91 function testPutExistingIfMatchStar() { 92 93 $request = new HTTP\Request( 94 'PUT', 95 '/file1', 96 ['If-Match' => '*'], 97 'hello' 98 ); 99 100 $response = $this->request($request); 101 102 $this->assertEquals(204, $response->getStatus()); 103 104 $this->assertEquals( 105 'hello', 106 $this->server->tree->getNodeForPath('file1')->get() 107 ); 108 109 $this->assertEquals( 110 [ 111 'X-Sabre-Version' => [Version::VERSION], 112 'Content-Length' => ['0'], 113 'ETag' => ['"' . md5('hello') . '"'] 114 ], 115 $response->getHeaders() 116 ); 117 118 } 119 120 /** 121 * PUT on existing file with If-Match: with a correct etag 122 * 123 * @depends testPutExisting 124 */ 125 function testPutExistingIfMatchCorrect() { 126 127 $request = new HTTP\Request( 128 'PUT', 129 '/file1', 130 ['If-Match' => '"' . md5('foo') . '"'], 131 'hello' 132 ); 133 134 $response = $this->request($request); 135 136 $this->assertEquals(204, $response->status); 137 138 $this->assertEquals( 139 'hello', 140 $this->server->tree->getNodeForPath('file1')->get() 141 ); 142 143 $this->assertEquals( 144 [ 145 'X-Sabre-Version' => [Version::VERSION], 146 'Content-Length' => ['0'], 147 'ETag' => ['"' . md5('hello') . '"'], 148 ], 149 $response->getHeaders() 150 ); 151 152 } 153 154 /** 155 * PUT with Content-Range should be rejected. 156 * 157 * @depends testPut 158 */ 159 function testPutContentRange() { 160 161 $request = new HTTP\Request( 162 'PUT', 163 '/file2', 164 ['Content-Range' => 'bytes/100-200'], 165 'hello' 166 ); 167 168 $response = $this->request($request); 169 $this->assertEquals(400, $response->getStatus()); 170 171 } 172 173 /** 174 * PUT on non-existing file with If-None-Match: * should work. 175 * 176 * @depends testPut 177 */ 178 function testPutIfNoneMatchStar() { 179 180 $request = new HTTP\Request( 181 'PUT', 182 '/file2', 183 ['If-None-Match' => '*'], 184 'hello' 185 ); 186 187 $response = $this->request($request); 188 189 $this->assertEquals(201, $response->getStatus()); 190 191 $this->assertEquals( 192 'hello', 193 $this->server->tree->getNodeForPath('file2')->get() 194 ); 195 196 $this->assertEquals( 197 [ 198 'X-Sabre-Version' => [Version::VERSION], 199 'Content-Length' => ['0'], 200 'ETag' => ['"' . md5('hello') . '"'] 201 ], 202 $response->getHeaders() 203 ); 204 205 } 206 207 /** 208 * PUT on non-existing file with If-Match: * should fail. 209 * 210 * @depends testPut 211 */ 212 function testPutIfMatchStar() { 213 214 $request = new HTTP\Request( 215 'PUT', 216 '/file2', 217 ['If-Match' => '*'], 218 'hello' 219 ); 220 221 $response = $this->request($request); 222 223 $this->assertEquals(412, $response->getStatus()); 224 225 } 226 227 /** 228 * PUT on existing file with If-None-Match: * should fail. 229 * 230 * @depends testPut 231 */ 232 function testPutExistingIfNoneMatchStar() { 233 234 $request = new HTTP\Request( 235 'PUT', 236 '/file1', 237 ['If-None-Match' => '*'], 238 'hello' 239 ); 240 $request->setBody('hello'); 241 242 $response = $this->request($request); 243 244 $this->assertEquals(412, $response->getStatus()); 245 246 } 247 248 /** 249 * PUT thats created in a non-collection should be rejected. 250 * 251 * @depends testPut 252 */ 253 function testPutNoParent() { 254 255 $request = new HTTP\Request( 256 'PUT', 257 '/file1/file2', 258 [], 259 'hello' 260 ); 261 262 $response = $this->request($request); 263 $this->assertEquals(409, $response->getStatus()); 264 265 } 266 267 /** 268 * Finder may sometimes make a request, which gets its content-body 269 * stripped. We can't always prevent this from happening, but in some cases 270 * we can detected this and return an error instead. 271 * 272 * @depends testPut 273 */ 274 function testFinderPutSuccess() { 275 276 $request = new HTTP\Request( 277 'PUT', 278 '/file2', 279 ['X-Expected-Entity-Length' => '5'], 280 'hello' 281 ); 282 $response = $this->request($request); 283 284 $this->assertEquals(201, $response->getStatus()); 285 286 $this->assertEquals( 287 'hello', 288 $this->server->tree->getNodeForPath('file2')->get() 289 ); 290 291 $this->assertEquals( 292 [ 293 'X-Sabre-Version' => [Version::VERSION], 294 'Content-Length' => ['0'], 295 'ETag' => ['"' . md5('hello') . '"'], 296 ], 297 $response->getHeaders() 298 ); 299 300 } 301 302 /** 303 * Same as the last one, but in this case we're mimicing a failed request. 304 * 305 * @depends testFinderPutSuccess 306 */ 307 function testFinderPutFail() { 308 309 $request = new HTTP\Request( 310 'PUT', 311 '/file2', 312 ['X-Expected-Entity-Length' => '5'], 313 '' 314 ); 315 316 $response = $this->request($request); 317 318 $this->assertEquals(403, $response->getStatus()); 319 320 } 321 322 /** 323 * Plugins can intercept PUT. We need to make sure that works. 324 * 325 * @depends testPut 326 */ 327 function testPutIntercept() { 328 329 $this->server->on('beforeBind', function($uri) { 330 $this->server->httpResponse->setStatus(418); 331 return false; 332 }); 333 334 $request = new HTTP\Request('PUT', '/file2', [], 'hello'); 335 $response = $this->request($request); 336 337 $this->assertEquals(418, $response->getStatus(), 'Incorrect status code received. Full response body: ' .$response->getBodyAsString()); 338 339 $this->assertFalse( 340 $this->server->tree->nodeExists('file2') 341 ); 342 343 $this->assertEquals([ 344 'X-Sabre-Version' => [Version::VERSION], 345 ], $response->getHeaders()); 346 347 } 348 349} 350