12
12
namespace CodeIgniter \HTTP ;
13
13
14
14
use CodeIgniter \HTTP \Exceptions \HTTPException ;
15
+ use InvalidArgumentException ;
15
16
16
17
/**
17
18
* Message Trait
@@ -25,7 +26,11 @@ trait MessageTrait
25
26
/**
26
27
* List of all HTTP request headers.
27
28
*
28
- * @var array<string, Header>
29
+ * [name => Header]
30
+ * or
31
+ * [name => [Header1, Header2]]
32
+ *
33
+ * @var array<string, Header|list<Header>>
29
34
*/
30
35
protected $ headers = [];
31
36
@@ -102,7 +107,7 @@ public function populateHeaders(): void
102
107
/**
103
108
* Returns an array containing all Headers.
104
109
*
105
- * @return array<string, Header> An array of the Header objects
110
+ * @return array<string, Header|list<Header> > An array of the Header objects
106
111
*/
107
112
public function headers (): array
108
113
{
@@ -122,7 +127,7 @@ public function headers(): array
122
127
*
123
128
* @param string $name
124
129
*
125
- * @return array| Header|null
130
+ * @return Header|list< Header> |null
126
131
*/
127
132
public function header ($ name )
128
133
{
@@ -140,9 +145,14 @@ public function header($name)
140
145
*/
141
146
public function setHeader (string $ name , $ value ): self
142
147
{
148
+ $ this ->checkMultipleHeaders ($ name );
149
+
143
150
$ origName = $ this ->getHeaderName ($ name );
144
151
145
- if (isset ($ this ->headers [$ origName ]) && is_array ($ this ->headers [$ origName ]->getValue ())) {
152
+ if (
153
+ isset ($ this ->headers [$ origName ])
154
+ && is_array ($ this ->headers [$ origName ]->getValue ())
155
+ ) {
146
156
if (! is_array ($ value )) {
147
157
$ value = [$ value ];
148
158
}
@@ -158,6 +168,23 @@ public function setHeader(string $name, $value): self
158
168
return $ this ;
159
169
}
160
170
171
+ private function hasMultipleHeaders (string $ name ): bool
172
+ {
173
+ $ origName = $ this ->getHeaderName ($ name );
174
+
175
+ return isset ($ this ->headers [$ origName ]) && is_array ($ this ->headers [$ origName ]);
176
+ }
177
+
178
+ private function checkMultipleHeaders (string $ name ): void
179
+ {
180
+ if ($ this ->hasMultipleHeaders ($ name )) {
181
+ throw new InvalidArgumentException (
182
+ 'The header " ' . $ name . '" already has multiple headers. '
183
+ . ' You cannot change them. If you really need to change, remove the header first. '
184
+ );
185
+ }
186
+ }
187
+
161
188
/**
162
189
* Removes a header from the list of headers we track.
163
190
*
@@ -179,6 +206,8 @@ public function removeHeader(string $name): self
179
206
*/
180
207
public function appendHeader (string $ name , ?string $ value ): self
181
208
{
209
+ $ this ->checkMultipleHeaders ($ name );
210
+
182
211
$ origName = $ this ->getHeaderName ($ name );
183
212
184
213
array_key_exists ($ origName , $ this ->headers )
@@ -188,6 +217,35 @@ public function appendHeader(string $name, ?string $value): self
188
217
return $ this ;
189
218
}
190
219
220
+ /**
221
+ * Adds a header (not a header value) with the same name.
222
+ * Use this only when you set multiple headers with the same name,
223
+ * typically, for `Set-Cookie`.
224
+ *
225
+ * @return $this
226
+ */
227
+ public function addHeader (string $ name , string $ value ): static
228
+ {
229
+ $ origName = $ this ->getHeaderName ($ name );
230
+
231
+ if (! isset ($ this ->headers [$ origName ])) {
232
+ $ this ->setHeader ($ name , $ value );
233
+
234
+ return $ this ;
235
+ }
236
+
237
+ if (! $ this ->hasMultipleHeaders ($ name )) {
238
+ if (isset ($ this ->headers [$ origName ])) {
239
+ $ this ->headers [$ origName ] = [$ this ->headers [$ origName ]];
240
+ }
241
+ }
242
+
243
+ // Add the header.
244
+ $ this ->headers [$ origName ][] = new Header ($ origName , $ value );
245
+
246
+ return $ this ;
247
+ }
248
+
191
249
/**
192
250
* Adds an additional header value to any headers that accept
193
251
* multiple values (i.e. are an array or implement ArrayAccess)
@@ -196,6 +254,8 @@ public function appendHeader(string $name, ?string $value): self
196
254
*/
197
255
public function prependHeader (string $ name , string $ value ): self
198
256
{
257
+ $ this ->checkMultipleHeaders ($ name );
258
+
199
259
$ origName = $ this ->getHeaderName ($ name );
200
260
201
261
$ this ->headers [$ origName ]->prependValue ($ value );
0 commit comments