HttpChannel and the CORS problem, how do give the right headings?



  • There is an expansion for Google Chrome, which sends XML-RPC data to server. XML-RPC is a dextop app.NET.

    This is the initialization code for the server:

        Dim properties As IDictionary = New Hashtable
    
    properties.Item("name") = "hostChannel"
    properties.Item("port") = 5678
    
    Dim chnl As New HttpChannel(properties, Nothing, New XmlRpcServerFormatterSinkProvider)
    
    Try
    
        ChannelServices.RegisterChannel(chnl, False)
    
        RemotingConfiguration.RegisterWellKnownServiceType(GetType(StateNameServer), "statename.rem", WellKnownObjectMode.Singleton)
        RemotingConfiguration.RegisterWellKnownServiceType(GetType(CoderServer), "statename.rem", WellKnownObjectMode.Singleton)
    
    Catch ex As Exception
    
        MessageBox.Show("Ошибка")
    
    End Try
    

    When ajax-requesting this server, CORS protection fails to work properly and makes a mistake in building.

    For this to work, we need the server to give the right headlines.
    Also on OPTIONS, the request from the browser was coded. 200 OK

    For the Apache web server, this problem has been eliminated .htaccess The file is at the root of the do, with the next contents.

    Header set Access-Control-Allow-Origin "*"
    Header always set Access-Control-Max-Age "1000"
    Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding"
    Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT"

    RewriteEngine On
    RewriteCond %{REQUEST_METHOD} OPTIONS
    RewriteRule ^(.*)$ blank.php [QSA,L]

    How to address this issue for the above-mentioned HttpChannel ?

    UPDATEThere's an example of adding titles through a proxy server, but how do I not understand that?
    http://xml-rpc.net/faq/xmlrpcnetfaq-3-0-0.html#2.6



  • The XML-RPC.NET Library is based on NET Remoting. The operation of NET Remoting can be expanded by transferring objects to the canal designer called https://msdn.microsoft.com/en-us/library/tdzwhfy3(v=vs.100).aspx ♪ Such facilities may include HTTP headings in response.

    To create its sink on the server's side, we need to write classes that operate interfaces. IServerChannelSink and IServerChannelSinkProviderand then merge the established service provider into a chain with a service provider from the XML-RPC.NET Library.XmlRpcServerFormatterSinkProviderand transfer it to the designer HttpChannel

    Example of class ExtSinkwhich:

    • Adds in response to the headline server as a design parameter headers
    • If OPTIONS is used in the request, the answer is returned 200 OK empty body (heads are also added).

    The basic code is located in the method ProcessMessage

    public class ExtSink : BaseChannelSinkWithProperties, IServerChannelSink
    {
        private IServerChannelSink _next;
        private IDictionary<string, string> _headers;
    
    // headers - набор http-заголовков для добавления в ответ
    public ExtSink(IServerChannelSink next, IDictionary&lt;string, string&gt; headers)
    {
        _next = next;
        _headers = headers;
    }
    
    public void AsyncProcessResponse(IServerResponseChannelSinkStack sinkStack,
        object state, IMessage msg, ITransportHeaders headers, Stream stream)
    {
        sinkStack.AsyncProcessResponse(msg, headers, stream);
    }
    
    public Stream GetResponseStream(IServerResponseChannelSinkStack sinkStack,
        object state, IMessage msg, ITransportHeaders headers)
    {
        return null;
    }
    
    public IServerChannelSink NextChannelSink
    {
        get { return _next; }
    }
    
    public ServerProcessing ProcessMessage(IServerChannelSinkStack sinkStack,
        IMessage requestMsg, ITransportHeaders requestHeaders,
        Stream requestStream, out IMessage responseMsg,
        out ITransportHeaders responseHeaders,
        out Stream responseStream)
    {
        sinkStack.Push(this, null);
    
        var next = _next;
    
        var method = (string)requestHeaders["__RequestVerb"];
        if (method.Equals("OPTIONS", StringComparison.OrdinalIgnoreCase)) {
            // формальные параметры
            requestMsg = new MethodCall(new Header[0]);
            requestStream = null;
    
            // обходим выполнение xml-rpc sink (который находится в _next),
            // если используется метод OPTIONS
            next = _next.NextChannelSink;
        }
    
        var result = next.ProcessMessage(sinkStack, requestMsg,
            requestHeaders, requestStream, out responseMsg,
            out responseHeaders, out responseStream);
    
        // копируем заголовки в ответ
        if (responseHeaders == null)
            responseHeaders = new TransportHeaders();
    
        foreach (var header in _headers) {
            responseHeaders[header.Key] = header.Value;
        }
    
        return result;
    }
    

    }

    Class ExtSinkProvider - a simple factory to create a copy ExtSink:

    public class ExtSinkProvider : IServerChannelSinkProvider
    {
    private IServerChannelSinkProvider _next;
    private IDictionary<string, string> _headers;

    public ExtSinkProvider(IDictionary&lt;string, string&gt; headers)
    {
        _headers = headers;
    }
    
    public IServerChannelSink CreateSink(IChannelReceiver channel)
    {
        var next = _next.CreateSink(channel);
        return new ExtSink(next, _headers);
    }
    
    public void GetChannelData(IChannelDataStore channelData)
    {
    }
    
    public IServerChannelSinkProvider Next
    {
        get { return _next; }
        set { _next = value; }
    }
    

    }

    Then let's bring together the provider. HttpHeadersSinkProvider in a supply chain XmlRpcServerFormatterSinkProvider Library:

    var properties = new Hashtable {
    { "name", "hostChannel" },
    { "port", 5678 },
    };

    // заголовки, которые будут добавлены в ответ
    var headers = new Dictionary<string, string> {
    { "Access-Control-Allow-Origin", "*" },
    { "Access-Control-Max-Age", "1000" },
    { "Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Origin, Authorization, Accept, Client-Security-Token, Accept-Encoding" },
    { "Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT" },
    };

    // объединяем провайдеры в цепочку
    // первым должен быть ExtSinkProvider, чтобы иметь возможность обойти выполнение xml-rpc
    var providersChain = new ExtSinkProvider(headers);
    providersChain.Next = new XmlRpcServerFormatterSinkProvider();

    // цепочку передаем в конструктор канала
    var channel = new HttpChannel(properties, null, providersChain);
    ChannelServices.RegisterChannel(channel, false);

    RemotingConfiguration.RegisterWellKnownServiceType(
    typeof(TestService), "statename.rem", WellKnownObjectMode.Singleton);




Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2