public void DoYourJob(Session oS, JwtAuthenticator auth, JwtRestClient client) { // ref1. https://stackoverflow.com/questions/29413942/c-sharp-anonymous-object-with-properties-from-dictionary/29428640#29428640 // see, `ref1` to dictionary to anonymous object. var uri = new Uri(oS.fullUrl); var c_url = string.Format("{0}_{1}{2}", uri.Scheme.ToLower(), uri.Host.ToLower(), uri.AbsolutePath.Replace("/", "").ToLower()); var tmp_param = new List <string>(); bool has_body = oS.requestBodyBytes.Length > 0 ? true : false; var body_param = new Dictionary <string, string>(); var url_param = new Dictionary <string, string>(); // Json Request 파싱을 위해 데이터 타입을 체크 필요 // MimeType Filter 필요, Content-Type: application/json if (oS.oRequest.headers["Content-Type"].Contains("application/json")) { try { var query1 = JsonConvert.DeserializeObject <Dictionary <string, string> >(oS.GetRequestBodyAsString()); foreach (var kv in query1) { FiddleFiddleLogger.FiddleLog( string.Format("JsonConvert Result {0}", kv.Key.ToLower()) ); if (!body_param.ContainsKey(kv.Key.ToLower())) { body_param.Add( kv.Key.ToLower(), Convert.ToBase64String( Encoding.ASCII.GetBytes( kv.Value ) // convert UTF8 string to bytes array // 2018.04.11, ASCII 인코딩으로 전환 뒤 이를 Base64 로 변환하는 것이 유리한 전략이며 // 데이터를 인코딩 혹은 디코딩하기에 유리하다. ) // convert bytes array to base64 string, that is base64-Encoding ); // Add Key-Value Pair to Dictionary } if (!tmp_param.Contains(kv.Key.ToLower())) { tmp_param.Add(kv.Key.ToLower()); } } }catch (Exception e) { FiddleFiddleLogger.FiddleLog( string.Format("[CERT] While Json Converting, {0}", e.Message) ); FiddleFiddleLogger.FiddleLog( // 인덱싱 실수를 하지 않기 위해 인덱스 번호를 마킹하는 것을 좋은 습관이다. string.Format("Continuation >> {0} {1} {2} {3}", oS.hostname, // 0 oS.port, // 1 oS.responseCode, // 2 oS.url // 3 ) ); } // json_body_param = new Dictionary(json_body_param.Intersect(query1)); } else if (oS.RequestMethod.ToLower() == "post" || oS.oRequest.headers["Content-Type"].Contains("application/x-www-form-urlencoded")) {// POST Parameter 추출 try { var body = HttpUtility.ParseQueryString(oS.GetRequestBodyAsString()); // 디코딩 오류를 극복하기 위한 전략이 필요하다. var query2 = body != null ? body:null; // query2 = HttpUtility.ParseQueryString(oS.GetRequestBodyAsString(oS.GetRequestBodyEncoding().GetDecoder()); // oS.GetRequestBodyEncoding().GetString(ref oS.requestBodyBytes, oS.requestBodyBytes.Length); // 디코딩 전략, 디코딩에 실패하는 데이터는 버린다. // 굳이 Decoding 을 여기서 할 필요가 없다. Base64 Encoding 후에 Viewer 에서 처리하도록 지연시킨다. // 아래의 링크를 참조바란다. // Eric Lawrence, https://www.telerik.com/forums/request-body-encoding if (query2 != null) { foreach (var item in query2) { tmp_param.Add(item.ToString().ToLower()); body_param.Add( item.ToString(), Convert.ToBase64String( Encoding.UTF8.GetBytes( query2[item.ToString()] ) // convert UTF8 string to bytes array ) // convert bytes array to base64 string, that is base64-Encoding ); // Add Parameter Key and Value to Dictionary } } } catch (Exception e) { FiddleFiddleLogger.FiddleLog( string.Format("[CERT] While POST Parmeter Converting, {0}", e.Message) ); FiddleFiddleLogger.FiddleLog( // 인덱싱 실수를 하지 않기 위해 인덱스 번호를 마킹하는 것을 좋은 습관이다. string.Format("Continuation >> {0} {1} {2} {3}", oS.hostname, // 0 oS.port, // 1 oS.responseCode, // 2 oS.url // 3 ) ); } } // GET Paramter 추출 var query3 = HttpUtility.ParseQueryString(uri.Query); foreach (var item in query3) { tmp_param.Add(item.ToString().ToLower()); // query3[item.ToString()]; url_param.Add( item.ToString(), Convert.ToBase64String( Encoding.UTF8.GetBytes( query3[item.ToString()] ) // convert UTF8 string to bytes array ) // convert bytes array to base64 string, that is base64-Encoding); ); } // 정렬 var ordered_param = tmp_param.OrderBy(x => x); string source = string.Join("|", ordered_param); string hash = ""; using (MD5 md5Hash = MD5.Create()) { hash = GetMd5Hash(md5Hash, source); } // String expires_in = HttpUtility.ParseQueryString(uri.Query) var req_head = new Dictionary <string, string>(); foreach (var item in oS.RequestHeaders) { req_head.Add(item.Name, item.Value); } var res_head = new Dictionary <string, string>(); // Dictionary 변환에 어려움이 있음, 해결이 필요하다. /// TODO: Dictionary 변환 작업 필요 Set-Cookie 의 경우 동일한 키 이름에 중복된 값이 존재 foreach (var item in oS.ResponseHeaders) { if (res_head.ContainsKey(item.Name)) { res_head[item.Name] = String.Join("|", res_head[item.Name], item.Value); } else { res_head[item.Name] = item.Value; } } var res = client.Insert(new { req_header = req_head, method = oS.RequestMethod, full_url = oS.fullUrl, url = oS.RequestHeaders.RequestPath, hostname = oS.hostname, url_param = url_param, body_param = body_param, client_ip = oS.clientIP, client_port = oS.clientPort, server_ip = oS.m_hostIP, server_port = oS.port, client_process = oS.LocalProcess, res_header = res_head, is_https = oS.isHTTPS, has_body = has_body, url_key = c_url, param_hash_key = hash, param_key = source }, auth); if (res.StatusCode != System.Net.HttpStatusCode.Created) { FiddleFiddleLogger.FiddleLog( res.Content + res.StatusCode.ToString() ); } }
/// <summary> /// Rules: /// 1. All of the Parameter's name is lower-case. /// 2. All of the Parameter's value is base64-encoded ascii-bytes-stream /// </summary> /// <param name="oS"></param> /// <param name="auth"></param> /// <param name="client"></param> public void SendRestRequest(Session oS, JwtAuthenticator auth, JwtRestClient client) { Uri uri = new Uri(oS.fullUrl); string urlKey = string.Format( "{0}_{1}{2}", uri.Scheme.ToLower(), // #0 uri.Host.ToLower(), // #1 uri.AbsolutePath.Replace("/", "").ToLower() // #2 ); // sample: https_www.yes24.comtemplatesftlogin.aspx List <string> paramKeyList = new List <string>(); paramKeyList.Add(urlKey); bool HasBody = oS.requestBodyBytes.Length > 0 ? true : false; // Check whether or not there is body part. Dictionary <string, string> bodyParam = new Dictionary <string, string>(); Dictionary <string, string> uriParam = new Dictionary <string, string>(); string paramMd5PHashKey = null; Dictionary <string, string> requestDicHeader = new Dictionary <string, string>(); Dictionary <string, string> responseDicHeader = new Dictionary <string, string>(); string requestBody = oS.GetRequestBodyAsString(); // Parse Body Part if (oS.oRequest.headers.Exists("Content-Type")) { if (oS.oRequest.headers["Content-Type"].Contains("application/json")) { try { var ConvertedBody = JsonConvert.DeserializeObject <Dictionary <string, string> >(requestBody); foreach (var kv in ConvertedBody) { var originKey = kv.Key.ToString(); var lowerKey = kv.Key.ToLower(); var encodedVal = Convert.ToBase64String(Encoding.ASCII.GetBytes(kv.Value)); // Plain -> ASCII-Bytes -> Base64-Encoding // Key Dup Check if (!bodyParam.ContainsKey(originKey)) { bodyParam.Add(originKey, encodedVal); } if (!paramKeyList.Contains(lowerKey)) { paramKeyList.Add(lowerKey); } } } catch { /* TODO : Error Reporting Function */ } } else if (oS.oRequest.headers["Content-Type"].Contains("application/x-www-form-urlencoded")) { var queryString = HttpUtility.ParseQueryString(requestBody); if (queryString != null) { foreach (var key in queryString.AllKeys) { var originKey = key; var lowerKey = key.ToLower(); var encodedVal = Convert.ToBase64String(Encoding.ASCII.GetBytes(queryString.Get(originKey))); if (!paramKeyList.Contains(lowerKey)) { paramKeyList.Add(lowerKey); } if (!bodyParam.ContainsKey(originKey)) { bodyParam.Add(originKey, encodedVal); } } } } } //Parse Url Part var uriQueryString = HttpUtility.ParseQueryString(uri.Query); if (uriQueryString != null) { foreach (var key in uriQueryString.AllKeys) { var originKey = key; string lowerKey = key.ToLower(); string encodedVal = null; try { encodedVal = Convert.ToBase64String(Encoding.ASCII.GetBytes(uriQueryString.Get(key.ToString()))); }catch { /* TODO: Error Reporting Function */ } if (!paramKeyList.Contains(lowerKey)) { paramKeyList.Add(lowerKey); } if (!uriParam.ContainsKey(originKey)) { uriParam.Add(originKey, encodedVal); } } } // Sorting & Calculate MD5 Hash var orderedParamKeyList = paramKeyList.OrderBy(x => x); string strOrderedParamKeyList = string.Join("|", orderedParamKeyList.ToArray <string>()); using (MD5 md5Hash = MD5.Create()) { paramMd5PHashKey = GetMd5Hash(md5Hash, strOrderedParamKeyList); } foreach (var header in oS.RequestHeaders) { if (!requestDicHeader.ContainsKey(header.Name)) { requestDicHeader.Add(header.Name, header.Value); } else { requestDicHeader[header.Name] = string.Join("|", requestDicHeader[header.Name], header.Value); } } foreach (var header in oS.ResponseHeaders) { if (!responseDicHeader.ContainsKey(header.Name)) { responseDicHeader.Add(header.Name, header.Value); } else { responseDicHeader[header.Name] = string.Join("|", responseDicHeader[header.Name], header.Value); } } try { var InsertResult = client.Insert(new { // Basic Information method = oS.RequestMethod, full_url = oS.fullUrl, url = oS.RequestHeaders.RequestPath, // Parsed Information req_header = requestDicHeader, res_code = oS.responseCode, res_header = responseDicHeader, url_param = uriParam, body_param = bodyParam, // Client-Side Information client_ip = oS.clientIP, client_port = oS.clientPort, client_process = oS.LocalProcess, // Server-Side Information server_ip = oS.m_hostIP, server_port = oS.port, hostname = oS.hostname, // Additionarl Information is_https = oS.isHTTPS, has_body = HasBody, // Redundant Check Information url_key = urlKey, param_hash_key = paramMd5PHashKey, param_key = strOrderedParamKeyList }, auth); if (InsertResult.StatusCode != System.Net.HttpStatusCode.Created) { // Fail to create new Record FiddleFiddleLogger.FiddleLog(string.Format(" #error '{2}' >> '{0}' >>> \n _START\n {1} \n_END\n", InsertResult.Content, InsertResult.StatusCode.ToString(), oS.fullUrl)); } else { // Success to create new Record } } catch { /* TODO: Error Reporting Function */ } }