Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blazor/Wasm games with Brotli compression/decompression are broken. #1512

Open
nkast opened this issue Nov 26, 2023 · 3 comments
Open

Blazor/Wasm games with Brotli compression/decompression are broken. #1512

nkast opened this issue Nov 26, 2023 · 3 comments

Comments

@nkast
Copy link

nkast commented Nov 26, 2023

Recently html games that are written in Blazor/Wasm stopped working.
The reported game is https://kwyrky.itch.io/blazorwasmgame1
My own game has the same issue: https://nkast.itch.io/alienexterminator

Those games were written in KNI, a C# game framework, and make use of the decode.js library to uncompressed the *.br files generated by Blazor webassembly.
host-and-deploy webassembly-compression

The error occurs in this line where BrotliDecode(...) is called to decompress '_framework/blazor.boot.json.br'.
decode.js throws a '"Corrupted padding bits"'

Http-Request

GET /html/7196597/_framework/blazor.boot.json.br HTTP/2
Host: html-classic.itch.zone
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:120.0) Gecko/20100101 Firefox/120.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: https://html-classic.itch.zone/html/7196597/index.html
DNT: 1
Sec-GPC: 1
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
Pragma: no-cache
Cache-Control: no-cache
TE: trailers

Http-Response

HTTP/2 200 
x-guploader-uploadid: ABPtcPqBqJFTH65zHX9-vY4tOHJze-OlHY8uyzNhiZF1tqlkcl4g6qTVAoYrCtr2aYhwNao40wY
last-modified: Sat, 21 Jan 2023 02:31:15 GMT
etag: "b68ade5c91657c3c379bb1190c50e571"
x-goog-generation: 1674268275595169
x-goog-metageneration: 1
x-goog-stored-content-encoding: br
x-goog-stored-content-length: 3132
content-type: application/json
x-goog-hash: crc32c=Z0F9oQ==
x-goog-hash: md5=toreXJFlfDw3m7EZDFDlcQ==
x-goog-storage-class: STANDARD
server: UploadServer
content-encoding: gzip
content-length: 3384
cache-control: public, max-age=2157
date: Mon, 27 Nov 2023 09:16:26 GMT
vary: Accept-Encoding
X-Firefox-Spdy: h2

