SOLVED: IIS - configuring it to serve out the new WebGL stack files - how?

TL,DR;
SOLUTION:

On my host I had to disable Dynamic compression,

In addition it (my browser?) seemed to be finicky about the charset
(.jsgz wanted application/x-javascript; charset=UTF-8)

I also had to register all 5 types in the mime section - not just the two in the original web.config or I got 404.3 errors

For some reason I did not get gzip attached to my RESPONSE HEADERS so I mangled together the following, which attempts to do all these things.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
  <rewrite>
  <rules>
  <rule name="Imported Rule 1" enabled="true" stopProcessing="true">
  <match url="(.*)Data(.*)\.js" ignoreCase="true" />
  <conditions logicalGrouping="MatchAll">
  <add input="{HTTP_ACCEPT_ENCODING}" pattern="gzip" ignoreCase="true" />
  </conditions>
  <action type="Rewrite" url="{R:1}Compressed{R:2}.jsgz" />
  </rule>
  <rule name="Imported Rule 2" enabled="true" stopProcessing="true">
  <match url="(.*)Data(.*)\.data" ignoreCase="true" />
  <action type="Rewrite" url="{R:1}Compressed{R:2}.datagz" />
  <conditions>
  </conditions>
  </rule>
  <rule name="Imported Rule 3" enabled="true" stopProcessing="true">
  <match url="(.*)Data(.*)\.mem" ignoreCase="true" />
  <action type="Rewrite" url="{R:1}Compressed{R:2}.memgz" />
  <conditions>
  </conditions>
  </rule>
  <rule name="Imported Rule 4" enabled="true" stopProcessing="true">
  <match url="(.*)Data(.*)\.unity3d" ignoreCase="true" />
  <action type="Rewrite" url="{R:1}Compressed{R:2}.unity3dgz" />
  <conditions>
  </conditions>
  </rule>
  </rules>
        <outboundRules>
  <!-- FIRST SETUP THE SWITCHES FOR THE RESPONSE ENCODING //-->
  <rule name="Rewrite JSGZ header" preCondition="IsJSGZ" stopProcessing="false">
  <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
  <action type="Rewrite" value="gzip" />
  </rule>
  <rule name="Rewrite MemGZ header" preCondition="IsMemGZ" stopProcessing="false">
  <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
  <action type="Rewrite" value="gzip" />
  </rule>
  <rule name="Rewrite DataGZ header" preCondition="IsDataGZ" stopProcessing="false">
  <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
  <action type="Rewrite" value="gzip" />
  </rule>
  <rule name="Rewrite Unity3DGZ header" preCondition="IsUnity3DGZ" stopProcessing="true">
  <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
  <action type="Rewrite" value="gzip" />
  </rule>
  <!-- AND SETUP THE MATCHES FOR THE RESPONSE ENCODING SWITCHES //-->
  <preConditions>
  <preCondition name="IsJSGZ">
  <add input="{PATH_INFO}" pattern="\.jsgz$" />
  </preCondition>
  <preCondition name="IsMemGZ">
  <add input="{PATH_INFO}" pattern="\.memgz$" />
  </preCondition>
  <preCondition name="IsDataGZ">
  <add input="{PATH_INFO}" pattern="\.datagz$" />
  </preCondition>
  <preCondition name="IsUnity3DGZ">
  <add input="{PATH_INFO}" pattern="\.unity3dgz$" />
  </preCondition>
  </preConditions>
  </outboundRules>
  </rewrite>
  <staticContent>
  <mimeMap fileExtension=".mem" mimeType="application/octet-stream" />
  <mimeMap fileExtension=".data" mimeType="application/octet-stream" />
  <mimeMap fileExtension=".memgz" mimeType="application/octet-stream" />
  <mimeMap fileExtension=".datagz" mimeType="application/octet-stream" />
  <mimeMap fileExtension=".unity3dgz" mimeType="application/octet-stream" />
  <mimeMap fileExtension=".jsgz" mimeType="application/x-javascript; charset=UTF-8" />
  </staticContent>
  <urlCompression doStaticCompression="true" doDynamicCompression="false" />
</system.webServer>
</configuration>

That one web.config needs dropping either in the root of the site you are hosting it on - or the main subfolder of the game you want to serve.

