I am creating a RESTful API in PHP, and have encountered a problem.
When the client is posting data to the server, the server should return:
Status code 201 CREATED
Header Location with the location of the new object
Content-Type application/xml
<SomeXmlData></SomeXmlData>
Dummy code, producing the problem on my computer:
<?php
header("Location: http://google.no/",true,201);
header("Content-Type: application/xml;charset=iso-8859-1");
echo "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>\n";
echo "<Jada></Jada>";
?>
The HTTP result is
HTTP/1.1 201 Created
Content-Type: text/html; charset=UTF-8
Location: http://google.no/
Server: Microsoft-IIS/7.5
X-Powered-By: PHP/5.4.5
X-Powered-By: ASP.NET
Date: Wed, 22 Aug 2012 13:52:57 GMT
Content-Length: 209
<head><title>Document Moved</title></head>
<body><h1>Object Moved</h1>This document may be found <a HREF="http://google.no/">here</a></body><?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Jada></Jada>
PHP automatically adds some HTML code, and HTML content-type to the response, because of the location header.
Because of this, my api won't work with its clients.
EDIT:
IIS 7.5 Windows 7 Proffesional
I am sorry to bear bad news, but look here:
Prevent IIS from changing response when Location header is present
Edit: Never did find an answer - I ended up switching to Apache
And it seems IIS has had its fingers into headers for a long time:
http://forums.iis.net/t/1158431.aspx
This is a bug in IIS FastCGI module. It will be fixed in Windows 7 RTM. We are also looking into possible ways for making this fix available for IIS 7.
Hopefully if the bugs are related (I expect they are), if you now have FastCGI, then the fix below could work. Otherwise, switching to PHP non-FastCGI module might also work, and it might be easier than throwing in with Apache.
http://support.microsoft.com/kb/980363
The solution was to create an IIS module, that rewrites the header "Custom-Location" to "Location" after FastCGI is done.
Then, FastCGI won't know that we are sending a Location header at all, and it won't modify my response.
The module:
string Location = context.Response.Headers["Custom-Location"] as string;
if (!string.IsNullOrEmpty(Location))
{
context.Response.Headers.Remove("Custom-Location");
context.Response.AddHeader("Location", Location);
}
PHP:
header("Custom-Location: http://google.no",true,201);
header("Content-Type: application/xml");
echo "<xml></xml>";
(still dummy code, not extremly correct code :) )
I had similar problem with WP REST API on IIS 8.5. Following html
<head>
<title>Document Moved</title>
</head>
<body>
<h1>Object Moved</h1>
This document may be found
<a HREF="[url-from-location-header]">here</a>
</body>
was added at start of every json returned with Location
header and status 201 Created
. Content-Type
was changed to text/html; charset=UTF-8
.
Adding cgi.rfc2616_headers = 1
in php.ini resulted with:
- clean body (json) without added html
- correct "Content-Type"
- "Location" header missing
- Status chaged to
200 OK
I wouldn't call this solution, this is more replacing one problem with another. Luckily this new problem in my situation was smaller than original one.