Likewise, I am going to be strict in what I do, and I'm not going to rely on a server to convert newlines to the HTTP 1.1 spec.
Why do you feel the need to output a response compliant to the HTTP spec when
you are not returning an HTTP response? You're returning a
CGI response, thus you should be concerned with following the
CGI spec, not the HTTP spec. So what does
the CGI spec say?
6.2. Response Types
The response comprises a message-header and a message-body, separated
by a blank line. The message-header contains one or more header
fields. The body may be NULL.
generic-response = 1*header-field NL [ response-body ]
It says headers are ended by a blank line, as delimited with "NL". Hmm, NL. Obviously means "new line", but what ASCII character sequence might that be?
6.3.4. Protocol-Specific Header Fields
The script MAY return any other header fields that relate to the
response message defined by the specification for the SERVER_PROTOCOL
(HTTP/1.0 [1] or HTTP/1.1 [4]). The server MUST translate the header
data from the CGI header syntax to the HTTP header syntax if these
differ. For example, the character sequence for newline (such as
UNIX's US-ASCII LF) used by CGI scripts may not be the same as that
used by HTTP (US-ASCII CR followed by LF).
Apache isn't capriciously translating
\n to
\r\n just for the sake of being permissive, the CGI spec says that CGI-supporting web servers "MUST" do this and
explicitly allows CGI scripts to use different line endings than those prescribed by the HTTP spec, even giving unix-style
\n-only line ends as an example of a possible alternative.
You can rely on servers to do this conversion because any server which doesn't is not compliant with the CGI spec.