Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions EventSource4Net.Test/EventSourceTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,44 @@ public void TestSuccesfulConnection()
}


[TestMethod]
public void TestSuccesfulConnectionWithHeaders()
{
// setup
Uri url = new Uri("http://test.com");
CancellationTokenSource cts = new CancellationTokenSource();
List<EventSourceState> states = new List<EventSourceState>();
ServiceResponseMock response = new ServiceResponseMock(url, System.Net.HttpStatusCode.OK);
WebRequesterFactoryMock factory = new WebRequesterFactoryMock(response);
ManualResetEvent stateIsOpen = new ManualResetEvent(false);

var headers = new Dictionary<string, string>
{
{ "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"]);
}
}
}
4 changes: 4 additions & 0 deletions EventSource4Net.Test/TestableEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ class TestableEventSource : EventSource
public TestableEventSource(Uri url,IWebRequesterFactory factory) : base(url,factory)
{

}
public TestableEventSource(Uri url, IWebRequesterFactory factory, Dictionary<string, string> headers) : base(url, factory, headers)
{

}
}
}
20 changes: 18 additions & 2 deletions EventSource4Net.Test/WebRequesterFactoryTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public WebRequesterMock WebRequesterMock
}
public WebRequesterFactoryMock(ServiceResponseMock response)
{
this.WebRequesterMock = new WebRequesterMock(response);
this.WebRequesterMock = new WebRequesterMock(response);
}
public IWebRequester Create()
{
Expand All @@ -36,21 +36,24 @@ public WebRequesterMock(ServiceResponseMock response)
this.Response = response;
}

public System.Threading.Tasks.Task<IServerResponse> Get(Uri url)
public System.Threading.Tasks.Task<IServerResponse> Get(Uri url, Dictionary<string, string> headers)
{
return Task.Factory.StartNew<IServerResponse>(() =>
{
GetCalled.Set();
Response.Headers = headers;
return Response;
});
}

}

class ServiceResponseMock : IServerResponse
{
private Stream mStream;
private StreamWriter mStreamWriter;
private Uri mUrl;
private Dictionary<string, string> mHeaders;
private HttpStatusCode mStatusCode;

public ManualResetEvent StatusCodeCalled = new ManualResetEvent(false);
Expand All @@ -61,6 +64,7 @@ public ServiceResponseMock(Uri url, HttpStatusCode statusCode)
mStatusCode = statusCode;
mStream = new TestableStream();
mStreamWriter = new StreamWriter(mStream);
mHeaders = new Dictionary<string, string>();
}

public System.Net.HttpStatusCode StatusCode
Expand All @@ -77,6 +81,18 @@ public System.IO.Stream GetResponseStream()
return mStream;
}

public Dictionary<string, string> Headers
{
get
{
return mHeaders;
}
set
{
mHeaders = value;
}
}

public Uri ResponseUri
{
get { return mUrl; }
Expand Down
9 changes: 5 additions & 4 deletions EventSource4Net/ConnectedState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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<string, string> mHeaders;

public EventSourceState State { get { return EventSourceState.OPEN; } }

public ConnectedState(IServerResponse response, IWebRequesterFactory webRequesterFactory)
public ConnectedState(IServerResponse response, IWebRequesterFactory webRequesterFactory, Dictionary<string, string> headers)
{
mResponse = response;
mWebRequesterFactory = webRequesterFactory;
mHeaders = headers;
}

public Task<IConnectionState> Run(Action<ServerSentEvent> msgReceived, CancellationToken cancelToken)
Expand Down Expand Up @@ -130,7 +131,7 @@ public Task<IConnectionState> Run(Action<ServerSentEvent> msgReceived, Cancellat
//stream.Close();
//mResponse.Close();
//mResponse.Dispose();
return new DisconnectedState(mResponse.ResponseUri, mWebRequesterFactory);
return new DisconnectedState(mResponse.ResponseUri, mWebRequesterFactory, mHeaders);
}
}
});
Expand Down
14 changes: 7 additions & 7 deletions EventSource4Net/ConnectingState.cs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -15,20 +12,23 @@ class ConnectingState : IConnectionState

private Uri mUrl;
private IWebRequesterFactory mWebRequesterFactory;
private Dictionary<string, string> mHeaders;

public EventSourceState State { get { return EventSourceState.CONNECTING; } }

