jsonrpc.net over httplistener

Mar 2, 2014 at 12:29 PM
is it possible to use jsonrpc.net over httplistener?
Coordinator
Mar 2, 2014 at 6:51 PM
Yes, you could look at the sockets or console example for ideas on how to hook it in.
Mar 2, 2014 at 8:01 PM
Edited Mar 2, 2014 at 8:02 PM
do you have a working example?

i was the one that pushed the sockets example and if we miss one for httplistener, i guess i'll be creating one too.
Coordinator
Mar 2, 2014 at 9:06 PM
Edited Mar 2, 2014 at 9:06 PM
I don't. The closest thing I have is the ASP.net http handler.
https://jsonrpc2.codeplex.com/SourceControl/latest#AustinHarris.JsonRpc/AustinHarris.JsonRpc.AspNet/JsonRpcHandler.cs

I may have to add you to the project if you keep making contributions. :)
Mar 3, 2014 at 4:24 PM
Hey again, i've implemented the http based version :)

We are developing a brand new pool server software for bitcoin like crypto coins and use json-rpc extensively (https://github.com/CoiniumServ/coinium).

Any way here's my json-rpc over http code :)
    public class GetworkServer : HttpServer
    {
        private static object[] _services =
        {
            new GetworkService()
        };

        public GetworkServer(int port)
            : base(port)
        {
            this.OnHttpRequest += Getwork_DataReceived;
        }

        private void Getwork_DataReceived(object sender, HttpRequestEventArgs e)
        {
            var context = e.Context;
            var httpRequest = context.Request;

            var encoding = Encoding.UTF8;

            var rpcResultHandler = new AsyncCallback(
                callback =>
                {
                    var asyncData = ((JsonRpcStateAsync) callback);

                    var result = asyncData.Result;
                    var data = Encoding.UTF8.GetBytes(result);
                    var rpcRequest = ((RpcRequest) asyncData.AsyncState);

                    rpcRequest.Response.ContentType = "application/json";
                    rpcRequest.Response.ContentEncoding = encoding;

                    rpcRequest.Response.ContentLength64 = data.Length;
                    rpcRequest.Response.OutputStream.Write(data,0,data.Length);                    

                    Log.Verbose("RPC-client send:\n{0}", result);
                });

            using (var reader = new StreamReader(httpRequest.InputStream, encoding))
            {
                var line = reader.ReadToEnd();
                var response = context.Response;

                var rpcRequest = new RpcRequest(line, response);

                var async = new JsonRpcStateAsync(rpcResultHandler, rpcRequest) { JsonRpc = line };
                JsonRpcProcessor.Process(async, this);
            }        
        }
    }
The RPCRequest class;
public class RpcRequest
    {
        public string Text { get; private set; }

        public HttpListenerResponse Response { get; private set; }

        public RpcRequest(string text, HttpListenerResponse response)
        {
            this.Text = text;
            this.Response = response;
        }
    }
The base http-server class;
public class HttpServer
    {
        public int Port { get; private set; }

        public delegate void HttpRequestEventHandler(object sender, HttpRequestEventArgs e);
        public event HttpRequestEventHandler OnHttpRequest;

        public HttpServer(int port)
        {
            this.Port = port;
        }

        public void Listen()
        {
            var listener = new HttpListener();

            if (!HttpListener.IsSupported)
                throw new NotSupportedException("HttpListener not supported. Switch to mono provided one.");

            listener.Prefixes.Add(string.Format("http://localhost:{0}/", this.Port));

            listener.Start();

            var tcs = new TaskCompletionSource<object>();

            listener.GetContextAsync().ContinueWith(async t =>
            {
                try
                {
                    while (true)
                    {
                        var context = await t;
                        this.HttpRequestRecieved(new HttpRequestEventArgs(context));
                        t = listener.GetContextAsync();
                    }
                }
                catch (Exception e)
                {
                    listener.Close();
                    tcs.TrySetException(e);
                }
            });
        }
        protected virtual void HttpRequestRecieved(HttpRequestEventArgs e)
        {
            var handler = OnHttpRequest;
            if (handler != null)
                handler(this, e);
        }
    }
And the HttpRequestRecieved
    public sealed class HttpRequestEventArgs : EventArgs
    {
        public System.Net.HttpListenerContext Context { get; private set; }

        public HttpRequestEventArgs(HttpListenerContext context)
        {
            this.Context = context;
        }

        public override string ToString()
        {
            return string.Empty;
        }
    }
So basically this allows to run json-rpc over http without ASP.NET or IIS. It basically uses httplistener class which only works with windows2000+ but with mono implementation of httplistener which is managed-only https://github.com/jbevain/mono.net.httplistener you can even get rid of that.

For further implementation & examples you can check our software;

Json RPC 2.0 over raw sockets:
Json rpc 1.0 over http (without asp.net & self-hosted!)
ps: it'd be lot better if the project was hosted on github :)
Coordinator
Mar 5, 2014 at 3:46 AM
Great stuff.

I'll take a look at git hub.

We have also started into working on a version 2 rewrite that would allow swapping out different encoder/decoders, and some additional high performance options. If you have api ideas I'd be interested in them.
Mar 5, 2014 at 8:35 AM
It would be nice to have a json processor that could take an input and and output parameter (as is in case with jayrock).
JsonRpcDispatcher dispatch = new JsonRpcDispatcher( service );
dispatch.Process( reader, writer );
And github is far better in every term. I'm having difficulties following the changes here. It would be a good idea to move github.