Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6238968
POST method fix, Now HttpHandler is called for POST
UmmarIqbal Nov 22, 2016
c3971c4
Fix for websocket handshake issue on Safari 10.0.1 (11602.2.14.0.7) w…
UmmarIqbal Nov 22, 2016
be1f836
README updated with bug fixes in this fork
UmmarIqbal Mar 9, 2017
61b09ed
Session support implementation 1st version
Mar 15, 2017
a31d7c9
Session cache implementation
Mar 15, 2017
83643a9
SessionStorageConfiguration class refectoring
Mar 16, 2017
f5029b5
Session cookie handling in http response
Mar 16, 2017
cc3a5ca
SessionHandler class refactoring + Session expire time handling logic…
Mar 16, 2017
3747758
Response code "302 MovedTemporarily" addition.
Mar 16, 2017
88b6e5e
Fallback functionality in HybridSessionStorageHandler for session's d…
Mar 16, 2017
a078fc5
Creation of New Session on logout
Mar 16, 2017
9a5281b
SessionStorageConfiguration class renaming + Cookies update on logour
Mar 16, 2017
072e031
Session handling code update, (HttpRequestProcessor, SessionHandler a…
May 5, 2017
23ba925
SessionCache type changed from List to Dictionary to better handle th…
May 5, 2017
883e7e5
some updates in comments
UmmarIqbal May 8, 2017
7cd2929
HybridSessionStorageHandler fixes
May 8, 2017
f887f2a
Merge branch 'session_support' of https://github.com/ummarbhutta/iotw…
May 8, 2017
2511557
Create appveyor.yml
ummarbhutta May 10, 2017
5c1d821
Update appveyor.yml
ummarbhutta May 10, 2017
5dc0bb0
Update appveyor.yml
ummarbhutta May 10, 2017
ba6ff10
Update appveyor.yml
ummarbhutta May 10, 2017
161dfcc
Update appveyor.yml
ummarbhutta May 10, 2017
0046295
Update appveyor.yml
ummarbhutta May 10, 2017
e7d699b
x64 configuration added for all projects
UmmarIqbal May 10, 2017
5c0482e
Merge branch 'master' of https://github.com/ummarbhutta/iotweb.git
UmmarIqbal May 10, 2017
02f2fad
build platform changed to x64
UmmarIqbal May 10, 2017
96089f4
pfx added for UWP project
UmmarIqbal May 10, 2017
548e408
readme update
UmmarIqbal May 10, 2017
4842feb
HttpServer object intialization with default session configuration + …
May 16, 2017
64b1a45
minor changes
UmmarIqbal May 17, 2017
acc4f05
Merge branch 'session_support' of https://github.com/ummarbhutta/iotw…
UmmarIqbal May 17, 2017
2ddf6e4
Code refactoring
May 24, 2017
b39b67b
Merge branch 'session_support' of https://github.com/ummarbhutta/iotw…
May 24, 2017
9e7ae61
1- Update of Session data after handling of 'After Filters' for request.
May 25, 2017
a34aa12
SessionHandler's SessionData and HybridSessionStorageHandler's Sessio…
May 29, 2017
2909b04
Minor fix
May 29, 2017
d62ee94
Merge pull request #1 from ummarbhutta/session_support
ummarbhutta Aug 4, 2017
a4293dd
- Request, Response and Context global objects changes reverted
UmmarIqbal Aug 9, 2017
eae10c0
Merge branch 'master' of https://github.com/ummarbhutta/iotweb.git
UmmarIqbal Aug 9, 2017
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
228 changes: 228 additions & 0 deletions IotWeb NET45/Helper/HybridSessionStorageHandler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using IotWeb.Common.Interfaces;
using IotWeb.Common.Util;
using System.Net.Mime;
using System.Security.AccessControl;
using IotWeb.Common.Http;
using Newtonsoft.Json;

namespace IotWeb.Server.Helper
{
public class HybridSessionStorageHandler : ISessionStorageHandler
{
private readonly SessionConfiguration _sessionConfiguration;
private Dictionary<string, SessionCacheObject> _sessionDataCache;
private readonly string _sessionFileExtension;

public HybridSessionStorageHandler(SessionConfiguration sessionConfiguration)
{
_sessionConfiguration = sessionConfiguration;
_sessionDataCache = new Dictionary<string, SessionCacheObject>();
_sessionFileExtension = "sess";
LoadSessionFiles();
}

private void LoadSessionFiles()
{
string[] files = Directory.GetFiles(GetStoragePath());

foreach (string file in files)
{
var sessionData = File.ReadAllText(file);
IDictionary<string, object> sessionDictionary = new Dictionary<string, object>();

if (!string.IsNullOrEmpty(sessionData))
sessionDictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(sessionData);

_sessionDataCache[Path.GetFileNameWithoutExtension(file)] = new SessionCacheObject(DateTime.Now, sessionDictionary);
}
}

public async Task<bool> DeleteSessionsAsync()
{
try
{
await Task.Run(() =>
{
lock (_sessionDataCache)
{
var sessionIds =
_sessionDataCache.Where(
s =>
s.Value.LastAccessTime <
DateTime.Now.AddMinutes(-_sessionConfiguration.SessionTimeOut)).Select(s => s.Key).ToList();

if (sessionIds.Count > 0)
{
foreach (var sid in sessionIds)
{
_sessionDataCache.Remove(sid);
}

string[] files = Directory.GetFiles(GetStoragePath());

var filesToDelete = files.Where(s => sessionIds.Contains(Path.GetFileNameWithoutExtension(s))).ToList();

foreach (string file in filesToDelete)
{
FileInfo fi = new FileInfo(file);
fi.Delete();
}
}
}
});

return true;
}
catch (Exception)
{
return false;
}
}

public async Task<bool> DeleteSessionAsync(string sessionId)
{
try
{
await Task.Run(() =>
{
lock (_sessionDataCache)
{
_sessionDataCache.Remove(sessionId);

if (File.Exists(GetFilePath(sessionId)))
{
FileInfo fi = new FileInfo(GetFilePath(sessionId));
fi.Delete();
}
}
});

return true;
}
catch (Exception)
{
return false;
}
}

public async Task<Dictionary<string, object>> GetDataAsync(string sessionId)
{
try
{
Dictionary<string, object> data = null;

await Task.Run(() =>
{
lock (_sessionDataCache)
{
if (_sessionDataCache.ContainsKey(sessionId))
{
_sessionDataCache[sessionId].LastAccessTime = DateTime.Now;
data = (Dictionary<string, object>)_sessionDataCache[sessionId].SessionData;
}
else if (File.Exists(GetFilePath(sessionId)))
{
var fileData = File.ReadAllText(GetFilePath(sessionId));
data = new Dictionary<string, object>();

if (!string.IsNullOrEmpty(fileData))
data = JsonConvert.DeserializeObject<Dictionary<string, object>>(fileData);

_sessionDataCache[sessionId] = new SessionCacheObject(DateTime.Now, data);
}
}
});

return data;
}
catch (Exception)
{
return null;
}
}

public async Task<Dictionary<SessionAttributes, object>> GetSessionMetadata(string sessionId)
{
throw new NotImplementedException();
}

public async Task<bool> SaveDataAsync(string sessionId, IDictionary<string, object> data)
{
try
{
bool isSaved = false;
await Task.Run(() =>
{
lock (_sessionDataCache)
{
_sessionDataCache[sessionId] = new SessionCacheObject(DateTime.Now, data);

var filePath = GetFilePath(sessionId);
var sessionData = JsonConvert.SerializeObject(data);
File.WriteAllText(filePath, sessionData);

isSaved = true;
}
});

return isSaved;
}
catch (Exception)
{
return false;
}
}

public bool UpdateSessionExpireTime(string sessionId)
{
lock (_sessionDataCache)
{
if (_sessionDataCache.ContainsKey(sessionId))
{
_sessionDataCache[sessionId].LastAccessTime = DateTime.Now;
return true;
}

return false;
}
}

private string GetStoragePath()
{
string fullStorageFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, _sessionConfiguration.StorageFolder);

if (!Directory.Exists(fullStorageFilePath))
Directory.CreateDirectory(fullStorageFilePath);

return fullStorageFilePath;
}

private string GetFilePath(string fileName)
{
string fullFilePath = Path.Combine(GetStoragePath(), fileName);

if (!string.IsNullOrWhiteSpace(_sessionFileExtension))
fullFilePath = fullFilePath + "." + _sessionFileExtension;

return fullFilePath;
}
}

public class SessionCacheObject
{
public DateTime LastAccessTime { get; set; }
public IDictionary<string, object> SessionData { get; set; }

public SessionCacheObject(DateTime lastAccessTime, IDictionary<string, object> sessionData)
{
LastAccessTime = lastAccessTime;
SessionData = sessionData;
}
}
}
14 changes: 11 additions & 3 deletions IotWeb NET45/HttpServer.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
using IotWeb.Common.Http;
using IotWeb.Common.Util;
using IotWeb.Server.Helper;