public ConnectingState(Uri url, IWebRequesterFactory webRequesterFactory)
public ConnectingState(Uri url, IWebRequesterFactory webRequesterFactory, Dictionary<string, string> 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<IConnectionState> Run(Action<ServerSentEvent> donothing, CancellationToken cancelToken)
{
IWebRequester requester = mWebRequesterFactory.Create();
var taskResp = requester.Get(mUrl);
var taskResp = requester.Get(mUrl, mHeaders);

return taskResp.ContinueWith<IConnectionState>(tsk =>
{
Expand All @@ -37,15 +37,15 @@ public Task<IConnectionState> Run(Action<ServerSentEvent> donothing, Cancellatio
IServerResponse response = tsk.Result;
if (response.StatusCode == HttpStatusCode.OK)
{
return new ConnectedState(response, mWebRequesterFactory);
return new ConnectedState(response, mWebRequesterFactory, mHeaders);
}
else
{
_logger.Info("Failed to connect to: " + mUrl.ToString() + response ?? (" Http statuscode: " + response.StatusCode));
}
}

return new DisconnectedState(mUrl, mWebRequesterFactory);
return new DisconnectedState(mUrl, mWebRequesterFactory, mHeaders);
});
}
}
Expand Down
9 changes: 6 additions & 3 deletions EventSource4Net/DisconnectedState.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,27 @@ class DisconnectedState : IConnectionState
{
private Uri mUrl;
private IWebRequesterFactory mWebRequesterFactory;
private Dictionary<string, string> mHeaders;

public EventSourceState State
{
get { return EventSourceState.CLOSED; }
}

public DisconnectedState(Uri url, IWebRequesterFactory webRequesterFactory)
public DisconnectedState(Uri url, IWebRequesterFactory webRequesterFactory, Dictionary<string, string> headers)
{
if (url == null) throw new ArgumentNullException("Url cant be null");
mUrl = url;
mWebRequesterFactory = webRequesterFactory;
mHeaders = headers;
}

public Task<IConnectionState> Run(Action<ServerSentEvent> donothing, CancellationToken cancelToken)
{
if(cancelToken.IsCancellationRequested)
return Task.Factory.StartNew<IConnectionState>(() => { return new DisconnectedState(mUrl, mWebRequesterFactory); });
return Task.Factory.StartNew<IConnectionState>(() => { return new DisconnectedState(mUrl, mWebRequesterFactory, mHeaders); });
else
return Task.Factory.StartNew<IConnectionState>(() => { return new ConnectingState(mUrl, mWebRequesterFactory); });
return Task.Factory.StartNew<IConnectionState>(() => { return new ConnectingState(mUrl, mWebRequesterFactory, mHeaders); });
}
}
}
26 changes: 21 additions & 5 deletions EventSource4Net/EventSource.cs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -16,6 +12,8 @@ public class EventSource
public event EventHandler<StateChangedEventArgs> StateChanged;
public event EventHandler<ServerSentEventReceivedEventArgs> EventReceived;

public CancellationTokenSource CancellationToken { get; set; }

private IWebRequesterFactory _webRequesterFactory = new WebRequesterFactory();
private int _timeout = 0;
public Uri Url { get; private set; }
Expand All @@ -24,6 +22,11 @@ public class EventSource
private IConnectionState mCurrentState = null;
private CancellationToken mStopToken;
private CancellationTokenSource mTokenSource = new CancellationTokenSource();
private Dictionary<string, string> _headers;
private Uri url;
private IWebRequesterFactory factory;
private Dictionary<string, string> headers;

private IConnectionState CurrentState
{
get { return mCurrentState; }
Expand All @@ -47,6 +50,12 @@ public EventSource(Uri url, int timeout)
Initialize(url, timeout);
}

public EventSource(Uri url, Dictionary<string, string> headers, int timeout)
{
_headers = headers;
Initialize(url, timeout);
}

/// <summary>
/// Constructor for testing purposes
/// </summary>
Expand All @@ -57,11 +66,18 @@ protected EventSource(Uri url, IWebRequesterFactory factory)
Initialize(url, 0);
}

protected EventSource(Uri url, IWebRequesterFactory factory, Dictionary<string, string> 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());
}

Expand Down
3 changes: 0 additions & 3 deletions EventSource4Net/IConnectionState.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

Expand Down
3 changes: 1 addition & 2 deletions EventSource4Net/IWebRequester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace EventSource4Net
{
public interface IWebRequester
{
Task<IServerResponse> Get(Uri url);

Task<IServerResponse> Get(Uri url, Dictionary<string, string> headers = null);
}
}
12 changes: 9 additions & 3 deletions EventSource4Net/WebRequester.cs
Original file line number Diff line number Diff line change
@@ -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<IServerResponse> Get(Uri url)
public Task<IServerResponse> Get(Uri url, Dictionary<string, string> 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<WebResponse>(wreq.BeginGetResponse,
wreq.EndGetResponse,
null).ContinueWith<IServerResponse>(t => new ServerResponse(t.Result));
Expand Down