{
  "cacheBootResources": true,
  "config": [ ],
  "debugBuild": false,
  "entryAssembly": "WebGLxna",
  "icuDataMode": 0,
  "linkerEnabled": true,
  "resources": {
    "assembly": {
      "Aether.Components.dll": "sha256-Cyj7\/zMrN2LTKO43UoeNFLBcazRZ6cJJNbL1rYAO9Ys=",
      "Aether.dll": "sha256-QIrKQ0FXbFxIMQdsYQPJCEOVAs85EtNMjAxVAmPAUY8=",
      "Aether.Particles.dll": "sha256-TrBvk5FcMDAkKbfmmlTqQGHIkAP2yY0L8V+2S0VnFxQ=",
      "Aether.Physics2D.Components.dll": "sha256-we+CVYT9Llx\/5rJYTZKFvC9KSlJnbZr4SExekQ1fipk=",
      "Aether.Physics2D.dll": "sha256-atwP6WdbA+OrkLSPdqDWizsTnQYLpsZn+fI52FFYOs0=",
      "MGJ3.Components.dll": "sha256-kxsmOwDF9HQgkIzuphBuZ5sRlcs0DeOOYyzNYPyGS5g=",
      "Microsoft.AspNetCore.Components.dll": "sha256-xv2jmxV8msKL2kdZk\/R+YdrKMoN55RbhYmXvPKTTgW4=",
      "Microsoft.AspNetCore.Components.Web.dll": "sha256-qU3IAmEqXKihCR1jmqNwiQI3vuEaPjNm9Fl+CA7mchs=",
      "Microsoft.AspNetCore.Components.WebAssembly.dll": "sha256-2n94FDGpkN1cvoXLu6PLx58lOudbge2yTEEF195Di30=",
      "Microsoft.Extensions.Configuration.Abstractions.dll": "sha256-yNUivmV4a48Mkbc1Sz+XJ9Y8moJKjWJo6Z0haFMFrKQ=",
      "Microsoft.Extensions.Configuration.dll": "sha256-OWH+xkIa4nRWGQutqm7dxgAY22jFGJlC+P6RzpDPrBE=",
      "Microsoft.Extensions.Configuration.Json.dll": "sha256-boSewHLerYdMMQk1EahIMSbAXSrf7Kgky4CGjZ3uuto=",
      "Microsoft.Extensions.DependencyInjection.Abstractions.dll": "sha256-eGWqw+M+dcThgPODjYDXobi9osfn3x1sGnbNgacKzbI=",
      "Microsoft.Extensions.DependencyInjection.dll": "sha256-azTt1JLi4RL0qaUPW8um+3BlO1IxYfZUaUP+kmJ6E6Y=",
      "Microsoft.Extensions.Logging.Abstractions.dll": "sha256-HvvXTIFdkrXJb\/BAlYnHIU4556GzDx2XYYQnhnWsP9I=",
      "Microsoft.Extensions.Logging.dll": "sha256-uvQcmI6XrSMo7BLb8B56Haq\/wjzfQPy1LJw48RmEmDs=",
      "Microsoft.Extensions.Options.dll": "sha256-T5jVw2iu5DWOW7fDB+sTItI3LDyjsz2wT4pCJl0cma8=",
      "Microsoft.Extensions.Primitives.dll": "sha256-Kk9trPYi6xuop+bJh7AertZVcNJkEyzyxW3andlyf5U=",
      "Microsoft.JSInterop.dll": "sha256-FmWkCNSUWh9oEGa1sKhfxQ\/3ydOlciEtF2lyI3hUKbI=",
      "Microsoft.JSInterop.WebAssembly.dll": "sha256-5rjENboVhqNLvFRQlepT4PYJ6Jo8jamVzm\/ujRo7Qd4=",
      "Monogame.Framework.dll": "sha256-udgVebSPs4OPrt5\/KrZf1Y982kMqt8uauUxOV96cbT8=",
      "netstandard.dll": "sha256-Y2RIgX8tF9CAsEJMPEo5IRCcGfoiHDNSsbU3fQ+g8rw=",
      "nkast.Wasm.Audio.dll": "sha256-j55hKWN0pxGjNQMPQK1cUlJoKyk9DZI4vwjxZQXru3M=",
      "nkast.Wasm.Canvas.dll": "sha256-+kIcf7Lh97eDebaKgg2kitRIFXlhN1lgdwlR+9N5y90=",
      "nkast.Wasm.Dom.dll": "sha256-htsmTghA9VYd3vz6u5ASzEctD5v+6+VbTF9qEzMuW1s=",
      "nkast.Wasm.XHR.dll": "sha256-oJpMDhHHsNmkS2WlDOVDcKVKiu4CADSsuL5eetCS6MU=",
      "System.Collections.Concurrent.dll": "sha256-XA52uX8TsjI9GZvSs02xcL9+ZexFANf0kvVZt+7o1OU=",
      "System.Collections.dll": "sha256-wJLnuawl7JIy+eZKhIyN5dwcakAFh4JWM6OMnQ3JAR4=",
      "System.Collections.NonGeneric.dll": "sha256-vAsxWU+7\/JufyHiXYFuyODHJFd\/HXeEiUHgFruPvbu4=",
      "System.Collections.Specialized.dll": "sha256-Zf8F7ZibhacBKk2ZD6zb6ft8zggv5xJU+NGRvZICezY=",
      "System.ComponentModel.dll": "sha256-1VjKvt9RUXsCbk2ICef0i1HEnLOupAC17JQmeJ\/ysDM=",
      "System.ComponentModel.Primitives.dll": "sha256-P+j\/5aboYiwq+20LYFevMUuMvau3aUxsV6+XBxIRbMc=",
      "System.ComponentModel.TypeConverter.dll": "sha256-xZ1s9OWeIe1QezJmj8OMOYBtPgtTHIo1rFlvQLi04mY=",
      "System.Console.dll": "sha256-1kJZZ5hAU9rQnMGsSxJqK1+IcK5VcgsO\/PgvHZ3sRsQ=",
      "System.Diagnostics.TraceSource.dll": "sha256-QQOK8atu7lt9vtKjzv3LcAKA74UnVMFCl3yXgHmfmtg=",
      "System.dll": "sha256-3Dx96Y+RlO\/k82GuDMLHREDY0XtFkReumxgF4OwQta4=",
      "System.Drawing.dll": "sha256-QSugHe2cbrehw8VEdBp11vqYVGYlsrIcsksevcxBTzU=",
      "System.Drawing.Primitives.dll": "sha256-Pz7IUwSMaP3D3d24nAQO8Gm4S2\/BcnT85+bMTtVBuAQ=",
      "System.Linq.dll": "sha256-PuEOeyYuI2ud9UPsZaYw6tdyY2J+TpYf60a8GRAsxj8=",
      "System.Linq.Expressions.dll": "sha256-C9Gi327cS+1BCm1M+2d4MAcTWam4Naqeu334pNjkfyM=",
      "System.Memory.dll": "sha256-Xi5ebfW554K0XPO+TJQ4E7cZRlFnGZEGI7+PfZsfmlc=",
      "System.Net.Http.dll": "sha256-Zu0C3iUH3OHFUVtabzrRYz0ciMk3WWcaJd9dKuoznvE=",
      "System.Net.Primitives.dll": "sha256-J9wrX+oYnAGov96QQeFR5+lB2h\/wnToRYynILnOhJQc=",
      "System.ObjectModel.dll": "sha256-MW65WUXA8yjRIJ6974HBqiURS827HbM3\/NE0MifdRXo=",
      "System.Private.CoreLib.dll": "sha256-fFZ9+G47qIdYr3QvBuwTh463T5fJJbn7Qc5SYTXQS0Y=",
      "System.Private.Runtime.InteropServices.JavaScript.dll": "sha256-F1pGM1l\/0Byi+8eAlus5ZuglMGoMTcjgOwU7gbstBoI=",
      "System.Private.Uri.dll": "sha256-HlyFP2Jc7vHMc19Ktb+hbmZ1weKvW6Ja7i3JKvASTZk=",
      "System.Private.Xml.dll": "sha256-OORGpQ2DVHI6cx29ueh+NlPzYok\/Nq9C+3JUdcHeO90=",
      "System.Runtime.CompilerServices.Unsafe.dll": "sha256-Cor0KCrsvgrEKmpSxuHFQcWmmm0sJn\/NiRRKNI1OLSk=",
      "System.Runtime.dll": "sha256-eZA4\/OkpKE2fUkRfUcEqsiZBVyK\/C+7r2mKdZfvdeGc=",
      "System.Runtime.InteropServices.dll": "sha256-t3lctenFHR2Quc2QH7iSvdp6Nb49ngNVewQoZOft3RU=",
      "System.Runtime.Serialization.Primitives.dll": "sha256-IfNOEC1cMK1T068Wc9XKU4TlTZnCTKqSgDOXwE7WKdw=",
      "System.Security.Cryptography.Algorithms.dll": "sha256-SCXk2hFmLNy6insstik\/lGXs2m1zGGcAFqlf0wdvK\/M=",
      "System.Security.Cryptography.Primitives.dll": "sha256-VXl2N89JxdrjAUAjVcRFd7Mdci75tWW9EwCyZnKCmgc=",
      "System.Text.Encoding.Extensions.dll": "sha256-ocu2wtdNl7+oATXgh5V8ka2TWcg7RIyMkDkoOXDwVUI=",
      "System.Text.Encodings.Web.dll": "sha256-oUsmj73hwCUgOH1k3iNuvk2WZyKwOYVokxswyU7aNGA=",
      "System.Text.Json.dll": "sha256-wg7PSZVulfoSRxzumuIvqLNyI4ZngUVHjl0NT95ltmM=",
      "System.Text.RegularExpressions.dll": "sha256-SH5KNXYrOWgyQa3d\/uuc8Q5u9rXgsOVo3s2cpg\/i5kY=",
      "System.Threading.dll": "sha256-20PawtJ+\/wVpj9n1mYzo2FtjKtWH6Y38WAVWsGnRbEg=",
      "System.Threading.Tasks.Parallel.dll": "sha256-37t4+NXpUX\/625TtjjslEjnMtNXn+xWvaDZGhMLsUS8=",
      "System.Threading.Thread.dll": "sha256-VxJMSz2ebd0Kif\/yGqDSFlVu6J2DJKqZZipJ8bLC2GU=",
      "WebGLxna.dll": "sha256-vEeZLHRqaEYA\/LPcrvH1aSicGZVIDhaifdzMd1Zry9E=",
      "XNALibrary.NETSTANDARD2_0.dll": "sha256-xDokAhrH2R2ejQN2N2LASQIA+q\/8f5PhugexUBkX5SE="
    },
    "extensions": null,
    "lazyAssembly": null,
    "libraryInitializers": null,
    "pdb": null,
    "runtime": {
      "dotnet.6.0.13.d3s7d5xanr.js": "sha256-socY77ojRqzllaVfYYgopToXg9oEaDSaOf84P87brGM=",
      "dotnet.wasm": "sha256-\/j2D4Jx0xps0WGMa82OJji+UzMImJIgvLSkYHLp6uQY=",
      "icudt.dat": "sha256-Zuq0dWAsBm6\/2lSOsz7+H9PvFaRn61KIXHMMwXDfvyE=",
      "icudt_CJK.dat": "sha256-WPyI4hWDPnOw62Nr27FkzGjdbucZnQD+Ph+GOPhAedw=",
      "icudt_EFIGS.dat": "sha256-4RwaPx87Z4dvn77ie\/ro3\/QzyS+\/gGmO3Y\/0CSAXw4k=",
      "icudt_no_CJK.dat": "sha256-OxylFgLJlFqixsj+nLxYVsv5iZLvfIKMpLf9hrWaChA="
    },
    "runtimeAssets": {
      "dotnet.wasm": {
        "behavior": "dotnetwasm",
        "hash": "sha256-\/j2D4Jx0xps0WGMa82OJji+UzMImJIgvLSkYHLp6uQY="
      }
    },
    "satelliteResources": null
  }
}
@nkast
Copy link
Author

