Resolving HTTP Error 416 Requested Range not satisfiable (IIS 7.5 example)

The chaos called HTTP often surprises us with some new sweet little error that put us in not so satisfiable position. For example the anonymous HTTP error 416.

This error is product of mismatch between the client (for example browser) and the server regarding to the Accept-Ranges header tag. In particular this error emerges when the client is requesting a bigger resource similar to pdf files or images and awaits for the response of the server. The initial response could be fine but the streaming of the resource could fail. Why?

Accept-Ranges: bytes means that the request can be served partially. After the initial content-length parameter the server should provides us Content-Range tag (bytes size) in the response with every ‘partial’ request to keep the consistency of the stream. If this doesn’t work right, say hello to error 416. To be noted that this is highly influenced by how the client is implemented, not only the server.

To check if the server supports range header we could do a thing. Send HEAD request instead of GET to the wanted resource. If response 206 is returned range is supported. If the response code is 200 server side should change Accept-Range header to not foul clients.

Curl example: $ curl -i -X HEAD http://address/path/resource

Nevertheless let’s just solve the problem. Usually I notice this error in relation IIS -> Chrome or Apache -> Chrome. But it occurs on Firefox too.

Setting Accept-Bytes: none in IIS: Intenet Information Service (IIS) Manager -> Server Node -> Sites -> Problematic Site -> HTTP Response Headers (In IIS section) -> Add (Action) -> Name: Accept-Bytes; Value: none .

Setting Accept-Bytes: none in Apache2 : Enable apache2 mod_headers. Add “Header set Accept-Ranges none” in configuration of host.

Restart changes to take effect.

Have a nice day : )

Resolving error 413 (Request Entity Too Large/Not Allowed) in IIS 7.5

Working with IIS lately have brought me a lot of trouble, however it also increased my in-depth knowledge of its working abilities and adaptability.

One loving situation (between the minor ones) appeared after we did transition from http to https. After fixing the minor ones everything was working smooth and groovy except that sometimes the upload of files was broken. Then we realized it was not someTIME, but someTHING or the concrete size of the uploaded file that was causing the problem. Haa, so common problem when setting up Web Server you say, me said also, but this time the workaround was a little more pain in the *ss if you know what I mean.

The response given when uploading was an intelligent block by the Web Server resulting with error 413 – Request Entity Too Large. That doesn’t make a sense, I’m uploading  file that is 100KB but the settings allow max to 100MB file…

So with the help of rogue googling enabled by http://www.startpage.com I set my self digging into the problem overcome. One thing was clear, the trigger for this dysfunctionality certainly was https, since the uploading worked fine on http not secure. That gave me the rough but brilliant idea what https do. It encrypts, keeps extra request data, it certainly enlarges the request payload.

Hmm, OK first lets check the standard file limits in IIS.

Normal setting for max upload file size:

Setting the request limits in the root web.config of the site (default is 30 MB). This can be set in Internet Information Services Manager Program also (MACHINE->Site->IIS->Request Filtering->Edit Feature Settings)

<!– 100 MB . Format uses Bytes –>

<security>

    <requestFiltering>

        <requestLimits maxAllowedContentLength=”102400000″ />

    </requestFiltering>

   </security>

For ASP.NET you have more specific configuration:

http://msdn.microsoft.com/en-us/library/e1f13641%28v=vs.85%29.aspx

Example:

 <system.web>

   <httpRuntime maxRequestLength=”102400000″ executionTimeout=”3600″ />

 </system.web>

For legacy ASP:

<!– This goes under ASP – can be set with IIS Manager also 😉 –>

<limits maxRequestEntityAllowed=”102400000″/>

And here comes our solution:

http://www.iis.net/configreference/system.webserver/serverruntime

What we faced here is a buffer related problem. It’s not about the maxRequestEntityAllowed since the default size is Unlimited , but how IIS handles the request. After some empirics we noticed that the problem was occurring only with files larger or equal to 42 KB. And what is the default value of uploadReadAheadSize? 42 KB.

Then I charged myself to change this property. So I did the following:

Since we need to do section overriding through the means of <location> to change the default values (this configuration is not possible through IIS Manager)

<location path=”SiteName” overrideMode=”Allow”>

  <system.webServer>

   <asp>

    <session />

    <comPlus />

    <cache />

    <limits maxRequestEntityAllowed=”102400000″/>

   </asp>

    <serverRuntime enabled=”true” uploadReadAheadSize=”102400″ />

   </system.webServer>

</location>

However for some God sake reason, this configuration didn’t change the default values, even with overriding enabled for the serverRuntime section in the applicationHost.config . For easy check there is one good friend – the appcmd.

C:\Windows\System32\inetsrv\appcmd.exe list config “SiteName” -section:system.webServer/serverRuntime

And this bring us to the solution. To cut the story:

* Enable the serverRuntime section

C:\Windows\System32\inetsrv\appcmd.exe set config “SiteName” -section:system.webServer/ServerRuntime /enabled:”True” /commit:apphost

* Set the uploadReadAheadSize to 10MB

