From 0c610dd41f9c56e4f861bf3a7f5dbf3af49e1f97 Mon Sep 17 00:00:00 2001 From: sta Date: Tue, 16 Jun 2015 21:37:55 +0900 Subject: [PATCH] Refactored HttpListenerResponse.cs --- websocket-sharp/Net/HttpListenerResponse.cs | 205 ++++++++------------ websocket-sharp/Net/ResponseStream.cs | 4 +- 2 files changed, 84 insertions(+), 125 deletions(-) diff --git a/websocket-sharp/Net/HttpListenerResponse.cs b/websocket-sharp/Net/HttpListenerResponse.cs index 7570f20f..c0b011ff 100644 --- a/websocket-sharp/Net/HttpListenerResponse.cs +++ b/websocket-sharp/Net/HttpListenerResponse.cs @@ -56,6 +56,7 @@ namespace WebSocketSharp.Net #region Private Fields private bool _chunked; + private bool _closeConnection; private Encoding _contentEncoding; private long _contentLength; private bool _contentLengthSet; @@ -79,7 +80,6 @@ namespace WebSocketSharp.Net internal HttpListenerResponse (HttpListenerContext context) { _context = context; - _headers = new WebHeaderCollection (); _keepAlive = true; _statusCode = 200; _statusDescription = "OK"; @@ -92,7 +92,11 @@ namespace WebSocketSharp.Net internal bool CloseConnection { get { - return _headers["Connection"] == "close"; + return _closeConnection; + } + + set { + _closeConnection = value; } } @@ -171,12 +175,12 @@ namespace WebSocketSharp.Net /// /// A that represents the value of the Content-Type entity-header. /// - /// - /// The value specified for a set operation is empty. - /// /// /// The value specified for a set operation is . /// + /// + /// The value specified for a set operation is empty. + /// /// /// The response has already been sent. /// @@ -206,19 +210,12 @@ namespace WebSocketSharp.Net /// /// A that contains the cookies sent with the response. /// - /// - /// The response has already been sent. - /// - /// - /// This object is closed. - /// public CookieCollection Cookies { get { return _cookies ?? (_cookies = new CookieCollection ()); } set { - checkDisposedOrHeadersSent (); _cookies = value; } } @@ -229,31 +226,18 @@ namespace WebSocketSharp.Net /// /// A that contains the headers sent to the client. /// - /// - /// The value specified for a set operation is . - /// /// - /// The headers has already been sent. + /// The value specified for a set operation isn't valid for a response. /// public WebHeaderCollection Headers { get { - return _headers; + return _headers ?? (_headers = new WebHeaderCollection (HttpHeaderType.Response, false)); } set { - /* - * "If you attempt to set a Content-Length, Keep-Alive, Transfer-Encoding, - * or WWW-Authenticate header using the Headers property, an exception - * will be thrown. Use the ContentLength64 or KeepAlive properties to set - * these headers. You cannot set the Transfer-Encoding or WWW-Authenticate - * headers manually." - */ - - // TODO: Check if this is marked readonly after the headers are sent. - - checkHeadersSent (); - if (value == null) - throw new ArgumentNullException ("value"); + if (value != null && value.State != HttpHeaderType.Response) + throw new InvalidOperationException ( + "The specified headers aren't valid for a response."); _headers = value; } @@ -305,13 +289,13 @@ namespace WebSocketSharp.Net /// /// A that represents the version used in the response. /// + /// + /// The value specified for a set operation is . + /// /// /// The value specified for a set operation doesn't have its Major property set to 1 or /// doesn't have its Minor property set to either 0 or 1. /// - /// - /// The value specified for a set operation is . - /// /// /// The response has already been sent. /// @@ -344,9 +328,6 @@ namespace WebSocketSharp.Net /// /// The value specified for a set operation is empty. /// - /// - /// The response has already been sent. - /// /// /// This object is closed. /// @@ -356,8 +337,8 @@ namespace WebSocketSharp.Net } set { - checkDisposedOrHeadersSent (); - if (value.Length == 0) + checkDisposed (); + if (value != null && value.Length == 0) throw new ArgumentException ("An empty string.", "value"); _location = value; @@ -397,12 +378,12 @@ namespace WebSocketSharp.Net /// /// The response has already been sent. /// - /// - /// The value specified for a set operation is invalid. Valid values are between 100 and 999. - /// /// /// This object is closed. /// + /// + /// The value specified for a set operation is invalid. Valid values are between 100 and 999. + /// public int StatusCode { get { return _statusCode; @@ -424,6 +405,9 @@ namespace WebSocketSharp.Net /// /// A that represents the description of the status code. /// + /// + /// The value specified for a set operation is . + /// /// /// The response has already been sent. /// @@ -437,7 +421,10 @@ namespace WebSocketSharp.Net set { checkDisposedOrHeadersSent (); - _statusDescription = value != null && value.Length > 0 + if (value == null) + throw new ArgumentNullException ("value"); + + _statusDescription = value.Length > 0 ? value : _statusCode.GetStatusDescription (); } @@ -479,12 +466,6 @@ namespace WebSocketSharp.Net throw new InvalidOperationException ("Cannot be changed after the headers are sent."); } - private void checkHeadersSent () - { - if (_headersSent) - throw new InvalidOperationException ("Cannot be changed after the headers are sent."); - } - private void close (bool force) { _disposed = true; @@ -510,8 +491,9 @@ namespace WebSocketSharp.Net internal WebHeaderCollection WriteHeadersTo (MemoryStream destination, bool closing) { - var headers = new WebHeaderCollection (); - headers.Add (_headers); + var headers = new WebHeaderCollection (HttpHeaderType.Response, true); + if (_headers != null) + headers.Add (_headers); if (_contentType != null) { var type = _contentType.IndexOf ("charset=", StringComparison.Ordinal) == -1 && @@ -546,13 +528,13 @@ namespace WebSocketSharp.Net /* * Apache forces closing the connection for these status codes: - * - HttpStatusCode.BadRequest 400 - * - HttpStatusCode.RequestTimeout 408 - * - HttpStatusCode.LengthRequired 411 - * - HttpStatusCode.RequestEntityTooLarge 413 - * - HttpStatusCode.RequestUriTooLong 414 - * - HttpStatusCode.InternalServerError 500 - * - HttpStatusCode.ServiceUnavailable 503 + * - 400 Bad Request + * - 408 Request Timeout + * - 411 Length Required + * - 413 Request Entity Too Large + * - 414 Request-Uri Too Long + * - 500 Internal Server Error + * - 503 Service Unavailable */ var closeConn = !_context.Request.KeepAlive || !_keepAlive || @@ -620,6 +602,9 @@ namespace WebSocketSharp.Net /// /// A that represents the value of the header to add. /// + /// + /// is or empty. + /// /// /// /// or contains invalid characters. @@ -631,30 +616,15 @@ namespace WebSocketSharp.Net /// is a restricted header name. /// /// - /// - /// is or empty. - /// /// /// The length of is greater than 65,535 characters. /// /// - /// - /// The response has already been sent. - /// - /// - /// -or- - /// - /// - /// The header cannot be allowed to add to the current headers. - /// - /// - /// - /// This object is closed. + /// The header cannot be allowed to add to the current headers. /// public void AddHeader (string name, string value) { - checkDisposedOrHeadersSent (); - _headers.Set (name, value); + Headers.Set (name, value); } /// @@ -666,15 +636,8 @@ namespace WebSocketSharp.Net /// /// is . /// - /// - /// The response has already been sent. - /// - /// - /// This object is closed. - /// public void AppendCookie (Cookie cookie) { - checkDisposedOrHeadersSent (); Cookies.Add (cookie); } @@ -688,6 +651,9 @@ namespace WebSocketSharp.Net /// /// A that represents the value to append to the header. /// + /// + /// is or empty. + /// /// /// /// or contains invalid characters. @@ -699,30 +665,15 @@ namespace WebSocketSharp.Net /// is a restricted header name. /// /// - /// - /// is or empty. - /// /// /// The length of is greater than 65,535 characters. /// /// - /// - /// The response has already been sent. - /// - /// - /// -or- - /// - /// - /// The current headers cannot allow the header to append a value. - /// - /// - /// - /// This object is closed. + /// The current headers cannot allow the header to append a value. /// public void AppendHeader (string name, string value) { - checkDisposedOrHeadersSent (); - _headers.Add (name, value); + Headers.Add (name, value); } /// @@ -781,24 +732,32 @@ namespace WebSocketSharp.Net } /// - /// Copies properties from the specified to this response. + /// Copies some properties from the specified to + /// this response. /// /// /// A to copy. /// - /// - /// The response has already been sent. - /// - /// - /// This object is closed. + /// + /// is . /// public void CopyFrom (HttpListenerResponse templateResponse) { - checkDisposedOrHeadersSent (); + if (templateResponse == null) + throw new ArgumentNullException ("templateResponse"); + + if (templateResponse._headers != null) { + if (_headers != null) + _headers.Clear (); + + Headers.Add (templateResponse._headers); + } + else if (_headers != null) { + _headers = null; + } - _headers.Clear (); - _headers.Add (templateResponse._headers); _contentLength = templateResponse._contentLength; + _contentLengthSet = templateResponse._contentLengthSet; _statusCode = templateResponse._statusCode; _statusDescription = templateResponse._statusDescription; _keepAlive = templateResponse._keepAlive; @@ -806,22 +765,29 @@ namespace WebSocketSharp.Net } /// - /// Configures the response to redirect the client's request to the specified - /// . + /// Configures the response to redirect the client's request to + /// the specified . /// /// /// A that represents the URL to redirect the client's request to. /// - /// - /// The response has already been sent. + /// + /// is . /// - /// - /// This object is closed. + /// + /// is empty. /// public void Redirect (string url) { - StatusCode = (int) HttpStatusCode.Redirect; + if (url == null) + throw new ArgumentNullException ("url"); + + if (url.Length == 0) + throw new ArgumentException ("An empty string.", "url"); + _location = url; + _statusCode = 302; + _statusDescription = "Found"; } /// @@ -830,21 +796,14 @@ namespace WebSocketSharp.Net /// /// A to set. /// - /// - /// already exists in the cookies and couldn't be replaced. - /// /// /// is . /// - /// - /// The response has already been sent. - /// - /// - /// This object is closed. + /// + /// already exists in the cookies and couldn't be replaced. /// public void SetCookie (Cookie cookie) { - checkDisposedOrHeadersSent (); if (cookie == null) throw new ArgumentNullException ("cookie"); diff --git a/websocket-sharp/Net/ResponseStream.cs b/websocket-sharp/Net/ResponseStream.cs index 250d2b9f..ad3c760a 100644 --- a/websocket-sharp/Net/ResponseStream.cs +++ b/websocket-sharp/Net/ResponseStream.cs @@ -130,7 +130,7 @@ namespace WebSocketSharp.Net if (!_response.HeadersSent) { if (!flushHeaders (closing)) { if (closing) - _response.Headers.InternalSet ("Connection", "close", true); + _response.CloseConnection = true; return false; } @@ -181,7 +181,7 @@ namespace WebSocketSharp.Net return false; _write (buff.GetBuffer (), (int) start, (int) len); - _response.Headers = headers; + _response.CloseConnection = headers["Connection"] == "close"; _response.HeadersSent = true; }