namespace IotWeb.Server
{
public class HttpServer : BaseHttpServer
{
public HttpServer(int port)
: base(new SocketServer(port))
{
public HttpServer(int port)
: base(new SocketServer(port), new HybridSessionStorageHandler(new SessionConfiguration()))
{
// No configuration required
}

public HttpServer(int port, SessionConfiguration sessionConfiguration)
: base(new SocketServer(port), new HybridSessionStorageHandler(sessionConfiguration))
{
// No configuration required
}
}
Expand Down
29 changes: 28 additions & 1 deletion IotWeb NET45/IotWeb NET45.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -29,23 +29,50 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>TRACE;DEBUG;NET45</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NET45</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Helper\HybridSessionStorageHandler.cs" />
<Compile Include="HttpServer.cs" />
<Compile Include="SocketServer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IotWeb Portable\IotWeb Portable.csproj">
<Project>{e788ca1a-9838-48a1-a961-1137e74eaf70}</Project>
<Project>{E788CA1A-9838-48A1-A961-1137E74EAF70}</Project>
<Name>IotWeb Portable</Name>
</ProjectReference>
</ItemGroup>
Expand Down
4 changes: 4 additions & 0 deletions IotWeb NET45/packages.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net45" />
</packages>
26 changes: 25 additions & 1 deletion IotWeb Portable/Http/BaseHttpServer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Collections.Generic;
using IotWeb.Common.Interfaces;

namespace IotWeb.Common.Http
{
Expand All @@ -17,7 +18,19 @@ public class BaseHttpServer : IServer

public bool Running { get { return SocketServer.Running; } }

protected BaseHttpServer(ISocketServer server)
private ISessionStorageHandler _sessionStorageHandler;
public ISessionStorageHandler SessionStorageHandler
{
get { return _sessionStorageHandler; }
}

protected BaseHttpServer(ISocketServer server, ISessionStorageHandler sessionStorageHandler)
: this(server)
{
_sessionStorageHandler = sessionStorageHandler;
}

protected BaseHttpServer(ISocketServer server)
{
SocketServer = server;
SocketServer.ConnectionRequested = ConnectionRequested;
Expand Down Expand Up @@ -204,4 +217,15 @@ internal IWebSocketRequestHandler GetHandlerForWebSocket(string uri, out string


}

/////////////////////////////////Changes done locally to fix HTTP 1.1 on Safari 10 websocket error on 22.11.2016/////////////////////
/// <summary>
/// Defines HTTP version
/// </summary>
public enum HttpVersion
{
Ver1_0,
Ver1_1
}
/////////////////////////////////Changes done locally to fix HTTP 1.1 on Safari 10 websocket error on 22.11.2016/////////////////////
}
7 changes: 6 additions & 1 deletion IotWeb Portable/Http/HttpContext.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
namespace IotWeb.Common.Http
using System.Collections.Generic;
using IotWeb.Common.Util;

namespace IotWeb.Common.Http
{
public class HttpContext : CaseInsensitiveDictionary<object>
{
/// <summary>
/// Common name for session entry.
/// </summary>
public const string Session = "Session";

public SessionHandler SessionHandler;
}
}
Loading