internal System.IO.Stream GetSaveStream(HTTPResponse response) { if (!HTTPCacheService.IsSupported) { return(null); } LastAccess = DateTime.UtcNow; string path = GetPath(); if (HTTPManager.IOService.FileExists(path)) { Delete(); } // Path name too long, we don't want to get exceptions if (path.Length > HTTPManager.MaxPathLength) { return(null); } // First write out the headers using (Stream writer = HTTPManager.IOService.CreateFileStream(GetPath(), FileStreamModes.Create)) { writer.WriteLine("HTTP/1.1 {0} {1}", response.StatusCode, response.Message); foreach (var kvp in response.Headers) { for (int i = 0; i < kvp.Value.Count; ++i) { writer.WriteLine("{0}: {1}", kvp.Key, kvp.Value[i]); } } writer.WriteLine(); } // If caching is enabled and the response is from cache, and no content-length header set, then we set one to the response. if (response.IsFromCache && !response.HasHeader("content-length")) { response.AddHeader("content-length", BodyLength.ToString()); } SetUpCachingValues(response); // then create the stream with Append FileMode return(HTTPManager.IOService.CreateFileStream(GetPath(), FileStreamModes.Append)); }
private void OnRequestFinished(HTTPRequest req, HTTPResponse resp) { if (State != States.Closed) { if (State == States.Closing || req.State == HTTPRequestStates.Aborted) { SetClosed("OnRequestFinished"); } else { string text = string.Empty; bool flag = true; switch (req.State) { case HTTPRequestStates.Processing: flag = !resp.HasHeader("content-length"); break; case HTTPRequestStates.Finished: if (resp.StatusCode == 200 && !resp.HasHeaderWithValue("content-type", "text/event-stream")) { text = "No Content-Type header with value 'text/event-stream' present."; flag = false; } if (flag && resp.StatusCode != 500 && resp.StatusCode != 502 && resp.StatusCode != 503 && resp.StatusCode != 504) { flag = false; text = $"Request Finished Successfully, but the server sent an error. Status Code: {resp.StatusCode}-{resp.Message} Message: {resp.DataAsText}"; } break; case HTTPRequestStates.Error: text = "Request Finished with Error! " + ((req.Exception == null) ? "No Exception" : (req.Exception.Message + "\n" + req.Exception.StackTrace)); break; case HTTPRequestStates.Aborted: text = "OnRequestFinished - Aborted without request. EventSource's State: " + State; break; case HTTPRequestStates.ConnectionTimedOut: text = "Connection Timed Out!"; break; case HTTPRequestStates.TimedOut: text = "Processing the request Timed Out!"; break; } if (State < States.Closing) { if (!string.IsNullOrEmpty(text)) { CallOnError(text, "OnRequestFinished"); } if (flag) { Retry(); } else { SetClosed("OnRequestFinished"); } } else { SetClosed("OnRequestFinished"); } } } }
private void OnRequestFinished(HTTPRequest req, HTTPResponse resp) { if (this.State == States.Closed) { return; } if (this.State == States.Closing || req.State == HTTPRequestStates.Aborted) { SetClosed("OnRequestFinished"); return; } string reason = string.Empty; // In some cases retry is prohibited bool canRetry = true; switch (req.State) { // The server sent all the data it's wanted. case HTTPRequestStates.Processing: canRetry = !resp.HasHeader("content-length"); break; // The request finished without any problem. case HTTPRequestStates.Finished: // HTTP 200 OK responses that have a Content-Type specifying an unsupported type, or that have no Content-Type at all, must cause the user agent to fail the connection. if (resp.StatusCode == 200 && !resp.HasHeaderWithValue("content-type", "text/event-stream")) { reason = "No Content-Type header with value 'text/event-stream' present."; canRetry = false; } // HTTP 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, and 504 Gateway Timeout responses, and any network error that prevents the connection // from being established in the first place (e.g. DNS errors), must cause the user agent to asynchronously reestablish the connection. // Any other HTTP response code not listed here must cause the user agent to fail the connection. if (canRetry && resp.StatusCode != 500 && resp.StatusCode != 502 && resp.StatusCode != 503 && resp.StatusCode != 504) { canRetry = false; reason = string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}", resp.StatusCode, resp.Message, resp.DataAsText); } break; // The request finished with an unexpected error. The request's Exception property may contain more info about the error. case HTTPRequestStates.Error: reason = "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"); break; // The request aborted, initiated by the user. case HTTPRequestStates.Aborted: // If the state is Closing, then it's a normal behaviour, and we close the EventSource reason = "OnRequestFinished - Aborted without request. EventSource's State: " + this.State; break; // Connecting to the server is timed out. case HTTPRequestStates.ConnectionTimedOut: reason = "Connection Timed Out!"; break; // The request didn't finished in the given time. case HTTPRequestStates.TimedOut: reason = "Processing the request Timed Out!"; break; } // If we are not closing the EventSource, then we will try to reconnect. if (this.State < States.Closing) { if (!string.IsNullOrEmpty(reason)) { CallOnError(reason, "OnRequestFinished"); } if (canRetry) { Retry(); } else { SetClosed("OnRequestFinished"); } } else { SetClosed("OnRequestFinished"); } }
private void OnInternalRequestUpgraded(HTTPRequest req, HTTPResponse resp) { HTTPManager.Logger.Information("WebSocket", "Internal request upgraded!", this.Context); webSocket = resp as WebSocketResponse; if (webSocket == null) { if (OnError != null) { string reason = string.Empty; if (req.Exception != null) { reason = req.Exception.Message + " " + req.Exception.StackTrace; } OnError(this, reason); } this.State = WebSocketStates.Closed; return; } // If Close called while we connected if (this.State == WebSocketStates.Closed) { webSocket.CloseStream(); return; } if (!resp.HasHeader("sec-websocket-accept")) { this.State = WebSocketStates.Closed; webSocket.CloseStream(); if (OnError != null) { OnError(this, "No Sec-Websocket-Accept header is sent by the server!"); } return; } webSocket.WebSocket = this; if (this.Extensions != null) { for (int i = 0; i < this.Extensions.Length; ++i) { var ext = this.Extensions[i]; try { if (ext != null && !ext.ParseNegotiation(webSocket)) { this.Extensions[i] = null; // Keep extensions only that successfully negotiated } } catch (Exception ex) { HTTPManager.Logger.Exception("WebSocket", "ParseNegotiation", ex, this.Context); // Do not try to use a defective extension in the future this.Extensions[i] = null; } } } this.State = WebSocketStates.Open; if (OnOpen != null) { try { OnOpen(this); } catch (Exception ex) { HTTPManager.Logger.Exception("WebSocket", "OnOpen", ex, this.Context); } } webSocket.OnText = (ws, msg) => { if (OnMessage != null) { OnMessage(this, msg); } }; webSocket.OnBinary = (ws, bin) => { if (OnBinary != null) { OnBinary(this, bin); } }; webSocket.OnClosed = (ws, code, msg) => { this.State = WebSocketStates.Closed; if (OnClosed != null) { OnClosed(this, code, msg); } }; if (OnIncompleteFrame != null) { webSocket.OnIncompleteFrame = (ws, frame) => { if (OnIncompleteFrame != null) { OnIncompleteFrame(this, frame); } } } ; if (StartPingThread) { webSocket.StartPinging(Math.Max(PingFrequency, 100)); } webSocket.StartReceive(); }
private void OnRequestFinished(HTTPRequest req, HTTPResponse resp) { if (this.State == States.Closed) return; if (this.State == States.Closing) { SetClosed("OnRequestFinished"); return; } string reason = string.Empty; // In some cases retry is prohibited bool canRetry = true; switch (req.State) { // The server sent all the data it's wanted. case HTTPRequestStates.Processing: canRetry = !resp.HasHeader("content-length"); break; // The request finished without any problem. case HTTPRequestStates.Finished: // HTTP 200 OK responses that have a Content-Type specifying an unsupported type, or that have no Content-Type at all, must cause the user agent to fail the connection. if (resp.StatusCode == 200 && !resp.HasHeaderWithValue("content-type", "text/event-stream")) { reason = "No Content-Type header with value 'text/event-stream' present."; canRetry = false; } // HTTP 500 Internal Server Error, 502 Bad Gateway, 503 Service Unavailable, and 504 Gateway Timeout responses, and any network error that prevents the connection // from being established in the first place (e.g. DNS errors), must cause the user agent to asynchronously reestablish the connection. // Any other HTTP response code not listed here must cause the user agent to fail the connection. if (canRetry && resp.StatusCode != 500 && resp.StatusCode != 502 && resp.StatusCode != 503 && resp.StatusCode != 504) { canRetry = false; reason = string.Format("Request Finished Successfully, but the server sent an error. Status Code: {0}-{1} Message: {2}", resp.StatusCode, resp.Message, resp.DataAsText); } break; // The request finished with an unexpected error. The request's Exception property may contain more info about the error. case HTTPRequestStates.Error: reason = "Request Finished with Error! " + (req.Exception != null ? (req.Exception.Message + "\n" + req.Exception.StackTrace) : "No Exception"); break; // The request aborted, initiated by the user. case HTTPRequestStates.Aborted: // If the state is Closing, then it's a normal behaviour, and we close the EventSource reason = "OnRequestFinished - Aborted without request. EventSource's State: " + this.State; break; // Ceonnecting to the server is timed out. case HTTPRequestStates.ConnectionTimedOut: reason = "Connection Timed Out!"; break; // The request didn't finished in the given time. case HTTPRequestStates.TimedOut: reason = "Processing the request Timed Out!"; break; } // If we are not closing the EventSource, then we will try to reconnect. if (this.State < States.Closing) { if (!string.IsNullOrEmpty(reason)) CallOnError(reason, "OnRequestFinished"); if (canRetry) Retry(); else SetClosed("OnRequestFinished"); } else SetClosed("OnRequestFinished"); }