Have you ever faced a constraint of data limitation between your client and server applications? For example, recently, I've got an error of a URI size limit of 8892 bytes, which allows something close to 9000 characters on the URI path. Unfortunately, my team couldn't change the origin to respect the constraint because of how the ecosystem works. A change like this would demand considerable effort, increasing the time to deliver the solution. Fortunately, we found a quick solution by using GZIP!
We had to compress the data on the backend and send it to the frontend, where it would decompress it. So, after a bit of research, these are the steps we followed to implement it in the project:
- Use the namespace
System.IO.Compressionthat provides a native solution (without external libraries) to handle GZIP requirements.
- Convert the gzipped content to base64 to ensure the data remains intact without modifications during transport. In our case, through the HTTP header.
- Use the namespace
To see it in action, download this project and execute the following command:
▶ docker-compose up app Starting gzip-between-backend-frontend-sample_app_1 ... done Attaching to gzip-between-backend-frontend-sample_app_1 app_1 | ### Running and watching the project 👀 app_1 | dotnet watch ⌚ Polling file watcher is enabled app_1 | dotnet watch 🚀 Started app_1 | Building... app_1 | warn: Microsoft.AspNetCore.DataProtection.Repositories.FileSystemXmlRepository app_1 | Storing keys in a directory '/root/.aspnet/DataProtection-Keys' that may not be persisted outside of the container. Protected data will be unavailable when container is destroyed. app_1 | info: Microsoft.Hosting.Lifetime app_1 | Now listening on: http://0.0.0.0:5128 app_1 | dotnet watch 🌐 Unable to launch the browser. Navigate to http://0.0.0.0:5128 app_1 | info: Microsoft.Hosting.Lifetime app_1 | Application started. Press Ctrl+C to shut down. app_1 | info: Microsoft.Hosting.Lifetime app_1 | Hosting environment: Development app_1 | info: Microsoft.Hosting.Lifetime app_1 | Content root path: /app/src/
If you access
http://localhost:5128/ and submit the text
Type something and check its output as GZip! but written ten times, you'll get the following:
Notice the compressed data has 90 bytes while the original has 449 bytes. So the algorithm reduced the original data by almost 80% 😲.
If you are in doubt about where you go in the code when you test the project, look at the bullets:
- When you access
HomeControllerhandles it through the
- Including other
Index.cshtmlis SSR (server-side rendering), and an HTML is sent to the browser.
- When you submit a text, the form sends the GET request to the method
- The method
RetrieveGZippedContentgets the text, compresses it, and then sends it as a query string using a redirect (302) to the
Index. Check out its test!
- Ultimately, the script configures the fields and displays the hidden HTML.
You'll get the error 414 (URI too long) if you put a huge input. To avoid that, you can change the project by sending the text through the body.
Although we could solve the issue, this is absolutely a technical debt. Sometimes a technical debt is acceptable as long as there is a path toward something that fixes not only it but many other aspects of the project or the ecosystem. The thing is: Is this a technical debt that we tell we'll fix in the future, but it never happens, or is it one that indeed will be fixed? I hope for the latter 🙏.
Posted listening to The Crying Game, Boy George 🎶.