From 5641184ee6ebba0daa8e5a726f3b942b230928d1 Mon Sep 17 00:00:00 2001 From: sta Date: Sat, 13 Jun 2015 17:20:00 +0900 Subject: [PATCH] Reset the headers after the updated headers are sent successfully --- websocket-sharp/Net/HttpListenerResponse.cs | 54 ++++++++++++--------- websocket-sharp/Net/ResponseStream.cs | 19 +++++--- 2 files changed, 43 insertions(+), 30 deletions(-) diff --git a/websocket-sharp/Net/HttpListenerResponse.cs b/websocket-sharp/Net/HttpListenerResponse.cs index 94fc6346..7570f20f 100644 --- a/websocket-sharp/Net/HttpListenerResponse.cs +++ b/websocket-sharp/Net/HttpListenerResponse.cs @@ -233,10 +233,7 @@ namespace WebSocketSharp.Net /// The value specified for a set operation is . /// /// - /// The response has already been sent. - /// - /// - /// This object is closed. + /// The headers has already been sent. /// public WebHeaderCollection Headers { get { @@ -254,7 +251,7 @@ namespace WebSocketSharp.Net // TODO: Check if this is marked readonly after the headers are sent. - checkDisposedOrHeadersSent (); + checkHeadersSent (); if (value == null) throw new ArgumentNullException ("value"); @@ -482,6 +479,12 @@ 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; @@ -505,23 +508,26 @@ namespace WebSocketSharp.Net #region Internal Methods - internal void WriteHeadersTo (MemoryStream destination, bool closing) + internal WebHeaderCollection WriteHeadersTo (MemoryStream destination, bool closing) { + var headers = new WebHeaderCollection (); + headers.Add (_headers); + if (_contentType != null) { var type = _contentType.IndexOf ("charset=", StringComparison.Ordinal) == -1 && _contentEncoding != null ? String.Format ("{0}; charset={1}", _contentType, _contentEncoding.WebName) : _contentType; - _headers.InternalSet ("Content-Type", type, true); + headers.InternalSet ("Content-Type", type, true); } - if (_headers["Server"] == null) - _headers.InternalSet ("Server", "websocket-sharp/1.0", true); + if (headers["Server"] == null) + headers.InternalSet ("Server", "websocket-sharp/1.0", true); var prov = CultureInfo.InvariantCulture; - if (_headers["Date"] == null) - _headers.InternalSet ("Date", DateTime.UtcNow.ToString ("r", prov), true); + if (headers["Date"] == null) + headers.InternalSet ("Date", DateTime.UtcNow.ToString ("r", prov), true); if (!_chunked) { if (!_contentLengthSet && closing) { @@ -530,13 +536,13 @@ namespace WebSocketSharp.Net } if (_contentLengthSet) - _headers.InternalSet ("Content-Length", _contentLength.ToString (prov), true); + headers.InternalSet ("Content-Length", _contentLength.ToString (prov), true); else if (_context.Request.ProtocolVersion > HttpVersion.Version10) _chunked = true; } if (_chunked) - _headers.InternalSet ("Transfer-Encoding", "chunked", true); + headers.InternalSet ("Transfer-Encoding", "chunked", true); /* * Apache forces closing the connection for these status codes: @@ -548,43 +554,45 @@ namespace WebSocketSharp.Net * - HttpStatusCode.InternalServerError 500 * - HttpStatusCode.ServiceUnavailable 503 */ - var closeConn = _statusCode == 400 || + var closeConn = !_context.Request.KeepAlive || + !_keepAlive || + _statusCode == 400 || _statusCode == 408 || _statusCode == 411 || _statusCode == 413 || _statusCode == 414 || _statusCode == 500 || - _statusCode == 503 || - !_context.Request.KeepAlive || - !_keepAlive; + _statusCode == 503; var reuses = _context.Connection.Reuses; if (closeConn || reuses >= 100) { - _headers.InternalSet ("Connection", "close", true); + headers.InternalSet ("Connection", "close", true); } else { - _headers.InternalSet ( + headers.InternalSet ( "Keep-Alive", String.Format ("timeout=15,max={0}", 100 - reuses), true); if (_context.Request.ProtocolVersion < HttpVersion.Version11) - _headers.InternalSet ("Connection", "keep-alive", true); + headers.InternalSet ("Connection", "keep-alive", true); } if (_location != null) - _headers.InternalSet ("Location", _location, true); + headers.InternalSet ("Location", _location, true); if (_cookies != null) foreach (Cookie cookie in _cookies) - _headers.InternalSet ("Set-Cookie", cookie.ToResponseString (), true); + headers.InternalSet ("Set-Cookie", cookie.ToResponseString (), true); var enc = _contentEncoding ?? Encoding.Default; var writer = new StreamWriter (destination, enc, 256); writer.Write ("HTTP/{0} {1} {2}\r\n", _version, _statusCode, _statusDescription); - writer.Write (_headers.ToStringMultiValue (true)); + writer.Write (headers.ToStringMultiValue (true)); writer.Flush (); // Assumes that the destination was at position 0. destination.Position = enc.CodePage == 65001 ? 3 : enc.GetPreamble ().Length; + + return headers; } #endregion diff --git a/websocket-sharp/Net/ResponseStream.cs b/websocket-sharp/Net/ResponseStream.cs index 09b7196e..250d2b9f 100644 --- a/websocket-sharp/Net/ResponseStream.cs +++ b/websocket-sharp/Net/ResponseStream.cs @@ -128,8 +128,12 @@ namespace WebSocketSharp.Net private bool flush (bool closing) { if (!_response.HeadersSent) { - if (!flushHeaders (closing)) + if (!flushHeaders (closing)) { + if (closing) + _response.Headers.InternalSet ("Connection", "close", true); + return false; + } _chunked = _response.SendChunked; _writeBody = _chunked ? _writeChunked : _write; @@ -166,20 +170,21 @@ namespace WebSocketSharp.Net private bool flushHeaders (bool closing) { - using (var headers = new MemoryStream ()) { - _response.WriteHeadersTo (headers, closing); - var start = headers.Position; - var len = headers.Length - start; + using (var buff = new MemoryStream ()) { + var headers = _response.WriteHeadersTo (buff, closing); + var start = buff.Position; + var len = buff.Length - start; if (len > 32768) return false; if (!_response.SendChunked && _response.ContentLength64 != _body.Length) return false; - _write (headers.GetBuffer (), (int) start, (int) len); + _write (buff.GetBuffer (), (int) start, (int) len); + _response.Headers = headers; + _response.HeadersSent = true; } - _response.HeadersSent = true; return true; }