I am a web developer who often switches between Apache and IIS hosted projects. Over the years, I have noticed one distinct difference between these two environments.
In Apache, if I know a page is going to take a while to load, I can prioritize output so that certain parts of the screen show first. Conversely, IIS waits until the entire page is finished loading before it shows any part of it.
Example:
<?php
echo "Hello ";
sleep(5);
echo "world.";
?>
In Apache, the above code would display "Hello", then 5 seconds later append "world." to it. In IIS - at least with its default settings - the browser would wait for 5 seconds and then display "Hello world." all at once.
Does anybody know why this happens? More importantly, given full admin access to the server, is there a way to force IIS to serve incremental content while it loads?
Things Tried So Far:
php.ini - output_buffering = Off
php.ini - implicit_flush = On
php.ini - zlib.output_compression = Off
IIS Output Caching - .php = Prevent all caching/Prevent all caching
FastCGI - the most common way to run PHP in IIS - is by default configured to buffer a certain amount of data before flushing it out to the browser; so we need to disable this buffer, or set responseBufferLimit to 0.
Unfortunately, Microsoft does not expose this option in FastCGI Settings, so we must change it directly in a file called applicationHost.config. You can search your server's hard drive for this file, or check in C:\Windows\System32\inetsrv\config\applicationHost.config
Open this file in a text editor and search for the section starting with <handlers. In this section, there should be an entry for your FastCGI instance. We need to modify this entry to add responseBufferLimit="0" as a parameter.
Before:
<add name="PHP_via_FastCGI" path="*.php" verb="GET,HEAD,POST", modules="FastCgiModule", scriptProcessor="C:\Program Files\PHP\v7.2\php-cgi.exe" resourceType="Either" />
After:
<add name="PHP_via_FastCGI" path="*.php" verb="GET,HEAD,POST", modules="FastCgiModule", scriptProcessor="C:\Program Files\PHP\v7.2\php-cgi.exe" resourceType="Either" responseBufferLimit="0" />
Alternatively, you can use a command line:
C:\Windows\SysWOW64\inetsrv>appcmd.exe set config /section:handlers "/[name='PHP_via_FastCGI'].ResponseBufferLimit:0"
where PHP_via_FastCGI is the Name assigned to your PHP handler. If you aren't sure, this can be found in the IIS Manager under Handler Mappings where Path contains *.php.
After you have Response Buffer Limit set to 0, restart IIS. Output should now be streamed to the browser as it is being produced.
Related
IIS 7.5 , 2008rc2, classic asp, 500 error msg:
The page cannot be displayed because an internal server error has occurred.
I need to know how to configure IIS to get a more detailed error.
I've tried setting to true all of debugging options in the ASP configuration.
But that didn't work. Can anyone help me?
I have come to the same problem and fixed the same way as Alex K.
So if "Send Errors To Browser" is not working set also this:
Error Pages -> 500 -> Edit Feature Settings -> "Detailed Errors"
Also note that if the content of the error page sent back is quite short and you're using IE, IE will happily ignore the useful content sent back by the server and show you its own generic error page instead. You can turn this off in IE's options, or use a different browser.
If you're on a remote server you can configure your web.config file like so:
<configuration>
<system.webServer>
<httpErrors errorMode="Detailed" />
<asp scriptErrorSentToBrowser="true"/>
</system.webServer>
<system.web>
<customErrors mode="Off"/>
<compilation debug="true"/>
</system.web>
Double click "ASP" in the site's Home screen in IIS admin, expand "Debugging Properties", enable "Send errors to browser", and click "Apply".
Under "Error Pages" on the home screen select "500", then "Edit feature settings" and select "Detailed Errors".
Note that the same steps apply for IIS 8.0 (Windows Server 2012).
After trying Vaclav's and Alex's answer, I still had to disable "Show friendly HTTP error messages" in IE
TLDR:First determine where in the pipeline you're getting the error from (scroll looking for screenshots of something that resembles your error), make changes to get something new, repeat.
First determine what error message you are actually seeing.
If you are seeing the file located here...
%SystemDrive%\inetpub\custerr<LANGUAGE-TAG>\500.htm
...which generally looks like this:
**...then you know you are seeing the currently configured error page in IIS ** and you do NOT need to change the ASP.net customErrors setting, asp error detail setting, or "show friendly http errors" browser setting.
You may want to look at the above referenced path instead of trusting my screenshot just in case somebody changed it.
"Yes, I see the above described error..."
In this case, you are seeing the setting of <httpErrors> or in IIS Manager it's Error Pages --> Edit Feature Settings. The default for this is errorMode=DetailedLocalOnly at the server node level (as opposed to the site level) which means that while you will see this configured error page while remote, you should be able to log on locally to the server and see the full error which should look something like this:
You should have everything that you need at that point to fix the current error.
"But I don't see the detailed error even browsing on the server"
That leaves a couple of possibilities.
The browser you are using on the server is configured to use a proxy
in its connection settings so it is not being seen as "local".
You're not actually browsing to the site you think you are browsing to - this commonly happens when there's a load balancer involved. Do a ping check to see if dns gives you an IP on the server or somewhere else.
Your site's httpErrors settings is set for "Custom" only. Change it to "DetailedLocalOnly". However, if you have a configuration error, this may not work since the site level httpErrors is also a configuration item. In that case proceed to #4
The default for httpErrors for all sites is set for "Custom". In this case you need to click on the top level server node in IIS Manager (and not a particular site) and change the httpErrors settings there to DetailedLocalOnly. If this is an internal server and you're not worried about divulging sensitive information, you could also set it to "Detailed" which will allow you to see the error from clients other than the server.
You're missing a module on the server like UrlRewrite (this one bites me a lot, and it often gives the generic message regardless of the httpErrors settings).
"Logging on to the server is not an option for me"
Change your site's httpErrors to "Detailed" so you can see it remotely. But if it doesn't work your error might already be a config error, see #3 immediately above. So you might be stuck with #4 or #5 and you're going to need somebody from your server team.
"I'm not seeing the error page described above. I'm seeing something different"
If you see this...
...and you expect to see something like this...
...then you need to change "Send errors to browser" to true in IIS Manager, under Site --> IIS --> ASP --> Debugging Properties
If you see this...
or this...
...you need to disable friendly errors in your browser or use fiddler's webview to look at the actual response vs what your browser chooses to show you.
If you see this...
...then custom errors is working but you don't have a custom error page (of course at this point were talking about .net and not classic asp). You need to change your customErrors tag in your web.config to RemoteOnly to view on the server, or Off to view remotely.
If you see something that is styled like your site, then custom errors is likely On or RemoteOnly and it's displaying the custom page (Views->Shared->Error.cshtml in MVC for example). That said, it is unlikely but possible that somebody changed the pages in IIS for httpErrors so see the first section on that.
In web.config under
<system.webServer>
replace (or add) the line
<httpErrors errorMode="Detailed"></httpErrors>
with
<httpErrors existingResponse="PassThrough" errorMode="Detailed"></httpErrors>
This is because by default IIS7 intercepts HTTP status codes such as 4xx and 5xx generated by applications further up the pipeline.
Next, enable "Send Errors to Browser" under the "ASP" section, and under "Error Pages / Edit Feature Settings", select "Detailed errors".
Also, give Write permissions on the website folder to the IIS_IUSRS builtin group.
try setting the value of the "existingResponse" httpErrors attribute to "PassThrough". Mine was set at "Replace" which was causing the YSOD not to display.
<httpErrors errorMode="Detailed" existingResponse="PassThrough">
One thing nobody's mentioned is as a very quick and temporary fix, you can view the error on the localhost of that web server.
You may also verify that if you changed your main website folder (c:\inetpub\wwwroot) to another folder you must give read permission to the IIS_IUSRS group in the new folder.
Fot people who have tried EVERYTHING and just CANNOT get the error details to show, like me, it's a good idea to check the different levels of configuration. I have a config file on Website level and on Application level (inside the website) check both. Also, as it turned out, I had Detailed Errors disabled on the highest node in IIS (just underneath Start Page, it has the name that is the same as the webservers computername). Check the Error Pages there.
Found it.
http://blogs.iis.net/ksingla/archive/2009/02/16/iis-7-5-updates-to-custom-errors-and-compression.aspx
run cmd as administrator, go to your system32\inetsrv folder and execute:
appcmd.exe set config -section:system.webServer/httpErrors -allowAbsolutePathsWhenDelegated:true
Now I can see detailed asp errors .
If you run the browser in the server and test your url of the project with the local ip you have received all errors of that project without a generally error page(for example 500 error page).
In my case it was permission issue.
Open application folder properties -> Security tab -> Edit -> Add
IIS AppPool\[DefaultAppPool or any other apppool] (if use ApplicationPoolIdentity option)
IUSRS
IIS_IUSRS
Double check the encoding of the asp file you are testing.
For instance if you created a file like below on a Windows Server Core 2019 :
echo "<%# LANGUAGE=Javascript %>" > test.asp
echo "<%Response.Write("test");%>" >> test.asp
Then test.asp will be encoded in Unicode, and requesting it will produce a 500 without any details.
Do a notepad test.asp, then click on "Save As..." and choose "ANSI" encoding to fix it.
I have a website which sits on a non-public domain and is delivered via a proxy through on a different domain. We're having some trouble with caching of content - this is an Umbraco site and making changes updates the pages if you hit the domain directly, but not through the proxy.
I've been informed that the proxy honours response headers and setting an eTag would fix the issue. Having looked into this I can see that IIS sets the eTag by default, and I can see this is working on static content i.e. .js, .css files like so:
However, if I visit a page on the site, for example /uk/products/product I don't see the eTag header.
Is this expected behaviour, should it only be working with those static content files or can I set this on the page to tell the proxy that it should recache?
The ETag HTTP response header is an identifier for a specific version of a resource. It lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content has not changed. Additionally,etags help prevents simultaneous updates of a resource from overwriting each other ("mid-air collisions").
If the resource at a given URL changes, a new Etag value must be generated.
Static content does not change from request to request. The content that gets returned to the Web browser is always the same. Examples of static content include HTML, JPG, or GIF files.
IIS automatically caches static content (such as HTML pages, images, and style sheets), since these types of content do not change from request to request. IIS also detects changes to the files when you make updates, and IIS flushes the cache as needed.
to enable caching in iis you could use iis output caching feature:
1)open iis manager. select site.
2)select the output caching feature from the middle pane.
3)select edit feature setting from the middle pane.
4)check the enable cache and enable kernel cache box and click ok.
if you want to set the ETag as blank you could also do by adding below code in web.config file:
<httpProtocol>
<customHeaders>
<add name="ETag" value="" />
</customHeaders>
</httpProtocol>
refer this below article for more detail:
Caching
To use or not to use ETag, that is the question.
Configure IIS Output Caching
I've read that IIS after version 7 automatically enables E-tags, however, I ran a Pingdom speed test and the report advised me to enable E-tags. I'm not sure that report is accurate, or the information I read about IIS 7 and newer may not be correct.
I'm running IIS 8 on Windows Server 2012R2, and I'm having an issue. I'd like to be able to host large files, but it's causing problems. If I put anything over ~400MB on it, then when I try to access that file from a browser I get a "404 file not found" error.
I should note that smaller files work fine. Any thoughts?
The problem could be that your MIME types need to be modified. From https://serverfault.com/a/78526/12894:
What is probably happening is that your server doesn't know that .war
is a type of file that needs to be downloaded rather than executed. It
then is run through your allowed Web Service Extensions for any
matches. If it doesn't find one, it throws a 404 error even though the
file does in fact exist.
If you set a MIME type for war files of type application/octet-stream,
that should resolve your issue.
See also the Microsoft article Requests for static files return 404 error (IIS 6.0)
Have you tried looking at the Web.config file for the maxrequestlength tag? The problem in this case is not the upload, but rather the request for the file, when the page is loaded. Look for the following line:
<httpruntime maxrequestlength="51200" executiontimeout="7200"/>
Where I set the second number to 2 hours (just a random timeout time) and the first number is the maximum file size that a page that needs the file can request. In this case, you can have 500Mb of upload size. This may fix it, however, there's also another section that you can edit, added in for security purposes:
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="524288000"/>
</requestFiltering>
</security>
Here, again you have 1024x1024*500=500Mb. This is edited in the session properties - you can do that through the Management Interface or through writing your own scripts. Have a look at MSDN here:
http://technet.microsoft.com/en-us/library/cc725820(v=ws.10).aspx
I have a ServiceStack project with ServiceStack Razor added. Any time I try and navigate to the root of the site, I'm getting redirected to /metadata.
This does not happen on my dev machine, only in my hosted environment (AppHarbor).
I do have a Default.cshtml in the root of my project.
Navigating to other URLs work fine: /default1.cshtml, /myservicewithviews
I've tried messing with the DefaultRedirectPath in my AppHost, but that didn't help.
Trying to force it DefaultRedirectPath = "default.cshtml" result in a redirect loop. Which makes sense.
What is causing this?
AppHarbor only publishes files marked "Content" when building projects (AppHb FAQ). This file was the only one not marked content and why I was only experiencing this in my hosted environment and could access all other content.
Not detecting a default document causes ServiceStack to set a RedirectHttpHandler to /metadata - shown around here
Another noteworthy point is that AppHarbor's load-balancer causes their internal port numbers to show up in ServiceStack URLs when performing things like Response Redirects.
To fix this problem, you add the following to your Web.Config:
<appSettings>
<!-- AppHarbor Setting to stop AppHb load balancer internal port numbers from showing up in URLs-->
<add key="aspnet:UseHostHeaderForRequestUrl" value="true" />
</appSettings>
You could also configure this setting in your AppHarbor config panel.
Have some strange behaviour regarding output caching in an ASP.NET 4 application on IIS 7.5. I've been able to repeat the problem simply on other empty setups, I'm certain this is a bug, but unsure how to report it to Microsoft.
A site in IIS responds to more than 1 domain, the .NET application examins the hostname, and produces content accordingly. For example, it may print the name of the request URL in a blank page. Eg, www.first-domain.com, and www.second-domain.com
The web.config has the appropriate caching, urlCompression, and httpCompression all turned OFF under the system.webServer node.
The aspx page sets the cache-control header for public, with either a future date for expires, or a max-age value.
Visiting www.first-domain.com outputs the page that successfully writes 'www.first-domain.com'.
However, visiting www.second-domain.com outputs a page that writes 'www.first-domain.com'.
Examining the failed-request-traces, System.Web.Caching.OutputCacheModule has found the cached output (even though the .config files have turned the function off), the cache has matched even though the request URL hostname are different, and thus the second request will output the results of the first request to the different domain for as long as the max-age/expiry was set for, before the correct page for the second-domain will appear.
Either setting cache-control to private, or removing the 'OutputCache' module in the web.config solves the problem, while maintaining the correct cache-control headers sent to the browser, but obviously, I can't take advantage of kernel caching when I need it.
I can't find any MSDN documentation on how the OutputCacheModule is configured.
Has anyone else experienced this issue, how can I go about enabling kernel caching and let it take into account URL Hostname (without separating the application to different sites in IIS).
Thanks.
Update:
Adding SetSlidingExpiration has no effect, as the kernal cache still caches the output regardless of the request hostname. The only scenario now is to either disable output caching, or run a duplicate instance of the app on each domain it will run - considering the drop in server performance this would result in vs. the increase of performance gained in using output caching, we decided to disable output caching for this app.
No answer has been provided after 9 months, and no solution has been found, only a workaround, perhaps this will be fixed in the next version of IIS greater than 7.5...
--
Adding SetSlidingExpiration has no effect, as the kernal cache still caches the output regardless of the request hostname. The only scenario now is to either disable output caching, or run a duplicate instance of the app on each domain it will run - considering the drop in server performance this would result in vs. the increase of performance gained in using output caching, we decided to disable output caching for this app.
I was having a very similar problem and no solutions here helped me.
TLDR: Forcefully removing the OutputCache module on the Web.config was the only solution I found.
My scenario was a little bit different.
I have CORS set up in Application_BeginRequest, answering Access-Control-Allow-Origin for specific hosts that call me (setting it to * has not been reliable).
My Controller also sets Cache-control: public for it's responses.
What I found
Whenever I set Cache-control: public, IIS forcefully caches the response. Breakpoints on either Application_BeginRequest or my Controller were never hit a second time.
Disabling output and kernel caching via IIS Manager as seen below would have me hitting the Application_BeginRequest breakpoints, but never got me into the Controller. Something was still caching responses.
This article suggested removing the OutputCache module from IIS would help.
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="OutputCache" />
</modules>
</system.webServer>
Doing so allowed me to hit my Controller, finally.
What would help even more
If someone from MS or not could shine a light whether there is a way to change this behavior. OutputCache could be useful in some parts of an application and unnecessary in others.
Beware
Maybe I'm(we're?) solving the wrong problem here.
Maybe IIS was taking over caching in this scenario because it should. Maybe proxies along the way between my server and the user would behave just like that in that exact scenario, and if that's the case then working around this on IIS is wrong. I'll have to figure that out and maybe you should too.
I have similar problem. I use custom url rewriter. I have pages example.com/articles and example.com/art-ANY_ID.html. Both url map to articles.aspx (in second example as articles.aspx?id=ANY_ID). It worked fine with ASP.NET 2.0 and Classic pipeline mode. After we have changed it to ASP.NET 4 and integrated mode, we have got strange behaviour: both url return identically output. It was any page like example.com/art-ANY_ID.html.
Now we removed <add extension=".html" policy="CacheUntilChange" kernelCachePolicy="CacheUntilChange" /> from section <caching enabled="true" enableKernelCache="true"> and it fine works. I not understand why http.sys cache it.
Have you find any explanations?