diff --git a/EventSource4Net.Test/EventSourceTest.cs b/EventSource4Net.Test/EventSourceTest.cs index 43cd90e..0148e75 100644 --- a/EventSource4Net.Test/EventSourceTest.cs +++ b/EventSource4Net.Test/EventSourceTest.cs @@ -81,5 +81,44 @@ public void TestSuccesfulConnection() } + [TestMethod] + public void TestSuccesfulConnectionWithHeaders() + { + // setup + Uri url = new Uri("http://test.com"); + CancellationTokenSource cts = new CancellationTokenSource(); + List states = new List(); + ServiceResponseMock response = new ServiceResponseMock(url, System.Net.HttpStatusCode.OK); + WebRequesterFactoryMock factory = new WebRequesterFactoryMock(response); + ManualResetEvent stateIsOpen = new ManualResetEvent(false); + + var headers = new Dictionary + { + { "x-key", "headerValue" } + }; + + TestableEventSource es = new TestableEventSource(url, factory, headers); + es.StateChanged += (o, e) => + { + states.Add(e.State); + if (e.State == EventSourceState.OPEN) + { + stateIsOpen.Set(); + cts.Cancel(); + } + }; + + + // act + stateIsOpen.Reset(); + + es.Start(cts.Token); + + stateIsOpen.WaitOne(); + + // assert + Assert.AreEqual(1, factory.WebRequesterMock.Response.Headers.Count); + Assert.AreEqual("headerValue", factory.WebRequesterMock.Response.Headers["x-key"]); + } } } diff --git a/EventSource4Net.Test/TestableEventSource.cs b/EventSource4Net.Test/TestableEventSource.cs index e12c41d..e87f158 100644 --- a/EventSource4Net.Test/TestableEventSource.cs +++ b/EventSource4Net.Test/TestableEventSource.cs @@ -11,6 +11,10 @@ class TestableEventSource : EventSource public TestableEventSource(Uri url,IWebRequesterFactory factory) : base(url,factory) { + } + public TestableEventSource(Uri url, IWebRequesterFactory factory, Dictionary headers) : base(url, factory, headers) + { + } } } diff --git a/EventSource4Net.Test/WebRequesterFactoryTest.cs b/EventSource4Net.Test/WebRequesterFactoryTest.cs index ab61e7e..00c71b0 100644 --- a/EventSource4Net.Test/WebRequesterFactoryTest.cs +++ b/EventSource4Net.Test/WebRequesterFactoryTest.cs @@ -18,7 +18,7 @@ public WebRequesterMock WebRequesterMock } public WebRequesterFactoryMock(ServiceResponseMock response) { - this.WebRequesterMock = new WebRequesterMock(response); + this.WebRequesterMock = new WebRequesterMock(response); } public IWebRequester Create() { @@ -36,14 +36,16 @@ public WebRequesterMock(ServiceResponseMock response) this.Response = response; } - public System.Threading.Tasks.Task Get(Uri url) + public System.Threading.Tasks.Task Get(Uri url, Dictionary headers) { return Task.Factory.StartNew(() => { GetCalled.Set(); + Response.Headers = headers; return Response; }); } + } class ServiceResponseMock : IServerResponse @@ -51,6 +53,7 @@ class ServiceResponseMock : IServerResponse private Stream mStream; private StreamWriter mStreamWriter; private Uri mUrl; + private Dictionary mHeaders; private HttpStatusCode mStatusCode; public ManualResetEvent StatusCodeCalled = new ManualResetEvent(false); @@ -61,6 +64,7 @@ public ServiceResponseMock(Uri url, HttpStatusCode statusCode) mStatusCode = statusCode; mStream = new TestableStream(); mStreamWriter = new StreamWriter(mStream); + mHeaders = new Dictionary(); } public System.Net.HttpStatusCode StatusCode @@ -77,6 +81,18 @@ public System.IO.Stream GetResponseStream() return mStream; } + public Dictionary Headers + { + get + { + return mHeaders; + } + set + { + mHeaders = value; + } + } + public Uri ResponseUri { get { return mUrl; } diff --git a/EventSource4Net/ConnectedState.cs b/EventSource4Net/ConnectedState.cs index 7669993..602a0c3 100644 --- a/EventSource4Net/ConnectedState.cs +++ b/EventSource4Net/ConnectedState.cs @@ -2,8 +2,6 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using System.Net; -using System.IO; using System.Threading.Tasks; using System.Threading; @@ -17,12 +15,15 @@ class ConnectedState : IConnectionState private ServerSentEvent mSse = null; private string mRemainingText = string.Empty; // the text that is not ended with a lineending char is saved for next call. private IServerResponse mResponse; + private Dictionary mHeaders; + public EventSourceState State { get { return EventSourceState.OPEN; } } - public ConnectedState(IServerResponse response, IWebRequesterFactory webRequesterFactory) + public ConnectedState(IServerResponse response, IWebRequesterFactory webRequesterFactory, Dictionary headers) { mResponse = response; mWebRequesterFactory = webRequesterFactory; + mHeaders = headers; } public Task Run(Action msgReceived, CancellationToken cancelToken) @@ -130,7 +131,7 @@ public Task Run(Action msgReceived, Cancellat //stream.Close(); //mResponse.Close(); //mResponse.Dispose(); - return new DisconnectedState(mResponse.ResponseUri, mWebRequesterFactory); + return new DisconnectedState(mResponse.ResponseUri, mWebRequesterFactory, mHeaders); } } }); diff --git a/EventSource4Net/ConnectingState.cs b/EventSource4Net/ConnectingState.cs index d22c9f9..e2c9f53 100644 --- a/EventSource4Net/ConnectingState.cs +++ b/EventSource4Net/ConnectingState.cs @@ -1,10 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using System.Net; -using System.IO; using System.Threading; namespace EventSource4Net @@ -15,20 +12,23 @@ class ConnectingState : IConnectionState private Uri mUrl; private IWebRequesterFactory mWebRequesterFactory; + private Dictionary mHeaders; + public EventSourceState State { get { return EventSourceState.CONNECTING; } } - public ConnectingState(Uri url, IWebRequesterFactory webRequesterFactory) + public ConnectingState(Uri url, IWebRequesterFactory webRequesterFactory, Dictionary headers) { if (url == null) throw new ArgumentNullException("Url cant be null"); if (webRequesterFactory == null) throw new ArgumentNullException("Factory cant be null"); mUrl = url; mWebRequesterFactory = webRequesterFactory; + mHeaders = headers; } public Task Run(Action donothing, CancellationToken cancelToken) { IWebRequester requester = mWebRequesterFactory.Create(); - var taskResp = requester.Get(mUrl); + var taskResp = requester.Get(mUrl, mHeaders); return taskResp.ContinueWith(tsk => { @@ -37,7 +37,7 @@ public Task Run(Action donothing, Cancellatio IServerResponse response = tsk.Result; if (response.StatusCode == HttpStatusCode.OK) { - return new ConnectedState(response, mWebRequesterFactory); + return new ConnectedState(response, mWebRequesterFactory, mHeaders); } else { @@ -45,7 +45,7 @@ public Task Run(Action donothing, Cancellatio } } - return new DisconnectedState(mUrl, mWebRequesterFactory); + return new DisconnectedState(mUrl, mWebRequesterFactory, mHeaders); }); } } diff --git a/EventSource4Net/DisconnectedState.cs b/EventSource4Net/DisconnectedState.cs index da347cb..289eb23 100644 --- a/EventSource4Net/DisconnectedState.cs +++ b/EventSource4Net/DisconnectedState.cs @@ -11,24 +11,27 @@ class DisconnectedState : IConnectionState { private Uri mUrl; private IWebRequesterFactory mWebRequesterFactory; + private Dictionary mHeaders; + public EventSourceState State { get { return EventSourceState.CLOSED; } } - public DisconnectedState(Uri url, IWebRequesterFactory webRequesterFactory) + public DisconnectedState(Uri url, IWebRequesterFactory webRequesterFactory, Dictionary headers) { if (url == null) throw new ArgumentNullException("Url cant be null"); mUrl = url; mWebRequesterFactory = webRequesterFactory; + mHeaders = headers; } public Task Run(Action donothing, CancellationToken cancelToken) { if(cancelToken.IsCancellationRequested) - return Task.Factory.StartNew(() => { return new DisconnectedState(mUrl, mWebRequesterFactory); }); + return Task.Factory.StartNew(() => { return new DisconnectedState(mUrl, mWebRequesterFactory, mHeaders); }); else - return Task.Factory.StartNew(() => { return new ConnectingState(mUrl, mWebRequesterFactory); }); + return Task.Factory.StartNew(() => { return new ConnectingState(mUrl, mWebRequesterFactory, mHeaders); }); } } } diff --git a/EventSource4Net/EventSource.cs b/EventSource4Net/EventSource.cs index 7785155..389679f 100644 --- a/EventSource4Net/EventSource.cs +++ b/EventSource4Net/EventSource.cs @@ -1,10 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Text; -using System.Net; -using System.IO; -using System.Threading.Tasks; using System.Threading; namespace EventSource4Net @@ -16,6 +12,8 @@ public class EventSource public event EventHandler StateChanged; public event EventHandler EventReceived; + public CancellationTokenSource CancellationToken { get; set; } + private IWebRequesterFactory _webRequesterFactory = new WebRequesterFactory(); private int _timeout = 0; public Uri Url { get; private set; } @@ -24,6 +22,11 @@ public class EventSource private IConnectionState mCurrentState = null; private CancellationToken mStopToken; private CancellationTokenSource mTokenSource = new CancellationTokenSource(); + private Dictionary _headers; + private Uri url; + private IWebRequesterFactory factory; + private Dictionary headers; + private IConnectionState CurrentState { get { return mCurrentState; } @@ -47,6 +50,12 @@ public EventSource(Uri url, int timeout) Initialize(url, timeout); } + public EventSource(Uri url, Dictionary headers, int timeout) + { + _headers = headers; + Initialize(url, timeout); + } + /// /// Constructor for testing purposes /// @@ -57,11 +66,18 @@ protected EventSource(Uri url, IWebRequesterFactory factory) Initialize(url, 0); } + protected EventSource(Uri url, IWebRequesterFactory factory, Dictionary headers) + { + _webRequesterFactory = factory; + _headers = headers; + Initialize(url, 0); + } + private void Initialize(Uri url, int timeout) { _timeout = timeout; Url = url; - CurrentState = new DisconnectedState(Url,_webRequesterFactory); + CurrentState = new DisconnectedState(Url, _webRequesterFactory, _headers); _logger.Info("EventSource created for " + url.ToString()); } diff --git a/EventSource4Net/IConnectionState.cs b/EventSource4Net/IConnectionState.cs index 5654023..a17e36c 100644 --- a/EventSource4Net/IConnectionState.cs +++ b/EventSource4Net/IConnectionState.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; diff --git a/EventSource4Net/IWebRequester.cs b/EventSource4Net/IWebRequester.cs index 4a3367a..9e21b21 100644 --- a/EventSource4Net/IWebRequester.cs +++ b/EventSource4Net/IWebRequester.cs @@ -9,7 +9,6 @@ namespace EventSource4Net { public interface IWebRequester { - Task Get(Uri url); - + Task Get(Uri url, Dictionary headers = null); } } diff --git a/EventSource4Net/WebRequester.cs b/EventSource4Net/WebRequester.cs index 092ca1d..d1ffff5 100644 --- a/EventSource4Net/WebRequester.cs +++ b/EventSource4Net/WebRequester.cs @@ -1,20 +1,26 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Net; -using System.Text; using System.Threading.Tasks; namespace EventSource4Net { class WebRequester : IWebRequester { - public Task Get(Uri url) + public Task Get(Uri url, Dictionary headers = null) { var wreq = (HttpWebRequest)WebRequest.Create(url); wreq.Method = "GET"; wreq.Proxy = null; + if (headers != null) + { + foreach (var header in headers) + { + wreq.Headers.Add(header.Key, header.Value); + } + } + var taskResp = Task.Factory.FromAsync(wreq.BeginGetResponse, wreq.EndGetResponse, null).ContinueWith(t => new ServerResponse(t.Result));