// A sample HTTP request handler. S Manoharan.

using System;
using System.IO;
using System.Net;
using System.Text;

namespace W3Client
{
   public class RequestHandler
   {
      public RequestHandler(Uri uri, string httpVersion,
         string requestMethod, string requestHeaders, byte[] postData)
      {
         URI = uri;
         Version = httpVersion;
         RequestMethod = requestMethod;
         RequestHeaders = requestHeaders.Split(new char[] { '\r', '\n' },
            StringSplitOptions.RemoveEmptyEntries);
         RequestPayload = postData;
         ServicePointManager.Expect100Continue = true;
         ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
      } // RequestHandler

      public Uri URI
      {
         get;
         private set;
      } // URI

      public string Host
      {
         get;
         private set;
      } // Host

      public int Port
      {
         get;
         private set;
      } // Port

      public string Version
      {
         get;
         private set;
      } // Version

      public string Resource
      {
         get;
         private set;
      } // Resource

      public string RequestMethod
      {
         get;
         private set;
      } // RequestMethod

      public string[] RequestHeaders
      {
         get;
         private set;
      } // RequestHeaders

      public string Response
      {
         get;
         private set;
      } // Response

      public byte[] RequestPayload
      {
         get;
         private set;
      } // RequestPayload

      public byte[] ResponsePayload
      {
         get;
         private set;
      } // ResponsePayload

      public void DoRequest()
      {
         try
         {
            var req = (HttpWebRequest)WebRequest.Create(URI);
            req.ProtocolVersion = Version.Equals("HTTP/1.0") ? HttpVersion.Version10 : HttpVersion.Version11;
            foreach (string s in RequestHeaders)
            {
               string[] kvp = s.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
               string key = kvp.Length > 0 ? kvp[0].Trim() : null;
               string val = kvp.Length > 1 ? kvp[1].Trim() : null;
               if (!string.IsNullOrWhiteSpace(key) && !string.IsNullOrWhiteSpace(val))
               {
                  switch (key)
                  {
                     case "Host":
                        req.Host = val;
                        break;
                     case "Accept":
                        req.Accept = val;
                        break;
                     case "Content-Type":
                        req.ContentType = val;
                        break;
                     case "Connection":
                        break;
                     case "If-Modified-Since":
                        break;
                     default:
                        req.Headers.Add(key, val);
                        break;
                  }
               }
            }
            req.Method = RequestMethod;
            req.ContentLength = RequestPayload == null ? 0 : RequestPayload.Length;
            if (!req.Method.Equals("GET") && !req.Method.Equals("HEAD"))
            {
               using (Stream reqStream = req.GetRequestStream())
               {
                  reqStream.Write(RequestPayload, 0, RequestPayload.Length);
               }
            }
            HttpWebResponse response = (HttpWebResponse)req.GetResponse();

            StringBuilder sb = new StringBuilder();
            sb.Append((response.ProtocolVersion == HttpVersion.Version10) ? "HTTP/1.0" : "HTTP/1.1");
            sb.Append(string.Format(" {0} {1}\r\n", (int)response.StatusCode, response.StatusDescription));
            foreach (var key in response.Headers.AllKeys)
            {
               sb.Append(string.Format("{0}: {1}\r\n", key, response.Headers[key]));
            }
            sb.Append("\r\n"); // Separator line
            using (Stream s = response.GetResponseStream())
            {
               using (MemoryStream ms = new MemoryStream())
               {
                  s.CopyTo(ms);
                  ResponsePayload = ms.ToArray();
               }
            }
            Response = sb.ToString();
         }
         catch (WebException ex)
         {
            HttpWebResponse response = (HttpWebResponse)ex.Response;
            StringBuilder sb = new StringBuilder();
            sb.Append((response.ProtocolVersion == HttpVersion.Version10) ? "HTTP/1.0" : "HTTP/1.1");
            sb.Append(string.Format(" {0} {1}\r\n", (int)response.StatusCode, response.StatusDescription));
            foreach (var key in response.Headers.AllKeys)
            {
               sb.Append(string.Format("{0}: {1}\r\n", key, response.Headers[key]));
            }
            sb.Append("\r\n"); // Separator line
            Response = sb.ToString();
         }
      } // DoRequest

   } // class
} // namespace
