How to access the stream before compression runs via Global.asax?

Asked

Viewed 42 times

1

On the server side apply compression when possible:

public MvcApplication()
    {
        this.BeginRequest += OnRequestBegin;
        this.PreSendRequestContent += OnPreSendRequestContent;
    }

    private void OnPreSendRequestContent(object sender, EventArgs e)
    {
        var app = sender as HttpApplication;
        if (app == null || !app.Request.IsLocal || app.Context == null)
            return;
        var headers = app.Context.Response.Headers;
        headers.Remove("Server");
    }

    private void OnRequestBegin(object sender, EventArgs e)
    {
        ViewServiceLocator.Instance = new ViewServiceLocator(InjectionHelper.DefaultContainer);

        var app = sender as HttpApplication;

        string encodings = app.Request.Headers.Get("Accept-Encoding");
        if (encodings != null)
        {
            encodings = encodings.ToLower();
            AddCompression(app.Response, encodings);
        }
    }

    // Implement HTTP compression
    private void AddCompression(HttpResponse response, string encodings)
    {
        if (encodings.Contains("deflate"))
        {
            response.Filter = new System.IO.Compression.DeflateStream(response.Filter, System.IO.Compression.CompressionMode.Compress);
            response.AppendHeader("Content-Encoding", "deflate");
        }
        else if (encodings.Contains("gzip"))
        {
            response.Filter = new System.IO.Compression.GZipStream(response.Filter, System.IO.Compression.CompressionMode.Compress);
            response.AppendHeader("Content-Encoding", "gzip");
        }
    }

While on the client side I have a global loading and a loading that works by context:

    $.ajaxSetup({
    beforeSend: function (jqXHR, settings) {
        myApp.Request.Context = settings.context, jqXHR.url = settings.url;

        if (settings.global && (settings.context === "undefined" || settings.context !== "undefined" && !document.getElementById("main").contains(settings.context)))
            StartWait();
    },
    //Código removido para facilitar a leitura...
    xhr: function () {
        let xhr = new window.XMLHttpRequest(), $context = $(myApp.Request.Context);

        if (myApp.Request.Context) {
            xhr.addEventListener("progress", function (evt) {

                console.log("progress", evt);
                console.log("progress", $context);
                console.log("lengthComputable", evt.lengthComputable);
                console.log("x-decompressed-content-length", evt.target.getResponseHeader('x-decompressed-content-length'));
                console.log("content-length", evt.target.getResponseHeader('content-length'));

                let contentLength;
                if (evt.lengthComputable) {
                    contentLength = evt.total;
                } else {
                    contentLength = evt.target.getResponseHeader('content-length');
                }

                let percentComplete = evt.loaded / contentLength * 100;

                if (percentComplete === 100) {

                    console.log("progress-done", percentComplete);

                    DestroiLoadingContextual($context);
                }
            }, false);

            CriaLoadingContextual($context);
        }

        return xhr;
    }
});

My problem: When the request comes compressed from the server, evt.lengthComputable = false and evt.total = 0, the contentLength comes with the value of the compressed size, but i need size information original.

This seems to be a known problem

I’m trying to create a header "x-decompressed-content-length" informing the original value, in the Beginrequest as in the Presendrequestcontent, when I try to access the Outputstream of Response to obtain the Length, I get a exception;

What I did wrong or does anyone know any other possible solution?

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.