Whether or not you will need some or all of this I do not know.
I needed all of it.

Hope it helps someone. Massive thanks to philwinkel for his tireless efforts of assistance.


ORIG POST:

So I pored over the docs (such as they were, the ones I could find); Watched every video I could find about deployment (none actually useful); Tried web-searching; Read several, almost, related threads about web.config (the first part I posted below), Nothing actually seems to cover what I am experiencing.

I can not for the life of me figure out how to serve these files via IIS.
I think I have tried every permutation I can think of now of configurations (which isn’t admittedly many)

I get that there are some new file types. and they need mime registering. (see below)

I also observe that - through testing - unless I actually also allow the mime types of the .datagz .memgz .jsgz to be registered that they are not served. (I can find no reference to this requirement anywhere)

Here is what I have so far:

For some reason my latest build didn’t even spit out a web.config (a previous one did) - it is just a red plane and a green cube. nothing fancy.

In the web.config that was generated I have

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <staticContent>
            <mimeMap fileExtension=".mem" mimeType="application/octet-stream" />
            <mimeMap fileExtension=".data" mimeType="application/octet-stream" />
        </staticContent>
    </system.webServer>
</configuration>

and the .htaccess file (which is not IIS friendly directly but can be imported) says

Options +FollowSymLinks
RewriteEngine on

RewriteCond %{HTTP:Accept-encoding} gzip
RewriteRule (.*)Data(.*)\.js $1Compressed$2\.jsgz [L]
RewriteRule (.*)Data(.*)\.data $1Compressed$2\.datagz [L]
RewriteRule (.*)Data(.*)\.mem $1Compressed$2\.memgz [L]
RewriteRule (.*)Data(.*)\.unity3d $1Compressed$2\.unity3dgz [L]
AddEncoding gzip .jsgz
AddEncoding gzip .datagz
AddEncoding gzip .memgz
AddEncoding gzip .unity3dgz

which as far as I can tell is the same as 4 rewrite rules in IIS