nkast commented Nov 27, 2023

I updated the http request/response as captured by Firefox.
I also removed the .gz files from the Web.zip of my game and re-uploaded.

I requested both 'blazor.boot.json' and 'blazor.boot.json.br':
both files return as gzip compressed,

content-encoding: gzip
content-length: 3384

There is a difference in the 'x-goog-stored-content' headers
blazor.boot.json:

x-goog-stored-content-encoding : identity
x-goog-stored-content-length : 7054

blazor.boot.json.br:

x-goog-stored-content-encoding : br
x-goog-stored-content-length : 3132

The file I finally get from the fetch() method is the plaintext of 'blazor.boot.json' !
It is clear that the server,

  1. decompress the 'blazor.boot.json.br' file on the fly. (???)
  2. Recompress it as gzip on the fly.

What I would expect is to receive the compressed brotli content of 'blazor.boot.json.br' in the response body.
Regardless of whether it goes through gz compression or not.
There has to be a recent change on the server configuration because everything was working fine a while ago.

@leafo
Copy link
Member

leafo commented Nov 27, 2023

Thank you for the detailed report.

Our old CDN company was bought out by Akamai and we had to migrate to their platform last week (Full migration completed on Nov 22). Unfortunately, the integration Akamai provided subtly (and no so subtly) failing us in many ways.

I'll go through the configuration to see if I can identify differences in how automatic compression is happening.

Just so you are aware, though, we do some funky stuff with the .br extension as a workaround for certain Unity Exports. Here's the documentation on the expected behavior:

https://itch.io/docs/creators/html5#compression

If the filename ends with the extension .br then we'll assume that the content is Brotli compressed and the content-encoding will bet set to br. The The content-type header of the file will then be detected and set by the extension, after removing the .br. (Note: Brotli encoding can not be detected like gzip, so we must depend on the .br extension). This approach is commonly used by Unity 2020 WebGL export.

https://github.com/itchio/zipserver/blob/master/zipserver/archive.go#L326

@vchelaru
Copy link

Any update on this issue? It's been a while since it was last posted and there's no activity...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants