private async Task ProcessClientAsync(TcpClient tcpClient) { try { using (NetworkStream stream = tcpClient.GetStream()) { //we set the position of the red data (offset) var position = 0; //This is assumed to be the standard size of a buffer - 4kb var buffer = new byte[HTTPConstants.BufferSize]; //TODO Check if there is faster way to proceed with array of bytes var data = new List <byte>(); while (true) { var count = await stream.ReadAsync(buffer, position, buffer.Length); position += count; //We want to remove the empty bytes when adding to the data - if the last buffer is less than 4096b, then take only the non-empty data. //We could use LINQ (data.AddRange(buffer.Take(count));) but will be slower... if (count < buffer.Length) { var lastPartialBuffer = new byte[count]; Array.Copy(buffer, lastPartialBuffer, count); data.AddRange(lastPartialBuffer); break; } else { data.AddRange(buffer); } } //Finally, byte[] => string(text) var requestAsString = Encoding.UTF8.GetString(data.ToArray()); //Console.WriteLine(requestAsString); var request = new HttpRequest(requestAsString); //Console.WriteLine($"{request.Method} {request.Path} => "); HttpResponse response; var route = this.routeTable.FirstOrDefault( x => string.Compare(x.Path, request.Path, true) == 0 && x.Method == request.Method); if (route != null) { response = route.Action(request); } else { // Not Found 404 response = new HttpResponse("text/html", new byte[0], Enums.HttpStatusCode.NotFound); } //We add this headers/cookies to each response response.Headers.Add(new Header("Server", "SUS Custom Server 1.69")); //Set-Cookie: Gosho's Cookie=fc0c3724-c519-4722-abd6-d39eb5522536; Path=/;Max-Age=2073600; HttpOnly; //response.Cookies.Add(new ResponseCookie("Gosho's Cookie", Guid.NewGuid().ToString()) { HttpOnly = "true", MaxAge = 60 * 24 * 24 * 60 }); //This is where we add every session cookie from request to the response var sessionCookie = request.Cookies.FirstOrDefault(x => x.Name == HTTPConstants.SessionCookieName); if (sessionCookie != null) { var responseSessionCookie = new ResponseCookie(sessionCookie.Name, sessionCookie.Value); responseSessionCookie.Path = "/"; response.Cookies.Add(responseSessionCookie); } //HttpResponse .ToString() is overriden var responseHeaderBytes = Encoding.UTF8.GetBytes(response.ToString()); await stream.WriteAsync(responseHeaderBytes, 0, responseHeaderBytes.Length); if (response.Body != null) { await stream.WriteAsync(response.Body, 0, response.Body.Length); } } //To make sure it's close after we finish working with the current client (we do not trust "using" :) ) tcpClient.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message + " **************** ERRRRRRRRRRRRRRRRROR"); //Console.WriteLine(ex.Message); //Console.WriteLine(ex.StackTrace); //Console.WriteLine(ex.Source); //Console.WriteLine(ex.InnerException); } }
private async Task ProcessClientAsync(TcpClient tcpClient) { try { using NetworkStream stream = tcpClient.GetStream(); var data = new List <byte>(); int position = 0; byte[] buffer = new byte[HttpConstants.BufferSize]; //chunk while (true) { int count = await stream.ReadAsync(buffer, position, buffer.Length); position += count; if (count < buffer.Length) { var partialBuffer = new byte[count]; Array.Copy(buffer, partialBuffer, count); data.AddRange(partialBuffer); break; } else { data.AddRange(buffer); } } // byte[] => string (text) var requestAsString = Encoding.UTF8.GetString(data.ToArray()); var request = new HttpRequest(requestAsString); Console.WriteLine($"{request.Method} {request.Path} => {request.Headers.Count} headers"); HttpResponse response; var route = this.routeTable.FirstOrDefault( x => string.Compare(x.Path, request.Path, true) == 0 && x.Method == request.Method); if (route != null) { response = route.Action(request); } else { //Not found response = new HttpResponse("text/html", new byte[0], HttpStatusCode.NotFound); } response.Headers.Add(new Header("Server", "SUS Server 1.0")); var sessionCookie = request.Cookies.FirstOrDefault(x => x.Name == HttpConstants.SessionCookieName); if (sessionCookie != null) { var responseSessionCookie = new ResponseCookie(sessionCookie.Name, sessionCookie.Value); responseSessionCookie.Path = "/"; response.Cookies.Add(responseSessionCookie); } var responseHeaderBytes = Encoding.UTF8.GetBytes(response.ToString()); await stream.WriteAsync(responseHeaderBytes, 0, responseHeaderBytes.Length); if (response.Body != null) { await stream.WriteAsync(response.Body, 0, response.Body.Length); } tcpClient.Close(); } catch (Exception ex) { Console.WriteLine(ex); } }
private async Task ProcessClientAsync(TcpClient tcpClient) { try { using (NetworkStream stream = tcpClient.GetStream()) { //TOOD: research if there is faster data structure List <byte> data = new List <byte>(); int position = 0; byte[] buffer = new byte[HttpConstants.BufferSize]; //also called chunk while (true) { int count = await stream.ReadAsync(buffer, position, buffer.Length); position = +count; if (count < buffer.Length) { var partialBuffer = new byte[count]; Array.Copy(buffer, partialBuffer, count); data.AddRange(partialBuffer); break; //no data left } else { data.AddRange(data); } } //Request //byte[] => string (text) var requestString = Encoding.UTF8.GetString(data.ToArray()); var request = new HttpRequest(requestString); //Console.WriteLine(requestString); Console.WriteLine($"{request.Method} {request.Path} => {request.Headers.Count} Headers"); //let's go to the route table now and connect the request with the response //Response HttpResponse response; //if (this.routeTable.ContainsKey(request.Path)) //{ // var action = this.routeTable[request.Path]; // response = action(request); //} //var route = this.routeTable.FirstOrDefault(x => x.Path == request.Path); //to ignore the casing i use string.Compare(): var route = this.routeTable.FirstOrDefault(x => string.Compare(x.Path, request.Path, ignoreCase: true) == 0 && x.Method == request.Method); if (route != null) { var action = route.Action; response = action(request); } else { //404 Not Found response = new HttpResponse("text/html", new byte[0], HttpStatusCode.NotFound); } response.Headers.Add(new Header("Server", "SUS Server 1.0")); //response.Cookies.Add(new ResponseCookie("sid", Guid.NewGuid().ToString()) { HttpOnly = true, MaxAge = 60 * 24 * 60 * 60 }); var sessionCookie = request.Cookies.FirstOrDefault(x => x.Name == HttpConstants.SessionCookieName); if (sessionCookie != null) { //pravq si response cookie, zashtoto ako e samo cookie, to shte mi se razmqta po edno novo session cookie //za vseki request, dori za js i css fajlovete, a towa ne mi e nujno!!! Trqbwa mi 1 session cookie za 1 user!!! var responseSessionCookie = new ResponseCookie(sessionCookie.Name, sessionCookie.Value); //responseSessionCookie.Path = "/"; //toj si mi defaultno takyv path-a za towa sessionCookie!!!! response.Cookies.Add(responseSessionCookie); //mestq tazi cookie ot requesta v responsa!!! } var responseHeaderBytes = Encoding.UTF8.GetBytes(response.ToString()); await stream.WriteAsync(responseHeaderBytes, 0, responseHeaderBytes.Length); if (response.Body != null) { await stream.WriteAsync(response.Body, 0, response.Body.Length); } } tcpClient.Close(); } catch (Exception e) { //throw e; Console.WriteLine(e); } }