How do enable a .Net web-API to accept g-ziped posts

后端 未结 4 1547
别跟我提以往
别跟我提以往 2020-12-08 11:58

I have a fairly bog standard .net MVC 4 Web API application.

 public class LogsController : ApiController
{

    public HttpResponseMessage PostLog(List<         


        
4条回答
  •  我在风中等你
    2020-12-08 12:28

    I believe the correct answer is Kaliatech's and I would have left this as a comment and voted his up is I had enough reputation points, since I think his is basically correct.

    However, my situation called for the need to look at the encoding type type rather than the content type. Using this approach the calling system can still specify that the content type is json/xml/etc in the content type, but specify that the data is encoded using gzip or potentially another encoding/compression mechanism. This prevented me from needing to change the content type after decoding the input and allows any content type information to flow through in its original state.

    Here's the code. Again, 99% of this is Kaliatech's answer including the comments, so please vote his post up if this is useful.

    public class CompressedRequestHandler : DelegatingHandler
    {
        protected override System.Threading.Tasks.Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
        {
            if (IsRequetCompressed(request))
            {
                request.Content = DecompressRequestContent(request);
            }
    
            return base.SendAsync(request, cancellationToken);
        }
    
        private bool IsRequetCompressed(HttpRequestMessage request)
        {
            if (request.Content.Headers.ContentEncoding != null &&
                request.Content.Headers.ContentEncoding.Contains("gzip"))
            {
                return true;
            }
    
            return false;
        }
    
        private HttpContent DecompressRequestContent(HttpRequestMessage request)
        {
            // Read in the input stream, then decompress in to the outputstream.
            // Doing this asynronously, but not really required at this point
            // since we end up waiting on it right after this.
            Stream outputStream = new MemoryStream();
            Task task = request.Content.ReadAsStreamAsync().ContinueWith(t =>
                {
                    Stream inputStream = t.Result;
                    var gzipStream = new GZipStream(inputStream, CompressionMode.Decompress);
    
                    gzipStream.CopyTo(outputStream);
                    gzipStream.Dispose();
    
                    outputStream.Seek(0, SeekOrigin.Begin);
                });
    
            // Wait for inputstream and decompression to complete. Would be nice
            // to not block here and work async when ready instead, but I couldn't 
            // figure out how to do it in context of a DelegatingHandler.
            task.Wait();
    
            // Save the original content
            HttpContent origContent = request.Content;
    
            // Replace request content with the newly decompressed stream
            HttpContent newContent = new StreamContent(outputStream);
    
            // Copy all headers from original content in to new one
            foreach (var header in origContent.Headers)
            {
                newContent.Headers.Add(header.Key, header.Value);
            }
    
            return newContent;
        }
    

    I then registered this handler globally, which could be a dicey proposition if you are vulnerable to DoS attacks, but our service is locked down, so it works for us

    GlobalConfiguration.Configuration.MessageHandlers.Add(new CompressedRequestHandler());
    

提交回复
热议问题