Subversion-Projekte lars-tiefland.laravel_shop

Revision

Zur aktuellen Revision | Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
namespace Illuminate\Foundation\Http;
4
 
5
use Carbon\CarbonInterval;
6
use DateTimeInterface;
7
use Illuminate\Contracts\Debug\ExceptionHandler;
8
use Illuminate\Contracts\Foundation\Application;
9
use Illuminate\Contracts\Http\Kernel as KernelContract;
10
use Illuminate\Foundation\Http\Events\RequestHandled;
11
use Illuminate\Routing\Pipeline;
12
use Illuminate\Routing\Router;
13
use Illuminate\Support\Carbon;
14
use Illuminate\Support\Facades\Facade;
15
use Illuminate\Support\InteractsWithTime;
16
use InvalidArgumentException;
17
use Throwable;
18
 
19
class Kernel implements KernelContract
20
{
21
    use InteractsWithTime;
22
 
23
    /**
24
     * The application implementation.
25
     *
26
     * @var \Illuminate\Contracts\Foundation\Application
27
     */
28
    protected $app;
29
 
30
    /**
31
     * The router instance.
32
     *
33
     * @var \Illuminate\Routing\Router
34
     */
35
    protected $router;
36
 
37
    /**
38
     * The bootstrap classes for the application.
39
     *
40
     * @var string[]
41
     */
42
    protected $bootstrappers = [
43
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
44
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
45
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
46
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
47
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
48
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
49
    ];
50
 
51
    /**
52
     * The application's middleware stack.
53
     *
54
     * @var array
55
     */
56
    protected $middleware = [];
57
 
58
    /**
59
     * The application's route middleware groups.
60
     *
61
     * @var array
62
     */
63
    protected $middlewareGroups = [];
64
 
65
    /**
66
     * The application's route middleware.
67
     *
68
     * @var array
69
     */
70
    protected $routeMiddleware = [];
71
 
72
    /**
73
     * All of the registered request duration handlers.
74
     *
75
     * @var array
76
     */
77
    protected $requestLifecycleDurationHandlers = [];
78
 
79
    /**
80
     * When the kernel starting handling the current request.
81
     *
82
     * @var \Illuminate\Support\Carbon|null
83
     */
84
    protected $requestStartedAt;
85
 
86
    /**
87
     * The priority-sorted list of middleware.
88
     *
89
     * Forces non-global middleware to always be in the given order.
90
     *
91
     * @var string[]
92
     */
93
    protected $middlewarePriority = [
94
        \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
95
        \Illuminate\Cookie\Middleware\EncryptCookies::class,
96
        \Illuminate\Session\Middleware\StartSession::class,
97
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
98
        \Illuminate\Contracts\Auth\Middleware\AuthenticatesRequests::class,
99
        \Illuminate\Routing\Middleware\ThrottleRequests::class,
100
        \Illuminate\Routing\Middleware\ThrottleRequestsWithRedis::class,
101
        \Illuminate\Contracts\Session\Middleware\AuthenticatesSessions::class,
102
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
103
        \Illuminate\Auth\Middleware\Authorize::class,
104
    ];
105
 
106
    /**
107
     * Create a new HTTP kernel instance.
108
     *
109
     * @param  \Illuminate\Contracts\Foundation\Application  $app
110
     * @param  \Illuminate\Routing\Router  $router
111
     * @return void
112
     */
113
    public function __construct(Application $app, Router $router)
114
    {
115
        $this->app = $app;
116
        $this->router = $router;
117
 
118
        $this->syncMiddlewareToRouter();
119
    }
120
 
121
    /**
122
     * Handle an incoming HTTP request.
123
     *
124
     * @param  \Illuminate\Http\Request  $request
125
     * @return \Illuminate\Http\Response
126
     */
127
    public function handle($request)
128
    {
129
        $this->requestStartedAt = Carbon::now();
130
 
131
        try {
132
            $request->enableHttpMethodParameterOverride();
133
 
134
            $response = $this->sendRequestThroughRouter($request);
135
        } catch (Throwable $e) {
136
            $this->reportException($e);
137
 
138
            $response = $this->renderException($request, $e);
139
        }
140
 
141
        $this->app['events']->dispatch(
142
            new RequestHandled($request, $response)
143
        );
144
 
145
        return $response;
146
    }
147
 
148
    /**
149
     * Send the given request through the middleware / router.
150
     *
151
     * @param  \Illuminate\Http\Request  $request
152
     * @return \Illuminate\Http\Response
153
     */
154
    protected function sendRequestThroughRouter($request)
155
    {
156
        $this->app->instance('request', $request);
157
 
158
        Facade::clearResolvedInstance('request');
159
 
160
        $this->bootstrap();
161
 
162
        return (new Pipeline($this->app))
163
                    ->send($request)
164
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
165
                    ->then($this->dispatchToRouter());
166
    }
167
 
168
    /**
169
     * Bootstrap the application for HTTP requests.
170
     *
171
     * @return void
172
     */
173
    public function bootstrap()
174
    {
175
        if (! $this->app->hasBeenBootstrapped()) {
176
            $this->app->bootstrapWith($this->bootstrappers());
177
        }
178
    }
179
 
180
    /**
181
     * Get the route dispatcher callback.
182
     *
183
     * @return \Closure
184
     */
185
    protected function dispatchToRouter()
186
    {
187
        return function ($request) {
188
            $this->app->instance('request', $request);
189
 
190
            return $this->router->dispatch($request);
191
        };
192
    }
193
 
194
    /**
195
     * Call the terminate method on any terminable middleware.
196
     *
197
     * @param  \Illuminate\Http\Request  $request
198
     * @param  \Illuminate\Http\Response  $response
199
     * @return void
200
     */
201
    public function terminate($request, $response)
202
    {
203
        $this->terminateMiddleware($request, $response);
204
 
205
        $this->app->terminate();
206
 
207
        foreach ($this->requestLifecycleDurationHandlers as ['threshold' => $threshold, 'handler' => $handler]) {
208
            $end ??= Carbon::now();
209
 
210
            if ($this->requestStartedAt->diffInMilliseconds($end) > $threshold) {
211
                $handler($this->requestStartedAt, $request, $response);
212
            }
213
        }
214
 
215
        $this->requestStartedAt = null;
216
    }
217
 
218
    /**
219
     * Call the terminate method on any terminable middleware.
220
     *
221
     * @param  \Illuminate\Http\Request  $request
222
     * @param  \Illuminate\Http\Response  $response
223
     * @return void
224
     */
225
    protected function terminateMiddleware($request, $response)
226
    {
227
        $middlewares = $this->app->shouldSkipMiddleware() ? [] : array_merge(
228
            $this->gatherRouteMiddleware($request),
229
            $this->middleware
230
        );
231
 
232
        foreach ($middlewares as $middleware) {
233
            if (! is_string($middleware)) {
234
                continue;
235
            }
236
 
237
            [$name] = $this->parseMiddleware($middleware);
238
 
239
            $instance = $this->app->make($name);
240
 
241
            if (method_exists($instance, 'terminate')) {
242
                $instance->terminate($request, $response);
243
            }
244
        }
245
    }
246
 
247
    /**
248
     * Register a callback to be invoked when the requests lifecyle duration exceeds a given amount of time.
249
     *
250
     * @param  \DateTimeInterface|\Carbon\CarbonInterval|float|int  $threshold
251
     * @param  callable  $handler
252
     * @return void
253
     */
254
    public function whenRequestLifecycleIsLongerThan($threshold, $handler)
255
    {
256
        $threshold = $threshold instanceof DateTimeInterface
257
            ? $this->secondsUntil($threshold) * 1000
258
            : $threshold;
259
 
260
        $threshold = $threshold instanceof CarbonInterval
261
            ? $threshold->totalMilliseconds
262
            : $threshold;
263
 
264
        $this->requestLifecycleDurationHandlers[] = [
265
            'threshold' => $threshold,
266
            'handler' => $handler,
267
        ];
268
    }
269
 
270
    /**
271
     * When the request being handled started.
272
     *
273
     * @return \Illuminate\Support\Carbon|null
274
     */
275
    public function requestStartedAt()
276
    {
277
        return $this->requestStartedAt;
278
    }
279
 
280
    /**
281
     * Gather the route middleware for the given request.
282
     *
283
     * @param  \Illuminate\Http\Request  $request
284
     * @return array
285
     */
286
    protected function gatherRouteMiddleware($request)
287
    {
288
        if ($route = $request->route()) {
289
            return $this->router->gatherRouteMiddleware($route);
290
        }
291
 
292
        return [];
293
    }
294
 
295
    /**
296
     * Parse a middleware string to get the name and parameters.
297
     *
298
     * @param  string  $middleware
299
     * @return array
300
     */
301
    protected function parseMiddleware($middleware)
302
    {
303
        [$name, $parameters] = array_pad(explode(':', $middleware, 2), 2, []);
304
 
305
        if (is_string($parameters)) {
306
            $parameters = explode(',', $parameters);
307
        }
308
 
309
        return [$name, $parameters];
310
    }
311
 
312
    /**
313
     * Determine if the kernel has a given middleware.
314
     *
315
     * @param  string  $middleware
316
     * @return bool
317
     */
318
    public function hasMiddleware($middleware)
319
    {
320
        return in_array($middleware, $this->middleware);
321
    }
322
 
323
    /**
324
     * Add a new middleware to the beginning of the stack if it does not already exist.
325
     *
326
     * @param  string  $middleware
327
     * @return $this
328
     */
329
    public function prependMiddleware($middleware)
330
    {
331
        if (array_search($middleware, $this->middleware) === false) {
332
            array_unshift($this->middleware, $middleware);
333
        }
334
 
335
        return $this;
336
    }
337
 
338
    /**
339
     * Add a new middleware to end of the stack if it does not already exist.
340
     *
341
     * @param  string  $middleware
342
     * @return $this
343
     */
344
    public function pushMiddleware($middleware)
345
    {
346
        if (array_search($middleware, $this->middleware) === false) {
347
            $this->middleware[] = $middleware;
348
        }
349
 
350
        return $this;
351
    }
352
 
353
    /**
354
     * Prepend the given middleware to the given middleware group.
355
     *
356
     * @param  string  $group
357
     * @param  string  $middleware
358
     * @return $this
359
     *
360
     * @throws \InvalidArgumentException
361
     */
362
    public function prependMiddlewareToGroup($group, $middleware)
363
    {
364
        if (! isset($this->middlewareGroups[$group])) {
365
            throw new InvalidArgumentException("The [{$group}] middleware group has not been defined.");
366
        }
367
 
368
        if (array_search($middleware, $this->middlewareGroups[$group]) === false) {
369
            array_unshift($this->middlewareGroups[$group], $middleware);
370
        }
371
 
372
        $this->syncMiddlewareToRouter();
373
 
374
        return $this;
375
    }
376
 
377
    /**
378
     * Append the given middleware to the given middleware group.
379
     *
380
     * @param  string  $group
381
     * @param  string  $middleware
382
     * @return $this
383
     *
384
     * @throws \InvalidArgumentException
385
     */
386
    public function appendMiddlewareToGroup($group, $middleware)
387
    {
388
        if (! isset($this->middlewareGroups[$group])) {
389
            throw new InvalidArgumentException("The [{$group}] middleware group has not been defined.");
390
        }
391
 
392
        if (array_search($middleware, $this->middlewareGroups[$group]) === false) {
393
            $this->middlewareGroups[$group][] = $middleware;
394
        }
395
 
396
        $this->syncMiddlewareToRouter();
397
 
398
        return $this;
399
    }
400
 
401
    /**
402
     * Prepend the given middleware to the middleware priority list.
403
     *
404
     * @param  string  $middleware
405
     * @return $this
406
     */
407
    public function prependToMiddlewarePriority($middleware)
408
    {
409
        if (! in_array($middleware, $this->middlewarePriority)) {
410
            array_unshift($this->middlewarePriority, $middleware);
411
        }
412
 
413
        $this->syncMiddlewareToRouter();
414
 
415
        return $this;
416
    }
417
 
418
    /**
419
     * Append the given middleware to the middleware priority list.
420
     *
421
     * @param  string  $middleware
422
     * @return $this
423
     */
424
    public function appendToMiddlewarePriority($middleware)
425
    {
426
        if (! in_array($middleware, $this->middlewarePriority)) {
427
            $this->middlewarePriority[] = $middleware;
428
        }
429
 
430
        $this->syncMiddlewareToRouter();
431
 
432
        return $this;
433
    }
434
 
435
    /**
436
     * Sync the current state of the middleware to the router.
437
     *
438
     * @return void
439
     */
440
    protected function syncMiddlewareToRouter()
441
    {
442
        $this->router->middlewarePriority = $this->middlewarePriority;
443
 
444
        foreach ($this->middlewareGroups as $key => $middleware) {
445
            $this->router->middlewareGroup($key, $middleware);
446
        }
447
 
448
        foreach ($this->routeMiddleware as $key => $middleware) {
449
            $this->router->aliasMiddleware($key, $middleware);
450
        }
451
    }
452
 
453
    /**
454
     * Get the priority-sorted list of middleware.
455
     *
456
     * @return array
457
     */
458
    public function getMiddlewarePriority()
459
    {
460
        return $this->middlewarePriority;
461
    }
462
 
463
    /**
464
     * Get the bootstrap classes for the application.
465
     *
466
     * @return array
467
     */
468
    protected function bootstrappers()
469
    {
470
        return $this->bootstrappers;
471
    }
472
 
473
    /**
474
     * Report the exception to the exception handler.
475
     *
476
     * @param  \Throwable  $e
477
     * @return void
478
     */
479
    protected function reportException(Throwable $e)
480
    {
481
        $this->app[ExceptionHandler::class]->report($e);
482
    }
483
 
484
    /**
485
     * Render the exception to a response.
486
     *
487
     * @param  \Illuminate\Http\Request  $request
488
     * @param  \Throwable  $e
489
     * @return \Symfony\Component\HttpFoundation\Response
490
     */
491
    protected function renderException($request, Throwable $e)
492
    {
493
        return $this->app[ExceptionHandler::class]->render($request, $e);
494
    }
495
 
496
    /**
497
     * Get the application's route middleware groups.
498
     *
499
     * @return array
500
     */
501
    public function getMiddlewareGroups()
502
    {
503
        return $this->middlewareGroups;
504
    }
505
 
506
    /**
507
     * Get the application's route middleware.
508
     *
509
     * @return array
510
     */
511
    public function getRouteMiddleware()
512
    {
513
        return $this->routeMiddleware;
514
    }
515
 
516
    /**
517
     * Get the Laravel application instance.
518
     *
519
     * @return \Illuminate\Contracts\Foundation\Application
520
     */
521
    public function getApplication()
522
    {
523
        return $this->app;
524
    }
525
 
526
    /**
527
     * Set the Laravel application instance.
528
     *
529
     * @param  \Illuminate\Contracts\Foundation\Application  $app
530
     * @return $this
531
     */
532
    public function setApplication(Application $app)
533
    {
534
        $this->app = $app;
535
 
536
        return $this;
537
    }
538
}