(careful - when you import the rules directly via the IIS importer: the format will be wrong and it will be appending an extra / after the rewritten URL and before the filename - like /Compressed/fileuploader/.jsgz - so fix that by eliding the extra / from the rule.

You can jump on the actual server and run the requests locally to check the errors if you have it configured this way.

Here is a previous request for: http://kaycare.co.uk/games/WebGL/Data/fileloader.js
(requested directly)

I got the error:

HTTP Error 404.3 - Not Found
The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.

Module StaticFileModule
Notification ExecuteRequestHandler
Handler StaticFile
Error Code 0x80070032
Requested URL /games/WebGL/Compressed/fileloader.jsgz
Physical Path \games\WebGL\Compressed\fileloader.jsgz
Logon Method Anonymous
Logon User Anonymous

SO TO FIX THIS I MADE THE FILE BELOW

In addition it seems like then (as I was saying before) I have to also allow the various compressed types to be served?

I made this:

Which is a rewrite of http://forums.iis.net/post/1970627.aspx

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
     <rewrite>
         <outboundRules>
        <!-- FIRST SETUP THE SWITCHES FOR THE RESPONSE ENCODING //-->
             <rule name="Rewrite JSGZ header" preCondition="IsJSGZ" stopProcessing="false">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
            <rule name="Rewrite MemGZ header" preCondition="IsMemGZ" stopProcessing="false">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
              <rule name="Rewrite DataGZ header" preCondition="IsDataGZ" stopProcessing="false">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
            <rule name="Rewrite Unity3DGZ header" preCondition="IsUnity3DGZ" stopProcessing="true">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
             <!-- AND SETUP THE MATCHES FOR THE RESPONSE ENCODING SWITCHES //-->
            <preConditions>
                 <preCondition name="IsJSGZ">
                     <add input="{PATH_INFO}" pattern="\.jsgz$" />
            </preCondition>
                 <preCondition name="IsMemGZ">
                     <add input="{PATH_INFO}" pattern="\.memgz$" />
                 </preCondition>
            <preCondition name="IsDataGZ">
                     <add input="{PATH_INFO}" pattern="\.datagz$" />
                 </preCondition>
            <preCondition name="IsUnity3DGZ">
                     <add input="{PATH_INFO}" pattern="\.unity3dgz$" />
                 </preCondition>
             </preConditions>
        </outboundRules>
     </rewrite>
     <staticContent>
    <!-- AND MIME REGISTER THE TYPES //-->
         <mimeMap fileExtension=".jsgz" mimeType="application/x-javascript" />
        <mimeMap fileExtension=".datagz" mimeType="application/octet-stream" />
        <mimeMap fileExtension=".memgz" mimeType="application/octet-stream" />
        <mimeMap fileExtension=".unity3dgz" mimeType="application/octet-stream" />    
        <mimeMap fileExtension=".mem" mimeType="application/octet-stream" />
        <mimeMap fileExtension=".data" mimeType="application/octet-stream" />
     </staticContent>
</system.webServer>
</configuration>

To handle that bit. not sure I got it right?

However when I finally put all this in place I end up with an Illegal character complaint?

(because the zipped file is NOT a script one would assume) - so it’s now “serving” but not being “serviced”

Anyone who has any knowledge I would be very appreciative.

I did try out the “Answers” section for a day first, but this was drowned out in “How do I script” noise.

I see that this answer will have great value for all MS IIS7 users in the future and as such hope you will forgive a little cross-posting. I waited a decent time.

Kind regards,

Much confused.

2 Likes

So what’s happening exactly? In your browser’s network tab, look at the requests for those files - what kind of response is the web server sending?

If it’s a 404.3 error - mime type missing, then you just need to add the mime types to your application root web.config:

I see you already did that for the .mem and .data mime types, but perhaps you should add all the unique file extensions that a unity webgl will serve?

I’m kind of confused why you are doing rewrites? If the unity webgl build creates static files, you shouldn’t have to use any rewrites?

What are you running on IIS, is it ASP. NET web forms, MVC, if so what version of ASP MVC, etc.

Or post a URL and I can take a look. That’s just off the top of my head; I haven’t used WebGL export yet so I’m not familiar with the different files it exports.

Hi, thanks.

in the hidden under the scrollbar code I did that

.... stuff elided

     <staticContent>
   <!-- AND MIME REGISTER THE TYPES //-->
         <mimeMap fileExtension=".jsgz" mimeType="application/x-javascript" />
       <mimeMap fileExtension=".datagz" mimeType="application/octet-stream" />
       <mimeMap fileExtension=".memgz" mimeType="application/octet-stream" />
       <mimeMap fileExtension=".unity3dgz" mimeType="application/octet-stream" />
       <mimeMap fileExtension=".mem" mimeType="application/octet-stream" />
       <mimeMap fileExtension=".data" mimeType="application/octet-stream" />
     </staticContent>
</system.webServer>
</configuration>

that was my thought also.

I do the rewrites as that is the unity way of doing things. as outlined in the top post in the section starting

“and the .htaccess file (which is not IIS friendly directly but can be imported) says:”

Thanks very much for answering though!!! I really appreciate any input.

RE THE SERVER: Vanilla 2008 Datacenter edition. so… .Net web forms I guess.
I have full access to the servers configs.

3 Likes

np, in a nutshell I think you just add mime types and configure compression in webconfig. I don’t think any rewrites should be necessary. I’m not familiar with the htaccess importer, I’d probably just configure it manually and skip the htaccess.

As for compression in IIS7, this post may be helpful:

(just skimmed it, seemed about right)

Yup, read that one.
Tried it. Compression is on and working fine.

Here is a quick precis

this is what I did:

  1. Upload to server (I was not clear if I had to actually upload the two huge .mem and .data file in /DATA, from my reading of the rewrite rules below, “No, I do not have to” since all requests for those files will be redirected to their pre-compressed cousins. (but I did anyways to be sure)

  2. checked that the web.config was being honoured to serve out the .mem and .data stuff (I also actually tried hard-coding the MIME TYPES just for sanities sake, yup, web.config or hard coded is same) EDIT <— ACTUALLY In the end I had to hard code them.

  3. Imported the rules into URL rewrite via the IMPORT RULES button and double checked they were sensible. They all seemed fine - 4 rules - redirecting unzipped requests to zipped equivalents. (they need little fix though as outlined in top post)

  4. Checked that the server has dynamic and static compression installed and enabled for the domain (which it does)

  5. revisited the .htaccess to see what I had missed.

It’s the final bit where in the .htaccess it would have been handled by:

AddEncoding gzip .jsgz AddEncoding gzip .datagz AddEncoding gzip .memgz AddEncoding gzip .unity3dgz

I /think/ it is this bit maybe where it goes wrong. Not sure how to do this is IIS?

I will upload a tiny test project so people can see the errors. http://kaycare.co.uk/games/WebGL/

well fixed all the errors I could find and ended up with
“NetworkError: 404 Not Found - http://kaycare.co.uk/games/WebGL/Data/UnityProgress.js”
again. Sigh…

Will keep digging.

it looks like something must be messed up in the web.config. all static files are throwing 500’s. you may want to turn on customErrors so you can see the IIS error.

“RemoteOnly” will allow you to remote into the server and check the response, if it’s a staging environment where you don’t care, you can set it to “On”

Yup. Many thanks - I have fixed particular error now. It was a stray character in the xml. Doh

However the real issue appears to be:

HTTP Error 404.3 - Not Found
The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.

which I clearly have done.

I will go hard code them in the IIS config instead and rip the web.config again. sigh.

Thanks for looking. Driving me potato cakes

Okay so, Finally, I have the files serving.

The STATIC section of the web.config was not being honored. Putting the MIME types into IIS finally allowed the files through BUT now they appear to not be being unencoded at my side.

Sigh.

application/x-javascript was the type I put on the .jsgz files… is that wrong?

UnityProgress.js:1 Uncaught SyntaxError: Unexpected token ILLEGAL
UnityConfig.js:1 Uncaught SyntaxError: Unexpected token ILLEGAL
fileloader.js:1 Uncaught SyntaxError: Unexpected token ILLEGAL
WebGL.js:1 Uncaught SyntaxError: Unexpected token ILLEGAL

Pretty sure that means I am being served the zipped js file now. and it isnt being parsed?


The responses all look okay server side?

and by accessing kaycare.co.uk/games/WebGL/data/fileloader.js you can now see a zipped version appearing…

I just did a test WebGL build in ASP MVC 4 website:

Due to the directory structure of MVC I changed some relative paths for “Data/” to “/Data/” in the index.html file that the webgl build spits out.

As expected 403.4 errors on the MIME types that I have not configured in my web.config yet,

Added the MIME maps to the web config:



That was enough to get the build running (albeit without compression)


For compression… I’ll try deploying to my shared web host, as I don’t want to change IIS express configuration right now. I’m just using standard web.config compression, relevant web.config is as follows:

  <system.webServer>

..

    <staticContent>
      <mimeMap fileExtension=".data" mimeType="application/octet-stream" />
      <mimeMap fileExtension=".mem" mimeType="application/octet-stream" />
    </staticContent>
    <httpCompression directory="%SystemDrive%\inetpub\temp\IIS Temporary Compressed Files">
      <scheme name="gzip" dll="%Windir%\system32\inetsrv\gzip.dll"/>
      <dynamicTypes>
        <add mimeType="text/*" enabled="true"/>
        <add mimeType="message/*" enabled="true"/>
        <add mimeType="application/javascript" enabled="true"/>
        <add mimeType="*/*" enabled="true"/>
      </dynamicTypes>
      <staticTypes>
        <add mimeType="text/*" enabled="true"/>
        <add mimeType="message/*" enabled="true"/>
        <add mimeType="application/javascript" enabled="true"/>
        <add mimeType="*/*" enabled="true"/>
      </staticTypes>
    </httpCompression>
    <urlCompression doStaticCompression="true" doDynamicCompression="true" />
  </system.webServer>

I pretty much picked that up off some website somewhere. I think this part should enable compression on everything…

and it appears to be gzipping and serving all the files,

I’m not using any rewrites, I think that was specific to wahtever configuration the unity people were using. Although, I think my configuration is not using the files from the “compressed” directory. Those must be pre-gzipped or something. I’ve never done that, I’ve always had my web server do the gzipping and have the server cache the response. I’ll have to see about that next…

The rewrites are to enable the huge versions of the files to be replaced “pre-realtime” with the pre-zipped versions of the files. Since zipping 124mb everytime someone wanted to play your game would soon kill your server.

(they should be in the compressed folder)

Well, it sounds like I am right at the very verge of getting this thing working.

Although I am back at exactly the same point I was when I started this thread.

.jsgz files being served. Nothing else happening once they are returned. I must have them encoded wrong or something stupid. will keep digging then. thanks for your tips.

RE POST: Aye I remember that post from years ago, probably when I first did gzip stuff in my own apps.
I have actually written custom http handlers in the past, - that used gzip - unbelievably, looking at the total lack of understanding going on today.

Brain getting old. Will give this yet another go.

i’ll try to get it working with the compressed files, are you using ASP MVC?

Vanilla 2008 server. IIS 7.5, whatever came on that.

Model View Controller? Errrr… Honestly I don’t know. Pretty sure that post dates the servers birthdate.

I only use this box to shove out files and the occasional, very lightweight, Asp .Net programming job.
It’s just a file workhorse. Hence me being pretty unsure about its potential guts.

EDIT: Hmm I seem to recall that stuff came out about a year after the server did. so I doubt it.

I think the rewrites are not adding the correct HTTP header to the response, that should tell the browser it’s using compression. It should be something like “content-encoding: gzip” or whatever.

It seems like the browser doesn’t realize that the response is gzipped, and it’s getting all this crazy garbled gzipped javascript data that it can’t understand. Therefore the “unexpected token” errors

there’s no content-encoding header in the response, so the browser just tries to read it without decompressing and it looks like this:

Yup, my thoughts too.

Except it says here that I am sending that header back

Quite the mystery.

So I elided the bit of web.config trickery I posted in the top post, so as to NOT pass back the gzip header. Same thing. Not processed. gah :smile:

I also tried the application/javascript type just in case.

it still doesn’t seem to be passing Content-Encoding header back to chrome at least. It’s weird that it’s working in firefox… When you look at the response, does it look like javascript?

nope, still junk. compressed junk.

    <rewrite>
         <outboundRules>
             <rule name="Rewrite JSGZ header" preCondition="IsJSGZ" stopProcessing="false">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
            <rule name="Rewrite MemGZ header" preCondition="IsMemGZ" stopProcessing="false">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
              <rule name="Rewrite DataGZ header" preCondition="IsDataGZ" stopProcessing="false">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
            <rule name="Rewrite Unity3DGZ header" preCondition="IsUnity3DGZ" stopProcessing="false">
                 <match serverVariable="RESPONSE_Content_Encoding" pattern=".*" />
                 <action type="Rewrite" value="gzip" />
             </rule>
            <preConditions>
                 <preCondition name="IsJSGZ">
                     <add input="{PATH_INFO}" pattern="\.jsgz$" />
            </preCondition>
                 <preCondition name="IsMemGZ">
                     <add input="{PATH_INFO}" pattern="\.memgz$" />
                 </preCondition>
            <preCondition name="IsDataGZ">
                     <add input="{PATH_INFO}" pattern="\.datagz$" />
                 </preCondition>
            <preCondition name="IsUnity3DGZ">
                     <add input="{PATH_INFO}" pattern="\.unity3dgz$" />
             </preCondition>
             </preConditions>
        </outboundRules>
     </rewrite>

without those it does not send those gzip headers, period. so either that is somehow affecting the wrong output and I need to put it somewhere else… Like in the main IIS config? I have zero idea how to do that though.

did you get yours going? the compressed one?

http://stackoverflow.com/questions/23600229/what-content-type-header-to-use-when-serving-gzipped-files

Seems like this is similar, but only cos he has put the wrong type in…

Maybe the type is not being parsed. bah. I dunno.

Chrome seems to be getting the headers now as far as I can see, neither it, nor firefox, honor the flag.

Well since those files are precompressed, maybe you should disable httpCompression on them in web config. It’s possible they are getting double compressed.

In which case the browser would decompress and itd still look like garbage.

1 Like

ooh
Good call. will try that…

Sigh. Sadly not.

<configuration>
<system.webServer>
        <urlCompression doStaticCompression="false" doDynamicCompression="false"/>
...

tried in all relevant locations, cache cleared between each or disabled as appropriate. Chrome/ff

Really good thought though.