@@ -39,6 +39,13 @@ class CorsRequestListener extends AbstractListenerAggregate
39
39
*/
40
40
protected $ corsService ;
41
41
42
+ /**
43
+ * Whether or not a preflight request was detected
44
+ *
45
+ * @var bool
46
+ */
47
+ protected $ isPreflight = false ;
48
+
42
49
/**
43
50
* @param CorsService $corsService
44
51
*/
@@ -52,17 +59,24 @@ public function __construct(CorsService $corsService)
52
59
*/
53
60
public function attach (EventManagerInterface $ events )
54
61
{
55
- $ this ->listeners [] = $ events ->attach (MvcEvent::EVENT_ROUTE , array ($ this , 'onCorsRequest ' ), -1 );
62
+ // Preflight can be handled during the route event, and should return early
63
+ $ this ->listeners [] = $ events ->attach (MvcEvent::EVENT_ROUTE , array ($ this , 'onCorsPreflight ' ), -1 );
64
+
65
+ // "in"flight should be handled during "FINISH" to ensure we operate on the actual route being returned
66
+ $ this ->listeners [] = $ events ->attach (MvcEvent::EVENT_FINISH , array ($ this , 'onCorsRequest ' ), 100 );
56
67
}
57
68
58
69
/**
59
- * Handle a CORS request (either preflight or normal CORS request)
70
+ * Handle a CORS preflight request
60
71
*
61
- * @param MvcEvent $event
62
- * @return mixed
72
+ * @param MvcEvent $event
73
+ * @return null|HttpResponse
63
74
*/
64
- public function onCorsRequest (MvcEvent $ event )
75
+ public function onCorsPreflight (MvcEvent $ event )
65
76
{
77
+ // Reset state flag
78
+ $ this ->isPreflight = false ;
79
+
66
80
/** @var $request HttpRequest */
67
81
$ request = $ event ->getRequest ();
68
82
/** @var $response HttpResponse */
@@ -72,23 +86,49 @@ public function onCorsRequest(MvcEvent $event)
72
86
return ;
73
87
}
74
88
75
- // First, the preflight request
76
- if ($ this ->corsService ->isPreflightRequest ($ request )) {
77
- return $ this ->corsService ->createPreflightCorsResponse ($ request );
89
+ // If this isn't a preflight, done
90
+ if (!$ this ->corsService ->isPreflightRequest ($ request )) {
91
+ return ;
92
+ }
93
+
94
+ // Preflight -- return a response now!
95
+ $ this ->isPreflight = true ;
96
+
97
+ return $ this ->corsService ->createPreflightCorsResponse ($ request );
98
+ }
99
+
100
+ /**
101
+ * Handle a CORS request (non-preflight, normal CORS request)
102
+ *
103
+ * @param MvcEvent $event
104
+ */
105
+ public function onCorsRequest (MvcEvent $ event )
106
+ {
107
+ // Do nothing if we previously created a preflight response
108
+ if ($ this ->isPreflight ) {
109
+ return ;
110
+ }
111
+
112
+ /** @var $request HttpRequest */
113
+ $ request = $ event ->getRequest ();
114
+ /** @var $response HttpResponse */
115
+ $ response = $ event ->getResponse ();
116
+
117
+ if (!$ request instanceof HttpRequest || !$ this ->corsService ->isCorsRequest ($ request )) {
118
+ return ;
78
119
}
79
120
80
- // Otherwise, it is the second step of the CORS request, and we let ZF continue
121
+ // This is the second step of the CORS request, and we let ZF continue
81
122
// processing the response
82
123
try {
83
124
$ response = $ this ->corsService ->populateCorsResponse ($ request , $ response );
84
- $ event ->setResponse ($ response );
85
125
} catch (DisallowedOriginException $ exception ) {
86
126
$ response = new HttpResponse (); // Clear response for security
87
-
88
127
$ response ->setStatusCode (403 )
89
128
->setReasonPhrase ($ exception ->getMessage ());
90
129
91
- return $ response ;
92
130
}
131
+
132
+ $ event ->setResponse ($ response );
93
133
}
94
134
}
0 commit comments