kema

HttpRequest

Oct 18th, 2017
142
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.26 KB | None | 0 0
  1. namespace MyCoolWebServer.Server.Http
  2. {
  3.     using Common;
  4.     using Contracts;
  5.     using Enums;
  6.     using Exceptions;
  7.     using System;
  8.     using System.Collections.Generic;
  9.     using System.Linq;
  10.     using System.Net;
  11.  
  12.     public class HttpRequest : IHttpRequest
  13.     {
  14.         private readonly string requestText;
  15.  
  16.         public HttpRequest(string requestText)
  17.         {
  18.             CoreValidator.ThrowIfNullOrEmpty(requestText, nameof(requestText));
  19.  
  20.             this.requestText = requestText;
  21.  
  22.             this.FormData = new Dictionary<string, string>();
  23.             this.QueryParameters = new Dictionary<string, string>();
  24.             this.UrlParameters = new Dictionary<string, string>();
  25.             this.Headers = new HttpHeaderCollection();
  26.             this.Cookies = new HttpCookieCollection();
  27.  
  28.             this.ParseRequest(requestText);
  29.         }
  30.  
  31.         public IDictionary<string, string> FormData { get; private set; }
  32.  
  33.         public IHttpHeaderCollection Headers { get; private set; }
  34.  
  35.         public IHttpCookieCollection Cookies { get; private set; }
  36.  
  37.         public string Path { get; private set; }
  38.  
  39.         public IDictionary<string, string> QueryParameters { get; private set; }
  40.  
  41.         public HttpRequestMethod Method { get; private set; }
  42.  
  43.         public string Url { get; private set; }
  44.  
  45.         public IDictionary<string, string> UrlParameters { get; private set; }
  46.  
  47.         public IHttpSession Session { get; set; }
  48.  
  49.         public void AddUrlParameter(string key, string value)
  50.         {
  51.             CoreValidator.ThrowIfNullOrEmpty(key, nameof(key));
  52.             CoreValidator.ThrowIfNullOrEmpty(value, nameof(value));
  53.  
  54.             this.UrlParameters[key] = value;
  55.         }
  56.  
  57.         private void ParseRequest(string requestText)
  58.         {
  59.             var requestLines = requestText.Split(Environment.NewLine);
  60.  
  61.             if (!requestLines.Any())
  62.             {
  63.                 BadRequestException.ThrowFromInvalidRequest();
  64.             }
  65.  
  66.             var requestLine = requestLines.First().Split(
  67.                 new[] { ' ' },
  68.                 StringSplitOptions.RemoveEmptyEntries);
  69.  
  70.             if (requestLine.Length != 3 || requestLine[2].ToLower() != "http/1.1")
  71.             {
  72.                 BadRequestException.ThrowFromInvalidRequest();
  73.             }
  74.  
  75.             this.Method = this.ParseMethod(requestLine.First());
  76.             this.Url = requestLine[1];
  77.             this.Path = this.ParsePath(this.Url);
  78.  
  79.             this.ParseHeaders(requestLines);
  80.             this.ParseCookies();
  81.             this.ParseParameters();
  82.             this.ParseFormData(requestLines.Last());
  83.  
  84.             this.SetSession();
  85.         }
  86.  
  87.         private HttpRequestMethod ParseMethod(string method)
  88.         {
  89.             HttpRequestMethod parsedMethod;
  90.             if (!Enum.TryParse(method, true, out parsedMethod))
  91.             {
  92.                 BadRequestException.ThrowFromInvalidRequest();
  93.             }
  94.  
  95.             return parsedMethod;
  96.         }
  97.  
  98.         private string ParsePath(string url)
  99.             => url.Split(new[] { '?', '#' }, StringSplitOptions.RemoveEmptyEntries)[0];
  100.  
  101.         private void ParseHeaders(string[] requestLines)
  102.         {
  103.             var emptyLineAfterHeadersIndex = Array.IndexOf(requestLines, string.Empty);
  104.  
  105.             for (int i = 1; i < emptyLineAfterHeadersIndex; i++)
  106.             {
  107.                 var currentLine = requestLines[i];
  108.                 var headerParts = currentLine.Split(new[] { ": " }, StringSplitOptions.RemoveEmptyEntries);
  109.  
  110.                 if (headerParts.Length != 2)
  111.                 {
  112.                     BadRequestException.ThrowFromInvalidRequest();
  113.                 }
  114.  
  115.                 var headerKey = headerParts[0];
  116.                 var headerValue = headerParts[1].Trim();
  117.  
  118.                 var header = new HttpHeader(headerKey, headerValue);
  119.  
  120.                 this.Headers.Add(header);
  121.             }
  122.  
  123.             if (!this.Headers.ContainsKey(HttpHeader.Host))
  124.             {
  125.                 BadRequestException.ThrowFromInvalidRequest();
  126.             }
  127.         }
  128.        
  129.         private void ParseCookies()
  130.         {
  131.             if (this.Headers.ContainsKey(HttpHeader.Cookie))
  132.             {
  133.                 var allCookies = this.Headers.Get(HttpHeader.Cookie);
  134.                
  135.                 foreach (var cookie in allCookies)
  136.                 {
  137.                     if (!cookie.Value.Contains('='))
  138.                     {
  139.                         return;
  140.                     }
  141.  
  142.                     var cookieParts = cookie
  143.                         .Value
  144.                         .Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
  145.                         .ToList();
  146.                    
  147.                     if (!cookieParts.Any())
  148.                     {
  149.                         continue;
  150.                     }
  151.  
  152.                     foreach (var cookiePart in cookieParts)
  153.                     {
  154.                         var cookieKeyValuePair = cookiePart
  155.                             .Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
  156.  
  157.                         if (cookieKeyValuePair.Length == 2)
  158.                         {
  159.                             var key = cookieKeyValuePair[0].Trim();
  160.                             var value = cookieKeyValuePair[1].Trim();
  161.  
  162.                             this.Cookies.Add(new HttpCookie(key, value, false));
  163.                         }
  164.                     }
  165.                 }
  166.             }
  167.         }
  168.  
  169.         private void ParseParameters()
  170.         {
  171.             if (!this.Url.Contains('?'))
  172.             {
  173.                 return;
  174.             }
  175.  
  176.             var query = this.Url
  177.                 .Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries)
  178.                 .Last();
  179.  
  180.             this.ParseQuery(query, this.UrlParameters);
  181.         }
  182.  
  183.         private void ParseFormData(string formDataLine)
  184.         {
  185.             if (this.Method == HttpRequestMethod.Get)
  186.             {
  187.                 return;
  188.             }
  189.  
  190.             this.ParseQuery(formDataLine, this.FormData);
  191.         }
  192.  
  193.         private void ParseQuery(string query, IDictionary<string, string> dict)
  194.         {
  195.             if (!query.Contains('='))
  196.             {
  197.                 return;
  198.             }
  199.  
  200.             var queryPairs = query.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
  201.  
  202.             foreach (var queryPair in queryPairs)
  203.             {
  204.                 var queryKvp = queryPair.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
  205.  
  206.                 if (queryKvp.Length != 2)
  207.                 {
  208.                     return;
  209.                 }
  210.  
  211.                 var queryKey = WebUtility.UrlDecode(queryKvp[0]);
  212.                 var queryValue = WebUtility.UrlDecode(queryKvp[1]);
  213.  
  214.                 dict.Add(queryKey, queryValue);
  215.             }
  216.         }
  217.        
  218.         private void SetSession()
  219.         {
  220.             if (this.Cookies.ContainsKey(SessionStore.SessionCookieKey))
  221.             {
  222.                 var cookie = this.Cookies.Get(SessionStore.SessionCookieKey);
  223.                 var sessionId = cookie.Value;
  224.                 this.Session = SessionStore.Get(sessionId);
  225.             }
  226.  
  227.         }
  228.  
  229.         public override string ToString() => this.requestText;
  230.     }
  231. }
Advertisement
Add Comment
Please, Sign In to add comment