首页 文章

在 ASMX 中解压缩传入的 HTTP SOAP 请求

提问于
浏览
1

我正在尝试让 IIS 接受压缩的 SOAP/XML 请求。

似乎 IIS 不支持开箱即用的压缩 HTTP 请求。任何带有Content-Encoding: gzipdeflate的 HTTP 请求都会返回 HTTP 错误 400。

所以我尝试按这个相关的问题中的描述添加DelegatingHandler via Global.asax

Global.asax

protected void Application_Start()
{
    GlobalConfiguration.Configuration.MessageHandlers.Add(new DecompressionHandler());
}

但是在ASMX的情况下,似乎没有 MessageHandler 被执行(我已经检查过,Application_Start被调用,但是整个 WebApi 配置似乎在 ASMX 中没有效果)。

所以问题是 - 如何在ASMX服务中实现SOAP请求解压缩?

1 回答

  • 0

    能够让它与SoapExtension一起工作:

    using System;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.IO.Compression;
    using System.Linq;
    using System.Net.Http;
    using System.Threading.Tasks;
    using System.Web.Services.Protocols;
    
    /// <summary>
    ///   ASPX SOAP request decompression WebMethod annotation
    /// </summary>
    [AttributeUsage(AttributeTargets.Method)]
    public class CompressedRequestAttribute : SoapExtensionAttribute
    {
      public override Type ExtensionType { get { return typeof(CompressedRequestExtension); } }
      public override int Priority { get { return 0; } set { } }
    }
    
    /// <summary>
    ///   ASPX SOAP request decompression implementation
    /// </summary>
    public class CompressedRequestExtension : SoapExtension
    {
      public override object GetInitializer(Type serviceType) { return null; }
    
      public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute) { return null; }
    
      public override void Initialize(object initializer) { }
    
      Stream origStream;
      StreamDelegate wrappedStream = new StreamDelegate();
    
      public override void ProcessMessage(SoapMessage message) {
        switch (message.Stage) {
          case SoapMessageStage.BeforeDeserialize:
            if (message.ContentEncoding == "gzip") {
              wrappedStream.wrapped = new GZipStream(origStream, CompressionMode.Decompress, true);
              message.ContentEncoding = null;
            }
            else if (message.ContentEncoding == "deflate") {
              wrappedStream.wrapped = new DeflateStream(origStream, CompressionMode.Decompress, true);
              message.ContentEncoding = null;
            }
            else {
              goto default;
            }
            break;
          default:
            wrappedStream.wrapped = origStream;
            break;
        }
      }
    
      public override Stream ChainStream(Stream stream) {
        origStream = stream;
        return wrappedStream;
      }
    
    }
    
    public class StreamDelegate : Stream
    {
      public Stream wrapped;
      public override bool CanRead { get { return wrapped.CanRead; } }
      public override bool CanSeek { get { return wrapped.CanSeek; } }
      public override bool CanWrite { get { return wrapped.CanWrite; } }
      public override long Length { get { return wrapped.Length; } }
      public override long Position { get { return wrapped.Position; } set { wrapped.Position = value; } }
      public override void Flush() { wrapped.Flush(); }
      public override int Read(byte[] buffer, int offset, int count) { return wrapped.Read(buffer, offset, count); }
      public override long Seek(long offset, SeekOrigin origin) { return wrapped.Seek(offset, origin); }
      public override void SetLength(long value) { wrapped.SetLength(value); }
      public override void Write(byte[] buffer, int offset, int count) { wrapped.Write(buffer, offset, count); }
    }
    

    然后使用以下内容注释每个WebMethod

    [CompressedRequestAttribute]
    

    并证明它有效:

    POST /TestService/TestAction1.asmx HTTP/1.1
    Host: localhost
    Accept-Encoding: deflate, gzip
    SOAPAction: http://example.com/TestService:action1
    Content-Type: text/xml;charset=UTF-8
    Content-Encoding: gzip
    Content-Length: 321
    
    <gzipped-request>
    
    HTTP/1.1 200 OK
    Content-Type: text/xml; charset=utf-8
    Server: Microsoft-IIS/10.0
    X-AspNet-Version: 4.0.30319
    Content-Encoding: gzip
    Content-Length: 10193
    
    <gzipped-response>
    

相关问题