# [PATCH] Allow unsetting headers previously set by header()

- Thread: https://externals.io/message/36631
- Original archive: https://news-web.php.net/php.internals/36631
- Started by Christian Schmidt on 2008-03-27T22:32:05+00:00
- Messages: 6
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #36631 — Christian Schmidt — 2008-03-27T22:32:05+00:00

URL: https://externals.io/message/36631#36631

When a header has been set using header('Foo: bar') it can be replaced with 
other headers, but it cannot be removed.

For instance, one could imagine that the auto_prepend_file calls 
header('Vary: Accept-Language') because most pages do language-negotiation. 
But if a single file generates, say, an image, it would improve caching if 
the Vary header was removed. Setting it to the empty string using 
header('Vary:') is not equivalent to unsetting the header.

I suggest extending the behaviour of `header()` so that when the first 
argument does not contain a colon (and does not begin with "HTTP/"), e.g. 
header('Vary'), it unsets the header with the specified name.

AFAICT this change is backwards compatible. According to the HTTP spec, RFC 
2616, section 4.2, header lines must include a colon, so calling e.g. 
header('Vary') does currently not generate a valid header:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2

The attached patch contains an implementation for the cgi and apache2handler 
SAPIs.

AFAICT these SAPIs don't need to be changed:
cli, embed, isapi, milter, pi3web, thttpd, tux, webjames.

These SAPIs need additional patching:
apache, apache_hooks, apache2filter, continuity/capi, caudium, nsapi, 
phttpd, roxen
I don't have an easy way to test these SAPIs, so any help with adding 
support for them is appreciated. AFAICT some of these don't have full 
 `header()` support (in particular for the second $replace parameter), so it 
may not be a big issue if they aren't patched right away.

For some reason I couldn't build apache2filter on my machine.

The atteched phpt file is intended to be put in 
ext/standard/tests/general_functions.


What do you think of the general idea of being able to unset headers?
And what do you think of my patch?

This is my first patch for PHP. I am not a strong C programmer.


Christian

---

## #36634 — Richard Lynch — 2008-03-28T00:20:21+00:00

URL: https://externals.io/message/36631#36634 · In reply to: #36631

> When a header has been set using header('Foo: bar') it can be replaced
> with
> other headers, but it cannot be removed.

I like the idea of being able to "unset" headers.

I'm not sure I like the idea of calling what looks lik an invalid
 `header()` to unset one...

One might envision a future PHP that would want to, for example, say:

"Invalid header:  Header must start with [A-Z]:"

for somebody who does:

header($foo);

where $foo is some random typo string that's not a header at all.

At the risk of incurring the wrath of everybody else, I'd prefer to
see a new function like header_unset (or unset_header) to "undo" a
header.

Some questions I'd have about functionality:

If a header was not set, and then you unset it, is that an error or
 `E_NOTICE` or anything?

If you try to unset a header after the headers have gone out,
presumably the same nifty message about WHERE the header was set would
be output.

But then to be truly pedantic, what if you unset a header that was
never set in the first place, after the headers have gone out?  Is
this an error or any kind?

Just trying to anticipate all the edge cases. :-)

-- 
Some people have a "gift" link here.
Know what I want?
I want you to buy a CD from some indie artist.
http://cdbaby.com/from/lynch
Yeah, I get a buck. So?

---

## #36635 — Christian Schmidt — 2008-03-28T00:48:16+00:00

URL: https://externals.io/message/36631#36635 · In reply to: #36634

Richard Lynch wrote:
> At the risk of incurring the wrath of everybody else, I'd prefer to
> see a new function like header_unset (or unset_header) to "undo" a
> header.
Currently `header()` supports adding, replacing and appending to existing 
headers as well as specifying the response status code, so I think that 
adding a header_unset() would break the current tradition. But I wouldn't 
object to adding a new function, though this is probably above by skills.


> If a header was not set, and then you unset it, is that an error or
> `E_NOTICE` or anything?
No. I think that the current `header()` implementation relies on the 
reasonable assumption that the user don't need to know or care what headers 
are already set. For instance, by default existing headers are silently 
overwritten.

> If you try to unset a header after the headers have gone out,
> presumably the same nifty message about WHERE the header was set would
> be output.
Yes - the same error message is generated for header('Foo') and header('Foo: 
bar').

> But then to be truly pedantic, what if you unset a header that was
> never set in the first place, after the headers have gone out?  Is
> this an error or any kind?
Yes - `header()` always generates an error when called after the headers have 
gone out. This is analog to the current behaviour when setting a header that 
was already set.

> Just trying to anticipate all the edge cases. :-)
I appreciate that :-) I should probably add checks for these to the phpt.


Christian

---

## #36690 — Edward Z. Yang — 2008-03-30T20:05:13+00:00

URL: https://externals.io/message/36631#36690 · In reply to: #36631

Christian Schmidt wrote:
> What do you think of the general idea of being able to unset headers?
> And what do you think of my patch?

If you need this kind of flexibility, I recommend you make an
HttpHeaders class which manages these things and then sends them when
necessary.

-- 
 Edward Z. Yang                        GnuPG: 0x869C48DA
 HTML Purifier <http://htmlpurifier.org> Anti-XSS Filter
 [[ 3FA8 E9A9 7385 B691 A6FC B3CB A933 BE7D 869C 48DA ]]

---

## #36692 — Sam Barrow — 2008-03-30T21:05:51+00:00

URL: https://externals.io/message/36631#36692 · In reply to: #36690

> Christian Schmidt wrote:
> > […]
> headers?
> > […]
> 
> If you need this kind of flexibility, I recommend you make an
> HttpHeaders class which manages these things and then sends them when
> necessary.
> 

That's what I do. All you need is some simple functions:

$headers = array();

addHeader($name, $value) {
	global $headers;
	$headers[$name] = $value;
	return true;
}
deleteHeader($name) {
	global $headers;
	if (array_key_exists($name, $headers)) {
		unset($headers[$name]);
	}
	return true;
}
sendHeaders() {
	global $headers;
	foreach ($headers as $name => $value) {
		header($name . ': ' . $value);
	}
	return true;
}

---

## #36701 — Christian Schmidt — 2008-03-31T08:14:32+00:00

URL: https://externals.io/message/36631#36701 · In reply to: #36690

Edward Z. Yang wrote:
> If you need this kind of flexibility, I recommend you make an
> HttpHeaders class which manages these things and then sends them when
> necessary.

Thanks, I'll consider that for now. However, it has the downside that I 
have to make an explicit function call in every PHP file in order to 
send the headers. My use case is a site with an auto_prepend_file that 
sets a header that is relevant for almost all .php files on the site 
except a few that unsets the header.

So I hope people my patch for the PHP core will still be considered. I 
think the added functionality is in line with the existing functionality 
to replace and append to existing headers.


Christian