C:\Windows\System32\inetsrv\appcmd.exe set config “SiteName” -section:system.webServer/ServerRuntime /uploadReadAheadSize:”1024000” /commit:apphost

Restart if required, and that’s it.

Just aside note don’t forget to change the uploadReadAheadSize to something smaller and more realistic since 10MB is huge for a buffer, cause you don’t want to be hit by the nasty bad boyz with their huge payload packets.

Deploying Java Applications: Apache Tomcat + IIS 7.5

I’m on vacation and I’m writing my first technical post. That’s unfortunate 🙂

So this will be for all you lads and gentleman (and ladies) struggling in the world of Java and its ecosystem. Have you ever deployed Java apps on IIS? Well If I am the man to be consulted I’ll never choose that solution. But of course here comes the project managers, the Active Directory stuff and so on, when you have such climate you must bend yourself and do your best.

I have the following scenario: couple of different Java apps deployed on Tomcats. Well that doesn’t sound so bad there are easy service wizard installs of Apache Tomcat on Windows, easier deployment of the same so I will not really bother with such a trivial things, I hope you can do that by yourself.

Where is the problem? Well there a plural applications and one open port for the outside world. That’s right, the standard HTTP 80 port.

Simple thing we should do is to port forward and url rewrite the addressing applications.

Before finding this solution I was aware of one way on connecting Java container with IIS, through ISAPI and JK. But that requires changing Windows registry, defining couple of configuration files, using isapi_redirect , in other words messy and hardly-working solution. There are couple of guides on the net, just google it if you want to try them. The next solution is clean, simple and productive.

The IIS I’m working on is version 7.5. That is nice because the fellow Microsoft guys introduce a new solution to us, ARR. The use of this module here is to be set up to work as proxy server and that is exactly what we need in this situation.

After installing this extension on the server machine (I’m working on Windows Server 2008) next thing is to enable proxy server. Follow this steps:

  1. Open the IIS Manager and in the IIS Group there should be Application Request Routing Cache module showing up. Select it.
  2. So here we are. In the Action menu choose – Server Proxy Settings .
  3. For the following scenario this set up will work : Enable proxy = true, checked keep-alive, time-out by will, reverse rewrite host headers in response checked. Apply the changes and proceed.

Half work done. Next thing that we need is the URL rewrite feature. Install it. (Here I don’t mention  anything about the features and roles that need to be installed to make IIS working. I think that is just not-needed information here. You have the wizards in Computer Management, use them).

Well I hope you got URL rewrite working. That’s where we will define the rewrites.

Lets imagine. Two  Tomcat installation with just one application per server.

Installation folders: D:\Tomcat1 , D:\Tomcat2 . We need only the HTTP connectors, so in $tomcat_home\conf\server.xml you can comment out the AJP connectors.

Don’t forget while installing the Tomcats, to configure them on different ports. Example :

  <Connector port=”8080″ protocol=”HTTP/1.1″ proxyName=”www.example.com” proxyPort=”80″
               connectionTimeout=”20000″
               redirectPort=”8443″ />

  <Connector port=”8081″ protocol=”HTTP/1.1″ proxyName=”www.example.com” proxyPort=”80″
               connectionTimeout=”20000″
               redirectPort=”8443″ />

You ask yourself why I have put proxyName and proxyPort here. Well they are not required but since we want this application to work for outside world as I mentioned , you don’t want Java calls like getServerName() to return localhost  and local port. We want ajax and applets to work. This way we ensure the right host name and port are returned.

Installation ports: Tomcat1 on port 8080, Tomcat2 on port 8081. Installed apps: on Tomcat1 app1, on Tomcat2 app2.

So we can open the deployed applications on following urls : http://localhost:8080/app1 and http://localhost:8081/app2 .

It’s time to finalize the installations. We want the apps to be accessible on the following urls http://www.example.com/app1 and http://www.example.com/app2 .

This is where URL rewrite comes in play and that’s where we do the things explicitly. You can define URL rewrite rules in the main configuration but I prefer creating new site bound to port 80 and defining it there. Add new site with name exampe.com and for physical path put D:\ or whatever you want for your local situation, this is just example. That’s the place where web.config file will be created and everything that we do in the IIS manager will be mapped in configuration file, which is an xml configuration file the IIS use.

  1. In the new site, IIS group, open URL rewrite.
  2. Add new rule from the actions menu. Choose blank rule.
  3. Configurations : Name – Tomcat1 rule,  requested url -> matches the pattern , simple pattern: (app1.+) , ignore cases true,  action type – rewrite , rewrite url: http://localhost:8080/{R:0}
  4. Apply , make another rule for the other tomcat and  just change the name, pattern and the port.
  5. Restart IIS and you got it.

Just to get things straight. URL rewrite allow us to filter by some rule patterns, conditions and replace server variables. We just defined simple rewrite rule. That’s why we use {R:0} . It simple variable for the first rule pattern. There can be more of course , the format is {R:N} , where N is from 0 to 9.

This was very simple. I hope this will give you some clues how can you manipulate this modules to do more complex stuff. And you are not limited to use only Java servers of course. Any socket listening on any port can work.

I wish you happy days, for the end a reward from me