본문 바로가기

카테고리 없음

2022 연습 a-4

using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TEST
{
    class Param
    {
        public HttpListenerContext ctx { get; set; }

        public string url;
        public string method;
        public string query;
        public string header;
    }

    class Program
    {
        static Dictionary<string, string> dic;
        static Dictionary<string, JObject> reqID;

        //static async Task Main(string[] args)
        static void Main(string[] args)
        {
            string jInput;
            if (args.Length > 0)
                jInput = args[0];
            else
                jInput = ".\\Proxy.jon"; //// //args[0];
            Console.WriteLine(jInput);

            string jFile = ReadFile(jInput);
            JObject json = JObject.Parse(jFile);
            int port = (int)json["port"];
            JArray routes = (JArray)json["routes"];
            Console.WriteLine("port " + port.ToString());
            dic = new Dictionary<string, string>();
            reqID = new Dictionary<string, JObject>();
            // HttpListener 객체를 생성하고, 웹 서버 주소를 설정합니다.
            HttpListener listener = new HttpListener();

            foreach (JObject jobj in routes)
            {
                Console.WriteLine("- " + jobj["pathPrefix"]);
                Console.WriteLine("- " + jobj["url"]);
                dic.Add((string)jobj["pathPrefix"], (string)jobj["url"]);
                string temp = "http://127.0.0.1:" + port.ToString() + jobj["pathPrefix"] + "/";
                Console.WriteLine(temp);
                listener.Prefixes.Add(temp);
                string trace = "http://127.0.0.1:" + port.ToString() + "/trace/";
                listener.Prefixes.Add(trace);
            }

            try
            {
                // 웹 서버를 시작합니다.
                listener.Start();
                Console.WriteLine("웹 서버가 시작되었습니다.");

                while (true)
                {
                    // 클라이언트 요청을 받아들입니다.
                    HttpListenerContext ctx = listener.GetContext();

                    string uri = ctx.Request.Url.ToString();
                    string url = ctx.Request.RawUrl.ToString();
                    string path = ctx.Request.RawUrl.ToString();
                    string query = "";
                    string urlKey = "";

                    Console.WriteLine("uri " + uri);
                    Console.WriteLine("url " + url);
                    Console.WriteLine("path " + path);

                    if (path.Contains("?"))
                    {
                        urlKey = path.Split('?')[0];
                        query = path.Split('?')[1];
                    }
                    else
                        urlKey = path;

                    if (urlKey.Split('/').Length > 2)
                        urlKey = "/" + urlKey.Split('/')[1];

                    string method = ctx.Request.HttpMethod;

                   
                    Console.WriteLine("query " + query);

                    if(dic.ContainsKey(urlKey))
                        Console.WriteLine("dic[urlKey] " + dic[urlKey]);
                    Console.WriteLine("target " + uri);
                    AppendLogToFile("log.txt", "target " + uri);

                    /*if (uri.Contains("http://127.0.0.1:5020/aut"))
                    {
                        Console.WriteLine("uri " + uri);
                    }*/
                    Param param = new Param();
                    param.ctx = ctx;
                    if (dic.ContainsKey(urlKey))
                        param.url = dic[urlKey] + url;
                    else
                        param.url = url;
                    param.method = method;
                    param.query = query;
                    //param.header = ctx.Request.Headers.Get("x-requestId");

                    int count = ctx.Request.Headers.AllKeys.Length;
                    for(int i=0; i<count; i++)
                    {
                        Console.WriteLine("Header Key:"+ctx.Request.Headers.Keys.Get(i));
                    }
                       

                    JObject obj = new JObject(
                            new JProperty("target", param.url),
                            new JProperty("status", "200")
                            );
                    
                    //reqID.Add(param.header, param.url);

                    Thread myThread = new Thread(requURL);
                    myThread.Start(param);
                    //await requestURL(param);
                    //Task.Run(() => requestURL(param)).Wait();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("웹 서버 오류: " + ex.Message);
            }
            finally
            {
                // 웹 서버를 종료합니다.
                listener.Stop();
                Console.WriteLine("웹 서버가 종료되었습니다.");
            }
        }

        static void requURL(object _param)
        {
            Param param = (Param)_param;
            HttpListenerContext ctx = param.ctx;

            Task.Run(() => requestURL(param)).Wait();
        }
        static async Task requestURL(Param _param)
        {
            Param param = (Param)_param;
            HttpListenerContext ctx = param.ctx;

            try
            {
                string responseString = "";
                HttpClient httpClient = new HttpClient();
                string res = string.Empty;
                HttpStatusCode statusCode = HttpStatusCode.OK;
                httpClient.DefaultRequestHeaders.Add("x-requestId", param.header);
                if (param.method == "GET")
                {
                    string sendUrl = param.url+param.header;
                    if (param.query != "")
                    {
                        //sendUrl += "?" + param.query;
                    }
                    Console.WriteLine("service :" + sendUrl);
                    AppendLogToFile("log.txt", "service " + sendUrl);
                    HttpResponseMessage resp = await httpClient.GetAsync(sendUrl);
                    statusCode = resp.StatusCode;

                    responseString = await resp.Content.ReadAsStringAsync();
                    //Console.WriteLine("responseString " + );
                    //resp.Headers.TryGetValues(, out var headerValues);  
                }
                else
                {
                    HttpContent httpContent = new StringContent("", Encoding.UTF8, "application/json");
                    string sendUrl = param.url + param.header;
                    Console.WriteLine("service :" + sendUrl);
                    AppendLogToFile("log.txt", "service " + sendUrl);
                    HttpResponseMessage resp = await httpClient.PostAsync(sendUrl, httpContent);
                    resp.EnsureSuccessStatusCode(); // 성공적인 응답인지 확인
                    statusCode = resp.StatusCode;
                    responseString = await resp.Content.ReadAsStringAsync();
                    //resp.Headers.TryGetValues("x-requestId", out var headerValues);
                    /*if (response.Headers.TryGetValues(headerName, out var headerValues))
                    {
                        foreach (var value in headerValues)
                        {
                            Console.WriteLine($"{headerName}: {value}");
                        }
                    }
                    else
                    {
                        Console.WriteLine($"Header '{headerName}' not found in the response");
                    }*/
                }

                byte[] responseBytes = Encoding.UTF8.GetBytes(responseString);

                // 응답 헤더를 설정합니다.
                HttpListenerResponse response = ctx.Response;
                response.StatusCode = (int)statusCode;
                //response.ContentType = client.Headers["Content-Type"];
                response.ContentLength64 = responseBytes.Length;
                response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
                response.OutputStream.Close();
            }

            catch (WebException ex)
            {
                HttpWebResponse resp = (HttpWebResponse)ex.Response;
                ctx.Response.StatusCode = (int)resp.StatusCode;
                ctx.Response.OutputStream.Close();
            }
        }

        static async Task SendPostRequest(string url, string requestBody)
        {
            using (HttpClient httpClient = new HttpClient())
            {
                HttpContent httpContent = new StringContent(requestBody, Encoding.UTF8, "application/json");

                HttpResponseMessage response = await httpClient.PostAsync(url, httpContent);
                response.EnsureSuccessStatusCode(); // 성공적인 응답인지 확인

                Console.WriteLine("POST request sent successfully");
            }
        }

        static void reqURL(object _param)
        {
            Param param = (Param)_param;
            HttpListenerContext ctx = param.ctx;

            try
            {
                string responseString = "";
                WebClient client = new WebClient();
                string res = string.Empty;
                if (param.method == "GET")
                {
                    string sendUrl = param.url;
                    if (param.query != "") sendUrl += "?" + param.query;
                    Console.WriteLine("sendUrl :" + sendUrl);
                    responseString = client.DownloadString(sendUrl);
                    Console.WriteLine("responseString " + responseString);
                }
                else
                {
                    client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
                    responseString = client.UploadString(param.url, "");
                }


                // 클라이언트에게 응답을 보낼 데이터를 생성합니다.
                HttpStatusCode statusCode = HttpStatusCode.OK; // 기본적으로 성공으로 가정
                if (client.ResponseHeaders is WebHeaderCollection headers && headers.Count > 0)
                {
                    // 응답 헤더에서 StatusCode 추출
                    if (Enum.TryParse(headers.Get(0), out HttpStatusCode parsedStatusCode))
                    {
                        statusCode = parsedStatusCode;
                    }
                }

                byte[] responseBytes = Encoding.UTF8.GetBytes(responseString);

                // 응답 헤더를 설정합니다.
                HttpListenerResponse response = ctx.Response;
                response.StatusCode = (int)statusCode;
                response.ContentType = client.Headers["Content-Type"];
                response.ContentLength64 = responseBytes.Length;
                response.OutputStream.Write(responseBytes, 0, responseBytes.Length);
                response.OutputStream.Close();
            }

            catch (WebException ex)
            {
                HttpWebResponse resp = (HttpWebResponse)ex.Response;
                ctx.Response.StatusCode = (int)resp.StatusCode;
                ctx.Response.OutputStream.Close();
            }
        }

        static string ReadFile(string filePath)
        {
            try
            {
                // 파일을 읽기 위해 StreamReader를 사용합니다.
                using (StreamReader reader = new StreamReader(filePath))
                {
                    // 파일의 모든 내용을 문자열로 읽어옵니다.
                    string content = reader.ReadToEnd();
                    return content;
                }
            }
            catch (FileNotFoundException)
            {
                Console.WriteLine("파일을 찾을 수 없습니다.");
            }
            catch (Exception ex)
            {
                Console.WriteLine("파일 읽기 오류: " + ex.Message);
            }

            return null;
        }

        public static void AppendLogToFile(string logFilePath, string logMessage)
        {
            try
            {
                // 기존 파일이 존재하면 Append 모드로 열기
                using (StreamWriter writer = new StreamWriter(logFilePath, true))
                {
                    // 로그 메시지를 파일에 추가
                    writer.WriteLine(logMessage);
                }

                Console.WriteLine("로그가 파일에 추가되었습니다.");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"로그 파일에 추가하는 중에 오류가 발생했습니다: {ex.Message}");
            }
        }
    }
}
반응형