1: using System;
2: using System.IO;
3: using System.Net;
4: using System.Text;
5: using System.Threading.Tasks;
6: using System.Net.Http;
7: using System.Net.Http.Headers;
8: using System.Net.Http.Json;
9: using Newtonsoft.Json;
10:
11: namespace Ia.Cl.Model
12: {
13: ////////////////////////////////////////////////////////////////////////////
14:
15: /// <summary publish="true">
16: /// Contains functions that relate to posting and receiving data from remote Internet/Intranet pages
17: /// </summary>
18: /// <remarks>
19: /// Copyright � 2001-2020 Jasem Y. Al-Shamlan (info@ia.com.kw), Integrated Applications - Kuwait. All Rights Reserved.
20: ///
21: /// This library is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
22: /// the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
23: ///
24: /// This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
25: /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
26: ///
27: /// You should have received a copy of the GNU General Public License along with this library. If not, see http://www.gnu.org/licenses.
28: ///
29: /// Copyright notice: This notice may not be removed or altered from any source distribution.
30: /// </remarks>
31: public class Http
32: {
33: ////////////////////////////////////////////////////////////////////////////
34:
35: /// <summary>
36: ///
37: /// </summary>
38: private static bool range = false;
39:
40: ////////////////////////////////////////////////////////////////////////////
41:
42: /// <summary>
43: ///
44: /// </summary>
45: public Http() { }
46:
47: // Note that "https://" and "http://" are different. Wrong protocol could produce a "(403) Forbidden" response.
48:
49: // Include custom cookies, start and end points, and posting of data to remove server.
50:
51: // See https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/calling-a-web-api-from-a-net-client
52:
53: // Remember to "synch all the way"
54:
55: ////////////////////////////////////////////////////////////////////////////
56:
57: /// <summary>
58: ///
59: /// </summary>
60: public static async Task<string> PostAsync<T>(string baseAddress, string serviceUrl, T t)
61: {
62: HttpResponseMessage httpResponseMessage;
63: var s = string.Empty;
64:
65: serviceUrl = SuffixUrlWithSlashIfItContainsDot(serviceUrl);
66:
67: using (var httpClient = new HttpClient())
68: {
69: httpClient.BaseAddress = new Uri(baseAddress);
70: httpClient.DefaultRequestHeaders.Accept.Clear();
71: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
72:
73: HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(t), Encoding.UTF8, "application/json");
74:
75: httpResponseMessage = await httpClient.PostAsJsonAsync(serviceUrl, httpContent);
76: // e.g. httpResponseMessage = await httpClient.PostAsJsonAsync("api/products", product);
77:
78: httpResponseMessage.EnsureSuccessStatusCode();
79:
80: s = await httpResponseMessage.Content.ReadAsStringAsync();
81: }
82:
83: return s;
84: }
85:
86: ////////////////////////////////////////////////////////////////////////////
87:
88: /// <summary>
89: ///
90: /// </summary>
91: public static async Task<string> PostAsync(string baseAddress, string serviceUrl)
92: {
93: HttpResponseMessage httpResponseMessage;
94: var s = string.Empty;
95:
96: serviceUrl = SuffixUrlWithSlashIfItContainsDot(serviceUrl);
97:
98: using (var httpClient = new HttpClient())
99: {
100: httpClient.BaseAddress = new Uri(baseAddress);
101: httpClient.DefaultRequestHeaders.Accept.Clear();
102: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
103:
104: HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(string.Empty), Encoding.UTF8, "application/json"); // dummy
105:
106: httpResponseMessage = await httpClient.PostAsJsonAsync(serviceUrl, httpContent);
107: // e.g. httpResponseMessage = await httpClient.PostAsJsonAsync("api/products", product);
108:
109: httpResponseMessage.EnsureSuccessStatusCode();
110:
111: s = await httpResponseMessage.Content.ReadAsStringAsync();
112: }
113:
114: return s;
115: }
116:
117: ////////////////////////////////////////////////////////////////////////////
118:
119: /// <summary>
120: ///
121: /// </summary>
122: public static async Task<T> GetAsync<T>(string baseAddress, string serviceUrl)
123: {
124: HttpResponseMessage httpResponseMessage;
125: T t;
126:
127: t = default;
128:
129: serviceUrl = SuffixUrlWithSlashIfItContainsDot(serviceUrl);
130:
131: using (var httpClient = new HttpClient())
132: {
133: httpClient.BaseAddress = new Uri(baseAddress);
134: httpClient.DefaultRequestHeaders.Accept.Clear();
135: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
136:
137: httpResponseMessage = await httpClient.GetAsync(serviceUrl);
138:
139: if (httpResponseMessage.IsSuccessStatusCode)
140: {
141: t = await httpResponseMessage.Content.ReadAsAsync<T>();
142: }
143: else
144: {
145:
146: }
147: }
148:
149: return t;
150: }
151:
152: ////////////////////////////////////////////////////////////////////////////
153:
154: /// <summary>
155: ///
156: /// </summary>
157: public static async Task<string> GetAsync(string baseAddress, string serviceUrl)
158: {
159: HttpResponseMessage httpResponseMessage;
160: var s = string.Empty;
161:
162: serviceUrl = SuffixUrlWithSlashIfItContainsDot(serviceUrl);
163:
164: using (var httpClient = new HttpClient())
165: {
166: httpClient.BaseAddress = new Uri(baseAddress);
167: httpClient.DefaultRequestHeaders.Accept.Clear();
168: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
169:
170: httpResponseMessage = await httpClient.GetAsync(serviceUrl);
171:
172: httpResponseMessage.EnsureSuccessStatusCode();
173:
174: s = await httpResponseMessage.Content.ReadAsStringAsync();
175: }
176:
177: return s;
178: }
179:
180: ////////////////////////////////////////////////////////////////////////////
181:
182: /// <summary>
183: ///
184: /// </summary>
185: public static async Task<string> PutAsync<T>(string baseAddress, string serviceUrl, T t)
186: {
187: HttpResponseMessage httpResponseMessage;
188: var s = string.Empty;
189:
190: serviceUrl = SuffixUrlWithSlashIfItContainsDot(serviceUrl);
191:
192: using (var httpClient = new HttpClient())
193: {
194: httpClient.BaseAddress = new Uri(baseAddress);
195: httpClient.DefaultRequestHeaders.Accept.Clear();
196: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
197:
198: HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(t), Encoding.UTF8, "application/json");
199:
200: httpResponseMessage = await httpClient.PutAsJsonAsync(serviceUrl, httpContent);
201: // e.g. httpResponseMessage = await httpClient.PutAsJsonAsync($"api/products/{product.Id}", product);
202:
203: httpResponseMessage.EnsureSuccessStatusCode();
204:
205: s = await httpResponseMessage.Content.ReadAsStringAsync();
206: }
207:
208: return s;
209: }
210:
211: ////////////////////////////////////////////////////////////////////////////
212:
213: /// <summary>
214: ///
215: /// </summary>
216: public static async Task<string> PutAsync(string baseAddress, string serviceUrl)
217: {
218: HttpResponseMessage httpResponseMessage;
219: var s = string.Empty;
220:
221: serviceUrl = SuffixUrlWithSlashIfItContainsDot(serviceUrl);
222:
223: using (var httpClient = new HttpClient())
224: {
225: httpClient.BaseAddress = new Uri(baseAddress);
226: httpClient.DefaultRequestHeaders.Accept.Clear();
227: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
228:
229: HttpContent httpContent = new StringContent(JsonConvert.SerializeObject(string.Empty), Encoding.UTF8, "application/json"); // dummy
230:
231: httpResponseMessage = await httpClient.PutAsJsonAsync(serviceUrl, httpContent);
232: // e.g. httpResponseMessage = await httpClient.PutAsJsonAsync($"api/products/{product.Id}", product);
233:
234: httpResponseMessage.EnsureSuccessStatusCode();
235:
236: s = await httpResponseMessage.Content.ReadAsStringAsync();
237: }
238:
239: return s;
240: }
241:
242: ////////////////////////////////////////////////////////////////////////////
243:
244: /// <summary>
245: ///
246: /// </summary>
247: public static async Task<string> DeleteAsync(string baseAddress, string serviceUrl)
248: {
249: HttpResponseMessage httpResponseMessage;
250: var s = string.Empty;
251:
252: serviceUrl = SuffixUrlWithSlashIfItContainsDot(serviceUrl);
253:
254: using (var httpClient = new HttpClient())
255: {
256: httpClient.BaseAddress = new Uri(baseAddress);
257: httpClient.DefaultRequestHeaders.Accept.Clear();
258: httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
259:
260: httpResponseMessage = await httpClient.DeleteAsync(serviceUrl);
261: // e.g. httpResponseMessage = await client.DeleteAsync($"api/products/{id}");
262:
263: httpResponseMessage.EnsureSuccessStatusCode();
264:
265: s = await httpResponseMessage.Content.ReadAsStringAsync();
266: }
267:
268: return s;
269: }
270:
271: ////////////////////////////////////////////////////////////////////////////
272:
273: /// <summary>
274: ///
275: /// </summary>
276: private static string SuffixUrlWithSlashIfItContainsDot(string url)
277: {
278: // - Suffix the URL with a slash e.g. http://somedomain.com/api/people/staff.33311/ instead of http://somedomain.com/api/people/staff.33311 to pass a dot '.'
279:
280: if (!string.IsNullOrEmpty(url))
281: {
282: if (url.Contains(".")) url += "/";
283: }
284:
285: return url;
286: }
287:
288: ////////////////////////////////////////////////////////////////////////////
289: ////////////////////////////////////////////////////////////////////////////
290:
291:
292:
293: ////////////////////////////////////////////////////////////////////////////
294: ////////////////////////////////////////////////////////////////////////////
295:
296: /// <summary>
297: ///
298: /// </summary>
299: public static string Request(string url)
300: {
301: range = false;
302:
303: return ProcessRequest(url, 0, false, null, null);
304: }
305:
306: ////////////////////////////////////////////////////////////////////////////
307:
308: /// <summary>
309: ///
310: /// </summary>
311: public static string Request(string url, int start)
312: {
313: range = true;
314:
315: return ProcessRequest(url, start, false, null, null);
316: }
317:
318: ////////////////////////////////////////////////////////////////////////////
319:
320: /// <summary>
321: ///
322: /// </summary>
323: public static string Request2(string url)
324: {
325: range = true;
326:
327: return ProcessRequest2(url, false);
328: }
329:
330: ////////////////////////////////////////////////////////////////////////////
331:
332: /// <summary>
333: ///
334: /// </summary>
335: public static string Request_Utf8(string url, int start)
336: {
337: range = true;
338:
339: return ProcessRequest(url, start, true, null, null);
340: }
341:
342: ////////////////////////////////////////////////////////////////////////////
343:
344: /// <summary>
345: ///
346: /// </summary>
347: public static string Request(string url, int start, System.Net.Cookie c)
348: {
349: range = true;
350:
351: return ProcessRequest(url, start, false, c, null);
352: }
353:
354: ////////////////////////////////////////////////////////////////////////////
355:
356: /// <summary>
357: ///
358: /// </summary>
359: public static string Request(string url, int start, System.Net.Cookie c1, System.Net.Cookie c2)
360: {
361: range = true;
362:
363: return ProcessRequest(url, start, false, c1, c2);
364: }
365:
366: ////////////////////////////////////////////////////////////////////////////
367:
368: /// <summary>
369: ///
370: /// </summary>
371: public static string Post(string URI, string Parameters)
372: {
373: // for a "Request format is unrecognized" problem see: http://support.microsoft.com/default.aspx?scid=kb;en-us;819267
374:
375: System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
376: //req.Proxy = new System.Net.WebProxy(ProxyString, true);
377:
378: req.ContentType = "application/x-www-form-urlencoded";
379: req.Method = "POST";
380: //req.Timeout = 3000;
381:
382: byte[] bytes = System.Text.Encoding.ASCII.GetBytes(Parameters);
383: req.ContentLength = bytes.Length;
384:
385: using (System.IO.Stream os = req.GetRequestStream())
386: {
387: os.Write(bytes, 0, bytes.Length);
388: //os.Close();
389: }
390:
391: System.Net.WebResponse resp = null;
392:
393: try
394: {
395: resp = req.GetResponse();
396:
397: if (resp == null) return null;
398:
399: System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream(), Encoding.GetEncoding(1256));
400: return sr.ReadToEnd().Trim();
401: }
402: catch (WebException ex)
403: {
404: string str = ex.Message;
405: }
406:
407: return null;
408: }
409:
410: ////////////////////////////////////////////////////////////////////////////
411:
412: /// <summary>
413: ///
414: /// </summary>
415: public static string Post(string URI, string Parameters, int code_page)
416: {
417: // for a "Request format is unrecognized" problem see: http://support.microsoft.com/default.aspx?scid=kb;en-us;819267
418:
419: // Sometimes you need to POST in Windows 1256 code page for the process to run
420:
421: System.Net.WebRequest req = System.Net.WebRequest.Create(URI);
422: //req.Proxy = new System.Net.WebProxy(ProxyString, true);
423:
424: req.ContentType = "application/x-www-form-urlencoded";
425: req.Method = "POST";
426: //req.Timeout = 3000;
427:
428: byte[] bytes = System.Text.Encoding.GetEncoding(code_page).GetBytes(Parameters);
429: req.ContentLength = bytes.Length;
430:
431: using (System.IO.Stream os = req.GetRequestStream())
432: {
433: os.Write(bytes, 0, bytes.Length);
434: //os.Close();
435: }
436:
437: System.Net.WebResponse resp = null;
438:
439: try
440: {
441: resp = req.GetResponse();
442:
443: if (resp == null) return null;
444:
445: System.IO.StreamReader sr = new System.IO.StreamReader(resp.GetResponseStream(), Encoding.GetEncoding(code_page));
446: return sr.ReadToEnd().Trim();
447: }
448: catch (WebException ex)
449: {
450: string str = ex.Message;
451: }
452:
453: return null;
454: }
455:
456: ////////////////////////////////////////////////////////////////////////////
457:
458: /// <summary>
459: ///
460: /// </summary>
461: private static string ProcessRequest(string url, int start, bool utf8, System.Net.Cookie c1, System.Net.Cookie c2)
462: {
463: string text = "";
464:
465: try
466: {
467: Uri ourUri = new Uri(url);
468: // Creates an HttpWebRequest for the specified URL.
469: HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(ourUri);
470:
471: // this code below is very important. It sends a request with a specific cookie in the collection
472: // to demonstrate to the remote server that we have his cookie and we should skip his advertisement.
473: if (c1 != null || c2 != null)
474: {
475: myHttpWebRequest.CookieContainer = new CookieContainer();
476: if (c1 != null) myHttpWebRequest.CookieContainer.Add(c1);
477: if (c2 != null) myHttpWebRequest.CookieContainer.Add(c2);
478: }
479:
480: myHttpWebRequest.Method = "POST";
481: //myHttpWebRequest.Timeout = 5000; // 5 sec
482: //myHttpWebRequest.MaximumResponseHeadersLength = 100; // *1024 (Kilobytes)
483:
484: // set the range of data to be returned if the start and end positions are given
485: if (range) myHttpWebRequest.AddRange(start);
486:
487: myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
488: myHttpWebRequest.ContentLength = 0;
489:
490: HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
491:
492: if (myHttpWebRequest.HaveResponse)
493: {
494: Stream receiveStream = myHttpWebResponse.GetResponseStream();
495: Encoding encode;
496:
497: if (utf8) encode = System.Text.Encoding.GetEncoding("utf-8");
498: else encode = System.Text.Encoding.GetEncoding(1252); // 1252 best for western char
499:
500: // Pipes the stream to a higher level stream reader with the required encoding format.
501: using (StreamReader readStream = new StreamReader(receiveStream, encode))
502: {
503: text = readStream.ReadToEnd().Trim(); // ONE
504:
505: /*
506: // TWO
507: Char[] read = new Char[256];
508: // Reads 256 characters at a time.
509: int count = readStream.Read( read, 0, 256 );
510:
511: while (count > 0)
512: {
513: // Dumps the 256 characters on a string and displays the string to the console.
514: String str = new String(read, 0, count);
515: text += str;
516: count = readStream.Read(read, 0, 256);
517: }
518: */
519:
520: // Releases the resources of the response.
521: //myHttpWebResponse.Close();
522: }
523: }
524: else
525: {
526: text = "\nResponse not received from server";
527: }
528: }
529: catch (WebException e)
530: {
531: HttpWebResponse response = (HttpWebResponse)e.Response;
532: if (response != null)
533: {
534: if (response.StatusCode == HttpStatusCode.Unauthorized)
535: {
536: string challenge = null;
537: challenge = response.GetResponseHeader("WWW-Authenticate");
538: if (challenge != null) text = "\nThe following challenge was raised by the server: " + challenge;
539: }
540: else text = "\nThe following WebException was raised : " + e.Message;
541: }
542: else text = "\nResponse Received from server was null";
543: }
544: catch (Exception e)
545: {
546: text = "\nThe following Exception was raised : " + e.Message;
547: }
548:
549: return text;
550: }
551:
552: ////////////////////////////////////////////////////////////////////////////
553:
554: /// <summary>
555: ///
556: /// </summary>
557: private static string ProcessRequest2(string url, bool utf8)
558: {
559: string text = "";
560:
561: try
562: {
563: Uri ourUri = new Uri(url);
564: // Creates an HttpWebRequest for the specified URL.
565: HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(ourUri);
566:
567: //myHttpWebRequest.Method = "POST";
568: //myHttpWebRequest.Timeout = 5000; // 5 sec
569: //myHttpWebRequest.MaximumResponseHeadersLength = 100; // *1024 (Kilobytes)
570:
571: // set the range of data to be returned if the start and end positions are given
572: //if (range) myHttpWebRequest.AddRange(start);
573:
574: myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
575: myHttpWebRequest.ContentLength = 0;
576:
577: HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
578:
579: if (myHttpWebRequest.HaveResponse)
580: {
581: Stream receiveStream = myHttpWebResponse.GetResponseStream();
582: Encoding encode;
583:
584: if (utf8) encode = System.Text.Encoding.GetEncoding("utf-8");
585: else encode = System.Text.Encoding.GetEncoding(1252); // 1252 best for western char
586:
587: // Pipes the stream to a higher level stream reader with the required encoding format.
588: using (StreamReader readStream = new StreamReader(receiveStream, encode))
589: {
590: text = readStream.ReadToEnd().Trim(); // ONE
591:
592: /*
593: // TWO
594: Char[] read = new Char[256];
595: // Reads 256 characters at a time.
596: int count = readStream.Read( read, 0, 256 );
597:
598: while (count > 0)
599: {
600: // Dumps the 256 characters on a string and displays the string to the console.
601: String str = new String(read, 0, count);
602: text += str;
603: count = readStream.Read(read, 0, 256);
604: }
605: */
606:
607: // Releases the resources of the response.
608: //myHttpWebResponse.Close();
609: }
610: }
611: else
612: {
613: text = "\nResponse not received from server";
614: }
615: }
616: catch (WebException e)
617: {
618: HttpWebResponse response = (HttpWebResponse)e.Response;
619: if (response != null)
620: {
621: if (response.StatusCode == HttpStatusCode.Unauthorized)
622: {
623: string challenge = null;
624: challenge = response.GetResponseHeader("WWW-Authenticate");
625: if (challenge != null) text = "\nThe following challenge was raised by the server: " + challenge;
626: }
627: else text = "\nThe following WebException was raised : " + e.Message;
628: }
629: else text = "\nResponse Received from server was null";
630: }
631: catch (Exception e)
632: {
633: text = "\nThe following Exception was raised : " + e.Message;
634: }
635:
636: return text;
637: }
638:
639: ////////////////////////////////////////////////////////////////////////////
640:
641: /// <summary>
642: ///
643: /// </summary>
644: private static int Get(string url, out string text, out string result)
645: {
646: int op;
647:
648: op = 0;
649: result = "";
650: text = "";
651:
652: try
653: {
654: Uri ourUri = new Uri(url);
655: // Creates an HttpWebRequest for the specified URL.
656: HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(ourUri);
657: HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
658:
659: Stream receiveStream = myHttpWebResponse.GetResponseStream();
660: Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
661:
662: // Pipes the stream to a higher level stream reader with the required encoding format.
663: using (StreamReader readStream = new StreamReader(receiveStream, encode))
664: {
665: Char[] read = new Char[256];
666: // Reads 256 characters at a time.
667: int count = readStream.Read(read, 0, 256);
668:
669: while (count > 0)
670: {
671: // Dumps the 256 characters on a string and displays the string to the console.
672: String str = new String(read, 0, count);
673: text += str;
674: count = readStream.Read(read, 0, 256);
675: }
676:
677: // Releases the resources of the response.
678: //myHttpWebResponse.Close();
679: }
680:
681: op = 1;
682: }
683: catch (WebException e)
684: {
685: HttpWebResponse response = (HttpWebResponse)e.Response;
686: if (response != null)
687: {
688: if (response.StatusCode == HttpStatusCode.Unauthorized)
689: {
690: string challenge = null;
691: challenge = response.GetResponseHeader("WWW-Authenticate");
692: if (challenge != null) result = "The following challenge was raised by the server: " + challenge;
693: }
694: else result = "The following WebException was raised : " + e.Message;
695: }
696: else result = "Response Received from server was null";
697:
698: op = -1;
699: }
700: catch (Exception e)
701: {
702: result = "The following Exception was raised : " + e.Message;
703: op = -1;
704: }
705:
706: return op;
707: }
708:
709: ////////////////////////////////////////////////////////////////////////////
710: ////////////////////////////////////////////////////////////////////////////
711: }
712: }