@@ -20,15 +20,24 @@ class StartSession
2020 */
2121 protected $ manager ;
2222
23+ /**
24+ * The callback that can resolve an instance of the cache factory.
25+ *
26+ * @var callable
27+ */
28+ protected $ cacheFactoryResolver ;
29+
2330 /**
2431 * Create a new session middleware.
2532 *
2633 * @param \Illuminate\Session\SessionManager $manager
34+ * @param callable $cacheFactoryResolver
2735 * @return void
2836 */
29- public function __construct (SessionManager $ manager )
37+ public function __construct (SessionManager $ manager, callable $ cacheFactoryResolver = null )
3038 {
3139 $ this ->manager = $ manager ;
40+ $ this ->cacheFactoryResolver = $ cacheFactoryResolver ;
3241 }
3342
3443 /**
@@ -44,11 +53,62 @@ public function handle($request, Closure $next)
4453 return $ next ($ request );
4554 }
4655
56+ $ session = $ this ->getSession ($ request );
57+
58+ if ($ this ->manager ->shouldBlock () ||
59+ ($ request ->route () && $ request ->route ()->locksFor ())) {
60+ return $ this ->handleRequestWhileBlocking ($ request , $ session , $ next );
61+ } else {
62+ return $ this ->handleStatefulRequest ($ request , $ session , $ next );
63+ }
64+ }
65+
66+ /**
67+ * Handle the given request within session state.
68+ *
69+ * @param \Illuminate\Http\Request $request
70+ * @param \Illuminate\Contracts\Session\Session $session
71+ * @param \Closure $next
72+ * @return mixed
73+ */
74+ protected function handleRequestWhileBlocking (Request $ request , $ session , Closure $ next )
75+ {
76+ $ lockFor = $ request ->route () && $ request ->route ()->locksFor ()
77+ ? $ request ->route ()->locksFor ()
78+ : 10 ;
79+
80+ $ lock = $ this ->cache ($ this ->manager ->blockDriver ())
81+ ->lock ('session: ' .$ session ->getId (), $ lockFor )
82+ ->betweenBlockedAttemptsSleepFor (50 );
83+
84+ try {
85+ $ lock ->block (
86+ ! is_null ($ request ->route ()->waitsFor ())
87+ ? $ request ->route ()->waitsFor ()
88+ : 10
89+ );
90+
91+ return $ this ->handleStatefulRequest ($ request , $ session , $ next );
92+ } finally {
93+ optional ($ lock )->release ();
94+ }
95+ }
96+
97+ /**
98+ * Handle the given request within session state.
99+ *
100+ * @param \Illuminate\Http\Request $request
101+ * @param \Illuminate\Contracts\Session\Session $session
102+ * @param \Closure $next
103+ * @return mixed
104+ */
105+ protected function handleStatefulRequest (Request $ request , $ session , Closure $ next )
106+ {
47107 // If a session driver has been configured, we will need to start the session here
48108 // so that the data is ready for an application. Note that the Laravel sessions
49109 // do not make use of PHP "native" sessions in any way since they are crappy.
50110 $ request ->setLaravelSession (
51- $ session = $ this ->startSession ($ request )
111+ $ this ->startSession ($ request, $ session )
52112 );
53113
54114 $ this ->collectGarbage ($ session );
@@ -71,11 +131,12 @@ public function handle($request, Closure $next)
71131 * Start the session for the given request.
72132 *
73133 * @param \Illuminate\Http\Request $request
134+ * @param \Illuminate\Contracts\Session\Session $session
74135 * @return \Illuminate\Contracts\Session\Session
75136 */
76- protected function startSession (Request $ request )
137+ protected function startSession (Request $ request, $ session )
77138 {
78- return tap ($ this -> getSession ( $ request ) , function ($ session ) use ($ request ) {
139+ return tap ($ session , function ($ session ) use ($ request ) {
79140 $ session ->setRequestOnHandler ($ request );
80141
81142 $ session ->start ();
@@ -216,4 +277,15 @@ protected function sessionIsPersistent(array $config = null)
216277
217278 return ! is_null ($ config ['driver ' ] ?? null );
218279 }
280+
281+ /**
282+ * Resolve the given cache driver.
283+ *
284+ * @param string $cache
285+ * @return \Illuminate\Cache\Store
286+ */
287+ protected function cache ($ driver )
288+ {
289+ return call_user_func ($ this ->cacheFactoryResolver )->driver ($ driver );
290+ }
219291}
0 commit comments