Subversion-Projekte lars-tiefland.laravel_shop

Revision

Revision 148 | Details | Vergleich mit vorheriger | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Foundation\Testing\Concerns;
4
 
5
use Illuminate\Contracts\Http\Kernel as HttpKernel;
6
use Illuminate\Cookie\CookieValuePrefix;
7
use Illuminate\Http\Request;
8
use Illuminate\Testing\LoggedExceptionCollection;
9
use Illuminate\Testing\TestResponse;
10
use Symfony\Component\HttpFoundation\File\UploadedFile as SymfonyUploadedFile;
11
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
12
 
13
trait MakesHttpRequests
14
{
15
    /**
16
     * Additional headers for the request.
17
     *
18
     * @var array
19
     */
20
    protected $defaultHeaders = [];
21
 
22
    /**
23
     * Additional cookies for the request.
24
     *
25
     * @var array
26
     */
27
    protected $defaultCookies = [];
28
 
29
    /**
30
     * Additional cookies will not be encrypted for the request.
31
     *
32
     * @var array
33
     */
34
    protected $unencryptedCookies = [];
35
 
36
    /**
37
     * Additional server variables for the request.
38
     *
39
     * @var array
40
     */
41
    protected $serverVariables = [];
42
 
43
    /**
44
     * Indicates whether redirects should be followed.
45
     *
46
     * @var bool
47
     */
48
    protected $followRedirects = false;
49
 
50
    /**
51
     * Indicates whether cookies should be encrypted.
52
     *
53
     * @var bool
54
     */
55
    protected $encryptCookies = true;
56
 
57
    /**
58
     * Indicated whether JSON requests should be performed "with credentials" (cookies).
59
     *
60
     * @see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
61
     *
62
     * @var bool
63
     */
64
    protected $withCredentials = false;
65
 
66
    /**
67
     * The latest test response (if any).
68
     *
69
     * @var \Illuminate\Testing\TestResponse|null
70
     */
71
    public static $latestResponse;
72
 
73
    /**
74
     * Define additional headers to be sent with the request.
75
     *
76
     * @param  array  $headers
77
     * @return $this
78
     */
79
    public function withHeaders(array $headers)
80
    {
81
        $this->defaultHeaders = array_merge($this->defaultHeaders, $headers);
82
 
83
        return $this;
84
    }
85
 
86
    /**
87
     * Add a header to be sent with the request.
88
     *
89
     * @param  string  $name
90
     * @param  string  $value
91
     * @return $this
92
     */
93
    public function withHeader(string $name, string $value)
94
    {
95
        $this->defaultHeaders[$name] = $value;
96
 
97
        return $this;
98
    }
99
 
100
    /**
101
     * Add an authorization token for the request.
102
     *
103
     * @param  string  $token
104
     * @param  string  $type
105
     * @return $this
106
     */
107
    public function withToken(string $token, string $type = 'Bearer')
108
    {
109
        return $this->withHeader('Authorization', $type.' '.$token);
110
    }
111
 
112
    /**
150 lars 113
     * Add a basic authentication header to the request with the given credentials.
114
     *
115
     * @param  string  $username
116
     * @param  string  $password
117
     * @return $this
118
     */
119
    public function withBasicAuth(string $username, string $password)
120
    {
121
        return $this->withToken(base64_encode("$username:$password"), 'Basic');
122
    }
123
 
124
    /**
148 lars 125
     * Remove the authorization token from the request.
126
     *
127
     * @return $this
128
     */
129
    public function withoutToken()
130
    {
131
        unset($this->defaultHeaders['Authorization']);
132
 
133
        return $this;
134
    }
135
 
136
    /**
137
     * Flush all the configured headers.
138
     *
139
     * @return $this
140
     */
141
    public function flushHeaders()
142
    {
143
        $this->defaultHeaders = [];
144
 
145
        return $this;
146
    }
147
 
148
    /**
149
     * Define a set of server variables to be sent with the requests.
150
     *
151
     * @param  array  $server
152
     * @return $this
153
     */
154
    public function withServerVariables(array $server)
155
    {
156
        $this->serverVariables = $server;
157
 
158
        return $this;
159
    }
160
 
161
    /**
162
     * Disable middleware for the test.
163
     *
164
     * @param  string|array|null  $middleware
165
     * @return $this
166
     */
167
    public function withoutMiddleware($middleware = null)
168
    {
169
        if (is_null($middleware)) {
170
            $this->app->instance('middleware.disable', true);
171
 
172
            return $this;
173
        }
174
 
175
        foreach ((array) $middleware as $abstract) {
176
            $this->app->instance($abstract, new class
177
            {
178
                public function handle($request, $next)
179
                {
180
                    return $next($request);
181
                }
182
            });
183
        }
184
 
185
        return $this;
186
    }
187
 
188
    /**
189
     * Enable the given middleware for the test.
190
     *
191
     * @param  string|array|null  $middleware
192
     * @return $this
193
     */
194
    public function withMiddleware($middleware = null)
195
    {
196
        if (is_null($middleware)) {
197
            unset($this->app['middleware.disable']);
198
 
199
            return $this;
200
        }
201
 
202
        foreach ((array) $middleware as $abstract) {
203
            unset($this->app[$abstract]);
204
        }
205
 
206
        return $this;
207
    }
208
 
209
    /**
210
     * Define additional cookies to be sent with the request.
211
     *
212
     * @param  array  $cookies
213
     * @return $this
214
     */
215
    public function withCookies(array $cookies)
216
    {
217
        $this->defaultCookies = array_merge($this->defaultCookies, $cookies);
218
 
219
        return $this;
220
    }
221
 
222
    /**
223
     * Add a cookie to be sent with the request.
224
     *
225
     * @param  string  $name
226
     * @param  string  $value
227
     * @return $this
228
     */
229
    public function withCookie(string $name, string $value)
230
    {
231
        $this->defaultCookies[$name] = $value;
232
 
233
        return $this;
234
    }
235
 
236
    /**
237
     * Define additional cookies will not be encrypted before sending with the request.
238
     *
239
     * @param  array  $cookies
240
     * @return $this
241
     */
242
    public function withUnencryptedCookies(array $cookies)
243
    {
244
        $this->unencryptedCookies = array_merge($this->unencryptedCookies, $cookies);
245
 
246
        return $this;
247
    }
248
 
249
    /**
250
     * Add a cookie will not be encrypted before sending with the request.
251
     *
252
     * @param  string  $name
253
     * @param  string  $value
254
     * @return $this
255
     */
256
    public function withUnencryptedCookie(string $name, string $value)
257
    {
258
        $this->unencryptedCookies[$name] = $value;
259
 
260
        return $this;
261
    }
262
 
263
    /**
264
     * Automatically follow any redirects returned from the response.
265
     *
266
     * @return $this
267
     */
268
    public function followingRedirects()
269
    {
270
        $this->followRedirects = true;
271
 
272
        return $this;
273
    }
274
 
275
    /**
276
     * Include cookies and authorization headers for JSON requests.
277
     *
278
     * @return $this
279
     */
280
    public function withCredentials()
281
    {
282
        $this->withCredentials = true;
283
 
284
        return $this;
285
    }
286
 
287
    /**
288
     * Disable automatic encryption of cookie values.
289
     *
290
     * @return $this
291
     */
292
    public function disableCookieEncryption()
293
    {
294
        $this->encryptCookies = false;
295
 
296
        return $this;
297
    }
298
 
299
    /**
300
     * Set the referer header and previous URL session value in order to simulate a previous request.
301
     *
302
     * @param  string  $url
303
     * @return $this
304
     */
305
    public function from(string $url)
306
    {
307
        $this->app['session']->setPreviousUrl($url);
308
 
309
        return $this->withHeader('referer', $url);
310
    }
311
 
312
    /**
313
     * Visit the given URI with a GET request.
314
     *
315
     * @param  string  $uri
316
     * @param  array  $headers
317
     * @return \Illuminate\Testing\TestResponse
318
     */
319
    public function get($uri, array $headers = [])
320
    {
321
        $server = $this->transformHeadersToServerVars($headers);
322
        $cookies = $this->prepareCookiesForRequest();
323
 
324
        return $this->call('GET', $uri, [], $cookies, [], $server);
325
    }
326
 
327
    /**
328
     * Visit the given URI with a GET request, expecting a JSON response.
329
     *
330
     * @param  string  $uri
331
     * @param  array  $headers
332
     * @return \Illuminate\Testing\TestResponse
333
     */
334
    public function getJson($uri, array $headers = [])
335
    {
336
        return $this->json('GET', $uri, [], $headers);
337
    }
338
 
339
    /**
340
     * Visit the given URI with a POST request.
341
     *
342
     * @param  string  $uri
343
     * @param  array  $data
344
     * @param  array  $headers
345
     * @return \Illuminate\Testing\TestResponse
346
     */
347
    public function post($uri, array $data = [], array $headers = [])
348
    {
349
        $server = $this->transformHeadersToServerVars($headers);
350
        $cookies = $this->prepareCookiesForRequest();
351
 
352
        return $this->call('POST', $uri, $data, $cookies, [], $server);
353
    }
354
 
355
    /**
356
     * Visit the given URI with a POST request, expecting a JSON response.
357
     *
358
     * @param  string  $uri
359
     * @param  array  $data
360
     * @param  array  $headers
361
     * @return \Illuminate\Testing\TestResponse
362
     */
363
    public function postJson($uri, array $data = [], array $headers = [])
364
    {
365
        return $this->json('POST', $uri, $data, $headers);
366
    }
367
 
368
    /**
369
     * Visit the given URI with a PUT request.
370
     *
371
     * @param  string  $uri
372
     * @param  array  $data
373
     * @param  array  $headers
374
     * @return \Illuminate\Testing\TestResponse
375
     */
376
    public function put($uri, array $data = [], array $headers = [])
377
    {
378
        $server = $this->transformHeadersToServerVars($headers);
379
        $cookies = $this->prepareCookiesForRequest();
380
 
381
        return $this->call('PUT', $uri, $data, $cookies, [], $server);
382
    }
383
 
384
    /**
385
     * Visit the given URI with a PUT request, expecting a JSON response.
386
     *
387
     * @param  string  $uri
388
     * @param  array  $data
389
     * @param  array  $headers
390
     * @return \Illuminate\Testing\TestResponse
391
     */
392
    public function putJson($uri, array $data = [], array $headers = [])
393
    {
394
        return $this->json('PUT', $uri, $data, $headers);
395
    }
396
 
397
    /**
398
     * Visit the given URI with a PATCH request.
399
     *
400
     * @param  string  $uri
401
     * @param  array  $data
402
     * @param  array  $headers
403
     * @return \Illuminate\Testing\TestResponse
404
     */
405
    public function patch($uri, array $data = [], array $headers = [])
406
    {
407
        $server = $this->transformHeadersToServerVars($headers);
408
        $cookies = $this->prepareCookiesForRequest();
409
 
410
        return $this->call('PATCH', $uri, $data, $cookies, [], $server);
411
    }
412
 
413
    /**
414
     * Visit the given URI with a PATCH request, expecting a JSON response.
415
     *
416
     * @param  string  $uri
417
     * @param  array  $data
418
     * @param  array  $headers
419
     * @return \Illuminate\Testing\TestResponse
420
     */
421
    public function patchJson($uri, array $data = [], array $headers = [])
422
    {
423
        return $this->json('PATCH', $uri, $data, $headers);
424
    }
425
 
426
    /**
427
     * Visit the given URI with a DELETE request.
428
     *
429
     * @param  string  $uri
430
     * @param  array  $data
431
     * @param  array  $headers
432
     * @return \Illuminate\Testing\TestResponse
433
     */
434
    public function delete($uri, array $data = [], array $headers = [])
435
    {
436
        $server = $this->transformHeadersToServerVars($headers);
437
        $cookies = $this->prepareCookiesForRequest();
438
 
439
        return $this->call('DELETE', $uri, $data, $cookies, [], $server);
440
    }
441
 
442
    /**
443
     * Visit the given URI with a DELETE request, expecting a JSON response.
444
     *
445
     * @param  string  $uri
446
     * @param  array  $data
447
     * @param  array  $headers
448
     * @return \Illuminate\Testing\TestResponse
449
     */
450
    public function deleteJson($uri, array $data = [], array $headers = [])
451
    {
452
        return $this->json('DELETE', $uri, $data, $headers);
453
    }
454
 
455
    /**
456
     * Visit the given URI with an OPTIONS request.
457
     *
458
     * @param  string  $uri
459
     * @param  array  $data
460
     * @param  array  $headers
461
     * @return \Illuminate\Testing\TestResponse
462
     */
463
    public function options($uri, array $data = [], array $headers = [])
464
    {
465
        $server = $this->transformHeadersToServerVars($headers);
466
 
467
        $cookies = $this->prepareCookiesForRequest();
468
 
469
        return $this->call('OPTIONS', $uri, $data, $cookies, [], $server);
470
    }
471
 
472
    /**
473
     * Visit the given URI with an OPTIONS request, expecting a JSON response.
474
     *
475
     * @param  string  $uri
476
     * @param  array  $data
477
     * @param  array  $headers
478
     * @return \Illuminate\Testing\TestResponse
479
     */
480
    public function optionsJson($uri, array $data = [], array $headers = [])
481
    {
482
        return $this->json('OPTIONS', $uri, $data, $headers);
483
    }
484
 
485
    /**
486
     * Visit the given URI with a HEAD request.
487
     *
488
     * @param  string  $uri
489
     * @param  array  $headers
490
     * @return \Illuminate\Testing\TestResponse
491
     */
492
    public function head($uri, array $headers = [])
493
    {
494
        $server = $this->transformHeadersToServerVars($headers);
495
 
496
        $cookies = $this->prepareCookiesForRequest();
497
 
498
        return $this->call('HEAD', $uri, [], $cookies, [], $server);
499
    }
500
 
501
    /**
502
     * Call the given URI with a JSON request.
503
     *
504
     * @param  string  $method
505
     * @param  string  $uri
506
     * @param  array  $data
507
     * @param  array  $headers
508
     * @return \Illuminate\Testing\TestResponse
509
     */
510
    public function json($method, $uri, array $data = [], array $headers = [])
511
    {
512
        $files = $this->extractFilesFromDataArray($data);
513
 
514
        $content = json_encode($data);
515
 
516
        $headers = array_merge([
517
            'CONTENT_LENGTH' => mb_strlen($content, '8bit'),
518
            'CONTENT_TYPE' => 'application/json',
519
            'Accept' => 'application/json',
520
        ], $headers);
521
 
522
        return $this->call(
523
            $method,
524
            $uri,
525
            [],
526
            $this->prepareCookiesForJsonRequest(),
527
            $files,
528
            $this->transformHeadersToServerVars($headers),
529
            $content
530
        );
531
    }
532
 
533
    /**
534
     * Call the given URI and return the Response.
535
     *
536
     * @param  string  $method
537
     * @param  string  $uri
538
     * @param  array  $parameters
539
     * @param  array  $cookies
540
     * @param  array  $files
541
     * @param  array  $server
542
     * @param  string|null  $content
543
     * @return \Illuminate\Testing\TestResponse
544
     */
545
    public function call($method, $uri, $parameters = [], $cookies = [], $files = [], $server = [], $content = null)
546
    {
547
        $kernel = $this->app->make(HttpKernel::class);
548
 
549
        $files = array_merge($files, $this->extractFilesFromDataArray($parameters));
550
 
551
        $symfonyRequest = SymfonyRequest::create(
552
            $this->prepareUrlForRequest($uri), $method, $parameters,
553
            $cookies, $files, array_replace($this->serverVariables, $server), $content
554
        );
555
 
556
        $response = $kernel->handle(
557
            $request = Request::createFromBase($symfonyRequest)
558
        );
559
 
560
        $kernel->terminate($request, $response);
561
 
562
        if ($this->followRedirects) {
563
            $response = $this->followRedirects($response);
564
        }
565
 
566
        return static::$latestResponse = $this->createTestResponse($response);
567
    }
568
 
569
    /**
570
     * Turn the given URI into a fully qualified URL.
571
     *
572
     * @param  string  $uri
573
     * @return string
574
     */
575
    protected function prepareUrlForRequest($uri)
576
    {
577
        if (str_starts_with($uri, '/')) {
578
            $uri = substr($uri, 1);
579
        }
580
 
581
        return trim(url($uri), '/');
582
    }
583
 
584
    /**
585
     * Transform headers array to array of $_SERVER vars with HTTP_* format.
586
     *
587
     * @param  array  $headers
588
     * @return array
589
     */
590
    protected function transformHeadersToServerVars(array $headers)
591
    {
592
        return collect(array_merge($this->defaultHeaders, $headers))->mapWithKeys(function ($value, $name) {
593
            $name = strtr(strtoupper($name), '-', '_');
594
 
595
            return [$this->formatServerHeaderKey($name) => $value];
596
        })->all();
597
    }
598
 
599
    /**
600
     * Format the header name for the server array.
601
     *
602
     * @param  string  $name
603
     * @return string
604
     */
605
    protected function formatServerHeaderKey($name)
606
    {
607
        if (! str_starts_with($name, 'HTTP_') && $name !== 'CONTENT_TYPE' && $name !== 'REMOTE_ADDR') {
608
            return 'HTTP_'.$name;
609
        }
610
 
611
        return $name;
612
    }
613
 
614
    /**
615
     * Extract the file uploads from the given data array.
616
     *
617
     * @param  array  $data
618
     * @return array
619
     */
620
    protected function extractFilesFromDataArray(&$data)
621
    {
622
        $files = [];
623
 
624
        foreach ($data as $key => $value) {
625
            if ($value instanceof SymfonyUploadedFile) {
626
                $files[$key] = $value;
627
 
628
                unset($data[$key]);
629
            }
630
 
631
            if (is_array($value)) {
632
                $files[$key] = $this->extractFilesFromDataArray($value);
633
 
634
                $data[$key] = $value;
635
            }
636
        }
637
 
638
        return $files;
639
    }
640
 
641
    /**
642
     * If enabled, encrypt cookie values for request.
643
     *
644
     * @return array
645
     */
646
    protected function prepareCookiesForRequest()
647
    {
648
        if (! $this->encryptCookies) {
649
            return array_merge($this->defaultCookies, $this->unencryptedCookies);
650
        }
651
 
652
        return collect($this->defaultCookies)->map(function ($value, $key) {
653
            return encrypt(CookieValuePrefix::create($key, app('encrypter')->getKey()).$value, false);
654
        })->merge($this->unencryptedCookies)->all();
655
    }
656
 
657
    /**
658
     * If enabled, add cookies for JSON requests.
659
     *
660
     * @return array
661
     */
662
    protected function prepareCookiesForJsonRequest()
663
    {
664
        return $this->withCredentials ? $this->prepareCookiesForRequest() : [];
665
    }
666
 
667
    /**
668
     * Follow a redirect chain until a non-redirect is received.
669
     *
670
     * @param  \Illuminate\Http\Response  $response
671
     * @return \Illuminate\Http\Response|\Illuminate\Testing\TestResponse
672
     */
673
    protected function followRedirects($response)
674
    {
675
        $this->followRedirects = false;
676
 
677
        while ($response->isRedirect()) {
678
            $response = $this->get($response->headers->get('Location'));
679
        }
680
 
681
        return $response;
682
    }
683
 
684
    /**
685
     * Create the test response instance from the given response.
686
     *
687
     * @param  \Illuminate\Http\Response  $response
688
     * @return \Illuminate\Testing\TestResponse
689
     */
690
    protected function createTestResponse($response)
691
    {
692
        return tap(TestResponse::fromBaseResponse($response), function ($response) {
693
            $response->withExceptions(
694
                $this->app->bound(LoggedExceptionCollection::class)
695
                    ? $this->app->make(LoggedExceptionCollection::class)
696
                    : new LoggedExceptionCollection
697
            );
698
        });
699
    }
700
}