12
12
use Illuminate \Support \Facades \Route ;
13
13
use Illuminate \Support \Str ;
14
14
use Illuminate \Validation \ValidationException ;
15
+ use Symfony \Component \HttpFoundation \Cookie ;
15
16
use Tonysm \TurboLaravel \Facades \Turbo as TurboFacade ;
16
17
use Tonysm \TurboLaravel \Turbo ;
17
18
@@ -20,6 +21,13 @@ class TurboMiddleware
20
21
/** @var \Tonysm\TurboLaravel\Http\Middleware\RouteRedirectGuesser */
21
22
private $ redirectGuesser ;
22
23
24
+ /**
25
+ * Encrypted cookies to be added to the internal requests following redirects.
26
+ *
27
+ * @var array
28
+ */
29
+ private array $ encryptedCookies ;
30
+
23
31
public function __construct (RouteRedirectGuesser $ redirectGuesser )
24
32
{
25
33
$ this ->redirectGuesser = $ redirectGuesser ;
@@ -32,6 +40,8 @@ public function __construct(RouteRedirectGuesser $redirectGuesser)
32
40
*/
33
41
public function handle ($ request , Closure $ next )
34
42
{
43
+ $ this ->encryptedCookies = $ request ->cookies ->all ();
44
+
35
45
if ($ this ->turboNativeVisit ($ request )) {
36
46
TurboFacade::setVisitingFromTurboNative ();
37
47
}
@@ -63,14 +73,24 @@ private function turboResponse($response, Request $request)
63
73
return $ response ;
64
74
}
65
75
76
+ // We get the response's encrypted cookies and merge them with the
77
+ // encrypted cookies of the first request to make sure that are
78
+ // sub-sequent request will use the most up-to-date values.
79
+
80
+ $ responseCookies = collect ($ response ->headers ->getCookies ())
81
+ ->mapWithKeys (fn (Cookie $ cookie ) => [$ cookie ->getName () => $ cookie ->getValue ()])
82
+ ->all ();
83
+
84
+ $ this ->encryptedCookies = array_replace_recursive ($ this ->encryptedCookies , $ responseCookies );
85
+
66
86
// When throwing a ValidationException and the app uses named routes convention, we can guess
67
87
// the form route for the current endpoint, make an internal request there, and return the
68
88
// response body with the form over a 422 status code, which is better for Turbo Native.
69
89
70
90
if ($ response ->exception instanceof ValidationException && ($ formRedirectUrl = $ this ->getRedirectUrl ($ request , $ response ))) {
71
91
$ response ->setTargetUrl ($ formRedirectUrl );
72
92
73
- return tap ($ this ->handleRedirectInternally ($ this -> kernel (), $ request , $ response ), function () use ($ request ) {
93
+ return tap ($ this ->handleRedirectInternally ($ request , $ response ), function () use ($ request ) {
74
94
App::instance ('request ' , $ request );
75
95
Facade::clearResolvedInstance ('request ' );
76
96
});
@@ -94,28 +114,34 @@ private function kernel(): Kernel
94
114
}
95
115
96
116
/**
97
- * @param Kernel $kernel
98
117
* @param Request $request
99
118
* @param Response $response
100
119
*
101
120
* @return Response
102
121
*/
103
- private function handleRedirectInternally ($ kernel , $ request , $ response )
122
+ private function handleRedirectInternally ($ request , $ response )
104
123
{
124
+ $ kernel = $ this ->kernel ();
125
+
105
126
do {
106
127
$ response = $ kernel ->handle (
107
128
$ request = $ this ->createRequestFrom ($ response ->headers ->get ('Location ' ), $ request )
108
129
);
109
130
} while ($ response ->isRedirect ());
110
131
111
- return $ response ->setStatusCode (422 );
132
+ if ($ response ->isOk ()) {
133
+ $ response ->setStatusCode (422 );
134
+ }
135
+
136
+ return $ response ;
112
137
}
113
138
114
139
private function createRequestFrom (string $ url , Request $ baseRequest )
115
140
{
116
141
$ request = Request::create ($ url , 'GET ' );
117
142
118
143
$ request ->headers ->replace ($ baseRequest ->headers ->all ());
144
+ $ request ->cookies ->replace ($ this ->encryptedCookies );
119
145
120
146
return $ request ;
121
147
}
0 commit comments