This just doesn't seem correct to me, so I'm looking for someone to tell me how I've misconfigured IIS... Configuration is IIS7.5 (2008R2), without SP1.
I have IIS 7.5 configured w/several sites. ALL sites have hostnames defined in the bindings, there is NO site w/out a hostname. However, if I request an unknown hostname from the server IIS (technically Microsoft-HTTPAPI/2.0) return a 404 error, not a 400 error. I would expect a 400 (or some other major error) rather than a lowly 404.
This causes a problem when I have nginx in front of multiple IISs and want to stop a site so nginx takes it out of rotation. Since IIS still returns a 404 for the request even when there is no active site for that name, nginx doesn't know the server is dead.
NB: IIS returns the 404 regardless of whether there is a server, but it's stopped, or there is no server.
Thoughts? Solutions?
-- Additional info: OK, I added a site on a port other than 80 (5000) and then on a connection to that port asked for a site that doesn't exist, and I get the expected error 400 (Invalid hostname). So, while IIS isn't listening for generic (no host name) connections on port 80 it would seem that something is. Any ideas how to get HTTPSys to dump the list of what it's listening for?
This is by design. A URL Reservation is not the same as a URL Registration, which happens dynamically when an application registers with HTTP.SYS to being listening. In the case of a URL Reservation, HTTP.SYS does not know whether the URL in a given Reservation is simply unavailable temporarily or does not exist at all. All it can know in this case is that there is a valid host name match (because of your strong/weak wildcard), but the URL path does not match for any currently registered listeners.
If you want a 400 or 503 response, then either do not use any URL Reservation, or use explicit URL Reservations that do not include wildcards. In short, if you configure HTTP.SYS such that it can match the prefix of the URL to any Reservation (including dynamic ones created via Registration), then it will either deliver the request to listening application (if the rest matches), or return a 404 if it can't find an active registered listener.
Another solution that may be simpler is to use the IIS service itself to manage sending a 503. To do this don't stop the site, but instead stop the Application Pool(s) associated with it. This will cause a fully qualified match to occur in HTTP.SYS (even with wlidcard URL Reservations), but will result in a 503 because there is no AppPool to deliver the request to.
Is there an active HTTP Module installed on the IIS instance you're not aware of which captures all requests?
Or did you forget that to stop the Default Web site (which comes with a standard IIS installation) active/running, then there is an empty binding.
The Default Web site standard binding is blank which means it accepts all HTTP host headers.
OK, after an "enjoyable" several hours with MS tech support, we're not in agreement as to whether this is a bug or not, but we are in agreement the problem stems from the presence of the "http://+5000/Temporary_Listen_Address/" which is added by WCF.
As a "workaround" if you add a more specific urlacl for your site in the format of: netsh http add urlacl url=http://hostname:80/ user=networkservice listen=yes delegate=yes
then you will get a 503, not a 404. I maintain this is a "bug", MS is "checking" (not holding my breath).
For those that hit this, the issue # is REG:112060473529066.
OK, figured it out (but I think it's a bug, need to report is to MS later). If I look at the URLACLs listed for HTTPSys using "netsh http show urlacl" I see a registration for "http://+:80/Temporary_Listen_Address/". This SHOULD NOT match the request I'm sending, but it seems to be matching. Per the documentation on UrlPrefix it wouldn't won't match, but per my tests it does.
When I created a new site on port 5000 there was no registration for the temporary_listen_address is all worked as I expected. With two sites (different host headers) running on port 5000 a request for a stopped site returns error 400. However, if I then register a urlacl (netsh http add urlacl) of "http://+:5000/test/" and request something that does not match that url prefix, I get a 404. Remove the registration and I get a 400 again.
I like HTTPSys in general, but it's damn complicated when you dig down into it. Will update w/MS's response later. I don't see a place on connect.microsoft.com to report it so I have to call.