diff --git a/websocket-sharp/HandshakeRequest.cs b/websocket-sharp/HandshakeRequest.cs
index 92d90776..604ce6f6 100644
--- a/websocket-sharp/HandshakeRequest.cs
+++ b/websocket-sharp/HandshakeRequest.cs
@@ -28,7 +28,6 @@
using System;
using System.Collections.Specialized;
-using System.Linq;
using System.Text;
using WebSocketSharp.Net;
@@ -38,10 +37,8 @@ namespace WebSocketSharp
{
#region Private Fields
- private string _method;
- private NameValueCollection _queryString;
- private string _rawUrl;
- private Uri _uri;
+ private string _method;
+ private string _uri;
#endregion
@@ -55,10 +52,9 @@ namespace WebSocketSharp
#region Public Constructors
- public HandshakeRequest (string uriString)
+ public HandshakeRequest (string absPathAndQuery)
{
- _uri = uriString.ToUri ();
- _rawUrl = _uri.IsAbsoluteUri ? _uri.PathAndQuery : uriString;
+ _uri = absPathAndQuery;
_method = "GET";
var headers = Headers;
@@ -73,9 +69,9 @@ namespace WebSocketSharp
public AuthenticationResponse AuthResponse {
get {
- var response = Headers ["Authorization"];
- return response != null && response.Length > 0
- ? AuthenticationResponse.Parse (response)
+ var auth = Headers ["Authorization"];
+ return auth != null && auth.Length > 0
+ ? AuthenticationResponse.Parse (auth)
: null;
}
}
@@ -100,47 +96,13 @@ namespace WebSocketSharp
get {
var headers = Headers;
return _method == "GET" &&
- ProtocolVersion >= HttpVersion.Version11 &&
+ ProtocolVersion > HttpVersion.Version10 &&
headers.Contains ("Upgrade", "websocket") &&
headers.Contains ("Connection", "Upgrade");
}
}
- public NameValueCollection QueryString {
- get {
- if (_queryString == null) {
- _queryString = new NameValueCollection ();
-
- var i = RawUrl.IndexOf ('?');
- if (i > 0) {
- var query = RawUrl.Substring (i + 1);
- var components = query.Split ('&');
- foreach (var c in components) {
- var nv = c.GetNameAndValue ("=");
- if (nv.Key != null) {
- var name = nv.Key.UrlDecode ();
- var val = nv.Value.UrlDecode ();
- _queryString.Add (name, val);
- }
- }
- }
- }
-
- return _queryString;
- }
- }
-
- public string RawUrl {
- get {
- return _rawUrl;
- }
-
- private set {
- _rawUrl = value;
- }
- }
-
- public Uri RequestUri {
+ public string RequestUri {
get {
return _uri;
}
@@ -156,7 +118,7 @@ namespace WebSocketSharp
public static HandshakeRequest Parse (string [] headerParts)
{
- var requestLine = headerParts [0].Split (new char [] { ' ' }, 3);
+ var requestLine = headerParts [0].Split (new [] { ' ' }, 3);
if (requestLine.Length != 3)
throw new ArgumentException ("Invalid request line: " + headerParts [0]);
@@ -168,8 +130,7 @@ namespace WebSocketSharp
Headers = headers,
HttpMethod = requestLine [0],
ProtocolVersion = new Version (requestLine [2].Substring (5)),
- RawUrl = requestLine [1],
- RequestUri = requestLine [1].ToUri ()
+ RequestUri = requestLine [1]
};
}
@@ -178,32 +139,34 @@ namespace WebSocketSharp
if (cookies == null || cookies.Count == 0)
return;
- var sorted = cookies.Sorted.ToArray ();
- var header = new StringBuilder (sorted [0].ToString (), 64);
- for (int i = 1; i < sorted.Length; i++)
- if (!sorted [i].Expired)
- header.AppendFormat ("; {0}", sorted [i].ToString ());
+ var buff = new StringBuilder (64);
+ foreach (var cookie in cookies.Sorted)
+ if (!cookie.Expired)
+ buff.AppendFormat ("{0}; ", cookie.ToString ());
- Headers ["Cookie"] = header.ToString ();
+ var len = buff.Length;
+ if (len > 2) {
+ buff.Length = len - 2;
+ Headers ["Cookie"] = buff.ToString ();
+ }
}
public override string ToString ()
{
- var buffer = new StringBuilder (64);
- buffer.AppendFormat (
- "{0} {1} HTTP/{2}{3}", _method, _rawUrl, ProtocolVersion, CrLf);
+ var buff = new StringBuilder (64);
+ buff.AppendFormat ("{0} {1} HTTP/{2}{3}", _method, _uri, ProtocolVersion, CrLf);
var headers = Headers;
foreach (var key in headers.AllKeys)
- buffer.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
+ buff.AppendFormat ("{0}: {1}{2}", key, headers [key], CrLf);
- buffer.Append (CrLf);
+ buff.Append (CrLf);
var entity = EntityBody;
if (entity.Length > 0)
- buffer.Append (entity);
+ buff.Append (entity);
- return buffer.ToString ();
+ return buff.ToString ();
}
#endregion
diff --git a/websocket-sharp/Net/HttpListenerRequest.cs b/websocket-sharp/Net/HttpListenerRequest.cs
index 1abaca02..6e6661b4 100644
--- a/websocket-sharp/Net/HttpListenerRequest.cs
+++ b/websocket-sharp/Net/HttpListenerRequest.cs
@@ -346,6 +346,7 @@ namespace WebSocketSharp.Net
///
public string RawUrl {
get {
+ // TODO: Should decode?
return _url.PathAndQuery;
}
}
@@ -467,7 +468,10 @@ namespace WebSocketSharp.Net
var i = component.IndexOf ('=');
if (i > -1) {
var name = HttpUtility.UrlDecode (component.Substring (0, i));
- var val = HttpUtility.UrlDecode (component.Substring (i + 1));
+ var val = component.Length > i + 1
+ ? HttpUtility.UrlDecode (component.Substring (i + 1))
+ : String.Empty;
+
res.Add (name, val);
}
else {
@@ -571,7 +575,7 @@ namespace WebSocketSharp.Net
string scheme = null;
string path = null;
if (_uri.StartsWith ("/")) {
- path = HttpUtility.UrlDecode (_uri);
+ path = _uri;
}
else if (_uri.MaybeUri ()) {
Uri uri;
@@ -589,7 +593,7 @@ namespace WebSocketSharp.Net
}
else {
// As authority form
- host = HttpUtility.UrlDecode (_uri);
+ host = _uri;
}
if (scheme == null)
diff --git a/websocket-sharp/Net/WebSockets/HttpListenerWebSocketContext.cs b/websocket-sharp/Net/WebSockets/HttpListenerWebSocketContext.cs
index c47fd797..76892ccc 100644
--- a/websocket-sharp/Net/WebSockets/HttpListenerWebSocketContext.cs
+++ b/websocket-sharp/Net/WebSockets/HttpListenerWebSocketContext.cs
@@ -167,18 +167,6 @@ namespace WebSocketSharp.Net.WebSockets
}
}
- ///
- /// Gets the absolute path of the requested URI.
- ///
- ///
- /// A that represents the absolute path of the requested URI.
- ///
- public override string Path {
- get {
- return _context.Request.Url.GetAbsolutePath ();
- }
- }
-
///
/// Gets the query string variables included in the request.
///
diff --git a/websocket-sharp/Net/WebSockets/TcpListenerWebSocketContext.cs b/websocket-sharp/Net/WebSockets/TcpListenerWebSocketContext.cs
index c9ec8338..48d428bd 100644
--- a/websocket-sharp/Net/WebSockets/TcpListenerWebSocketContext.cs
+++ b/websocket-sharp/Net/WebSockets/TcpListenerWebSocketContext.cs
@@ -45,14 +45,15 @@ namespace WebSocketSharp.Net.WebSockets
{
#region Private Fields
- private TcpClient _client;
- private CookieCollection _cookies;
- private HandshakeRequest _request;
- private bool _secure;
- private WebSocketStream _stream;
- private Uri _uri;
- private IPrincipal _user;
- private WebSocket _websocket;
+ private TcpClient _client;
+ private CookieCollection _cookies;
+ private NameValueCollection _queryString;
+ private HandshakeRequest _request;
+ private bool _secure;
+ private WebSocketStream _stream;
+ private Uri _uri;
+ private IPrincipal _user;
+ private WebSocket _websocket;
#endregion
@@ -65,6 +66,7 @@ namespace WebSocketSharp.Net.WebSockets
_secure = secure;
_stream = WebSocketStream.CreateServerStream (client, secure, cert);
_request = _stream.ReadHandshake (HandshakeRequest.Parse, 90000);
+ _uri = createRequestUrl (_request, secure);
_websocket = new WebSocket (this, protocol, logger);
}
@@ -178,18 +180,6 @@ namespace WebSocketSharp.Net.WebSockets
}
}
- ///
- /// Gets the absolute path of the requested URI.
- ///
- ///
- /// A that represents the absolute path of the requested URI.
- ///
- public override string Path {
- get {
- return _request.RequestUri.GetAbsolutePath ();
- }
- }
-
///
/// Gets the query string variables included in the request.
///
@@ -198,7 +188,8 @@ namespace WebSocketSharp.Net.WebSockets
///
public override NameValueCollection QueryString {
get {
- return _request.QueryString;
+ return _queryString ??
+ (_queryString = createQueryString (_uri != null ? _uri.Query : null));
}
}
@@ -210,7 +201,7 @@ namespace WebSocketSharp.Net.WebSockets
///
public override Uri RequestUri {
get {
- return _uri ?? (_uri = createRequestUri ());
+ return _uri;
}
}
@@ -318,16 +309,78 @@ namespace WebSocketSharp.Net.WebSockets
#region Private Methods
- private Uri createRequestUri ()
+ private static NameValueCollection createQueryString (string query)
{
- var scheme = _secure ? "wss" : "ws";
- var host = _request.Headers ["Host"];
- var rawUri = _request.RequestUri;
- var path = rawUri.IsAbsoluteUri
- ? rawUri.PathAndQuery
- : HttpUtility.UrlDecode (_request.RawUrl);
+ if (query == null || query.Length == 0)
+ return new NameValueCollection (1);
- return String.Format ("{0}://{1}{2}", scheme, host, path).ToUri ();
+ var res = new NameValueCollection ();
+ if (query [0] == '?')
+ query = query.Substring (1);
+
+ var components = query.Split ('&');
+ foreach (var component in components) {
+ var i = component.IndexOf ('=');
+ if (i > -1) {
+ var name = HttpUtility.UrlDecode (component.Substring (0, i));
+ var val = component.Length > i + 1
+ ? HttpUtility.UrlDecode (component.Substring (i + 1))
+ : String.Empty;
+
+ res.Add (name, val);
+ }
+ else {
+ res.Add (null, HttpUtility.UrlDecode (component));
+ }
+ }
+
+ return res;
+ }
+
+ private static Uri createRequestUrl (HandshakeRequest request, bool secure)
+ {
+ var host = request.Headers ["Host"];
+ if (host == null || host.Length == 0)
+ return null;
+
+ string scheme = null;
+ string path = null;
+
+ var reqUri = request.RequestUri;
+ if (reqUri.StartsWith ("/")) {
+ path = reqUri;
+ }
+ else if (reqUri.MaybeUri ()) {
+ Uri uri;
+ if (!Uri.TryCreate (reqUri, UriKind.Absolute, out uri) ||
+ !uri.Scheme.StartsWith ("ws"))
+ return null;
+
+ scheme = uri.Scheme;
+ host = uri.Authority;
+ path = uri.PathAndQuery;
+ }
+ else if (reqUri == "*") {
+ }
+ else {
+ // As authority form
+ host = reqUri;
+ }
+
+ if (scheme == null)
+ scheme = secure ? "wss" : "ws";
+
+ var colon = host.IndexOf (':');
+ if (colon == -1)
+ host = String.Format ("{0}:{1}", host, scheme == "ws" ? 80 : 443);
+
+ var url = String.Format ("{0}://{1}{2}", scheme, host, path);
+
+ Uri res;
+ if (!Uri.TryCreate (url, UriKind.Absolute, out res))
+ return null;
+
+ return res;
}
#endregion
diff --git a/websocket-sharp/Net/WebSockets/WebSocketContext.cs b/websocket-sharp/Net/WebSockets/WebSocketContext.cs
index 78930148..35803982 100644
--- a/websocket-sharp/Net/WebSockets/WebSocketContext.cs
+++ b/websocket-sharp/Net/WebSockets/WebSocketContext.cs
@@ -118,14 +118,6 @@ namespace WebSocketSharp.Net.WebSockets
///
public abstract string Origin { get; }
- ///
- /// Gets the absolute path of the requested URI.
- ///
- ///
- /// A that represents the absolute path of the requested URI.
- ///
- public abstract string Path { get; }
-
///
/// Gets the query string variables included in the request.
///
diff --git a/websocket-sharp/Server/HttpServer.cs b/websocket-sharp/Server/HttpServer.cs
index 19e14a6e..7b2d5491 100644
--- a/websocket-sharp/Server/HttpServer.cs
+++ b/websocket-sharp/Server/HttpServer.cs
@@ -505,10 +505,8 @@ namespace WebSocketSharp.Server
private void acceptWebSocketRequest (HttpListenerWebSocketContext context)
{
- var path = context.Path;
-
WebSocketServiceHost host;
- if (path == null || !_services.TryGetServiceHostInternally (path, out host)) {
+ if (!_services.TryGetServiceHostInternally (context.RequestUri.AbsolutePath, out host)) {
context.Close (HttpStatusCode.NotImplemented);
return;
}
diff --git a/websocket-sharp/Server/WebSocketServer.cs b/websocket-sharp/Server/WebSocketServer.cs
index ce433bf9..712bf5fd 100644
--- a/websocket-sharp/Server/WebSocketServer.cs
+++ b/websocket-sharp/Server/WebSocketServer.cs
@@ -492,16 +492,28 @@ namespace WebSocketSharp.Server
private void acceptWebSocket (TcpListenerWebSocketContext context)
{
- var path = context.Path;
-
- WebSocketServiceHost host;
- if (path == null || !_services.TryGetServiceHostInternally (path, out host)) {
- context.Close (HttpStatusCode.NotImplemented);
+ var reqUri = context.RequestUri;
+ if (reqUri == null) {
+ context.Close (HttpStatusCode.BadRequest);
return;
}
- if (_uri.IsAbsoluteUri)
- context.WebSocket.Url = new Uri (_uri, path);
+ if (_uri.IsAbsoluteUri) {
+ var req = reqUri.DnsSafeHost;
+ var expected = _uri.DnsSafeHost;
+ if (Uri.CheckHostName (req) == UriHostNameType.Dns &&
+ Uri.CheckHostName (expected) == UriHostNameType.Dns &&
+ req != expected) {
+ context.Close (HttpStatusCode.NotFound);
+ return;
+ }
+ }
+
+ WebSocketServiceHost host;
+ if (!_services.TryGetServiceHostInternally (reqUri.AbsolutePath, out host)) {
+ context.Close (HttpStatusCode.NotImplemented);
+ return;
+ }
host.StartSession (context);
}
diff --git a/websocket-sharp/WebSocket.cs b/websocket-sharp/WebSocket.cs
index 8056dadc..5fc1e346 100644
--- a/websocket-sharp/WebSocket.cs
+++ b/websocket-sharp/WebSocket.cs
@@ -118,7 +118,6 @@ namespace WebSocketSharp
_closeContext = context.Close;
_secure = context.IsSecureConnection;
_stream = context.Stream;
- _uri = context.Path.ToUri ();
init ();
}
@@ -133,7 +132,6 @@ namespace WebSocketSharp
_closeContext = context.Close;
_secure = context.IsSecureConnection;
_stream = context.Stream;
- _uri = context.Path.ToUri ();
init ();
}
@@ -459,11 +457,9 @@ namespace WebSocketSharp
///
public Uri Url {
get {
- return _uri;
- }
-
- internal set {
- _uri = value;
+ return _client
+ ? _uri
+ : _context.RequestUri;
}
}
@@ -685,10 +681,10 @@ namespace WebSocketSharp
private string checkIfValidHandshakeRequest (WebSocketContext context)
{
var headers = context.Headers;
- return !context.IsWebSocketRequest
- ? "Not WebSocket connection request."
- : !validateHostHeader (headers ["Host"])
- ? "Invalid Host header."
+ return context.RequestUri == null
+ ? "Invalid request url."
+ : !context.IsWebSocketRequest
+ ? "Not WebSocket connection request."
: !validateSecWebSocketKeyHeader (headers ["Sec-WebSocket-Key"])
? "Invalid Sec-WebSocket-Key header."
: !validateSecWebSocketVersionClientHeader (headers ["Sec-WebSocket-Version"])
@@ -1311,24 +1307,6 @@ namespace WebSocketSharp
receive ();
}
- // As server
- private bool validateHostHeader (string value)
- {
- if (value == null || value.Length == 0)
- return false;
-
- if (!_uri.IsAbsoluteUri)
- return true;
-
- var i = value.IndexOf (':');
- var host = i > 0 ? value.Substring (0, i) : value;
- var expected = _uri.DnsSafeHost;
-
- return Uri.CheckHostName (host) != UriHostNameType.Dns ||
- Uri.CheckHostName (expected) != UriHostNameType.Dns ||
- host == expected;
- }
-
// As client
private bool validateSecWebSocketAcceptHeader (string value)
{