Mercurial > pub > bltoolkit
diff Source/Net/HttpReader.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Net/HttpReader.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,465 @@ +/* + * File: HttpReader.cs + * Created: 01/17/2003 + * Author: Igor Tkachev + * mailto:it@rsdn.ru + */ + +using System; +using System.Collections; +using System.IO; +using System.Net; +using System.Text; +using System.Security.Cryptography.X509Certificates; +using System.Collections.Generic; + +namespace BLToolkit.Net +{ + public delegate void ProcessStream(Stream stream); + + /// <summary> + /// Encapsulates WebReader functions. + /// </summary> + public class HttpReader + { + #region Costructors + + public HttpReader() + { + BaseUri = string.Empty; + } + + public HttpReader(string baseUri) + { + BaseUri = baseUri; + } + + #endregion + + #region Public Properties + + private X509Certificate _certificate; + public X509Certificate Certificate + { + get { return _certificate; } + set { _certificate = value; } + } + + private string _baseUri; + public string BaseUri + { + get { return _baseUri; } + set { _baseUri = value; } + } + + private string _previousUri; + public string PreviousUri + { + get { return _previousUri; } + set { _previousUri = value; } + } + + private CookieContainer _cookieContainer = new CookieContainer(); + public CookieContainer CookieContainer + { + get { return _cookieContainer; } + set { _cookieContainer = value; } + } + + private string _userAgent = @"HttpReader"; + public string UserAgent + { + get { return _userAgent; } + set { _userAgent = value; } + } + + private string _accept = + @"image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-excel, application/vnd.ms-powerpoint, */*"; + public string Accept + { + get { return _accept; } + set { _accept = value; } + } + + private Uri _requestUri; + public Uri RequestUri + { + get { return _requestUri; } + set { _requestUri = value; } + } + + private string _contentType = string.Empty; + public string ContentType + { + get { return _contentType; } + set { _contentType = value; } + } + + private IWebProxy _proxy = new WebProxy(); + public IWebProxy Proxy + { + get { return _proxy; } + set { _proxy = value; } + } + + private ICredentials _credentials = CredentialCache.DefaultCredentials; + public ICredentials Credentials + { + get { return _credentials; } + set { _credentials = value; } + } + + private string _html; + public string Html + { + get { return _html; } + } + + private readonly Hashtable _headers = new Hashtable(); + public Hashtable Headers + { + get { return _headers; } + } + + private string _location; + public string Location + { + get { return _location; } + } + + private bool _sendReferer = true; + public bool SendReferer + { + get { return _sendReferer; } + set { _sendReferer = value; } + } + + private HttpStatusCode _statusCode; + public HttpStatusCode StatusCode + { + get { return _statusCode; } + } + + private int _timeout; + public int Timeout + { + get { return _timeout; } + set { _timeout = value; } + } + + #endregion + + #region Public Methods + + public void LoadCertificate(string fileName) + { + Certificate = X509Certificate.CreateFromCertFile(fileName); + } + + #endregion + + #region Request Methods + + private HttpWebRequest PrepareRequest(string method, string requestUri, ProcessStream requestStreamProcessor) + { + _html = ""; + + string uri = BaseUri; + + if (method != "SOAP") + uri += requestUri; + + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); + + if (Proxy != null) request.Proxy = Proxy; + if (Credentials != null) request.Credentials = Credentials; + + request.CookieContainer = CookieContainer; + request.UserAgent = UserAgent; + request.Accept = Accept; + request.Method = method == "SOAP"? "POST" : method; + request.KeepAlive = true; + + if (SendReferer) + request.Referer = PreviousUri ?? uri; + + foreach (string key in Headers.Keys) + request.Headers.Add(key, Headers[key].ToString()); + + if (method == "POST") + { + request.ContentType = "application/x-www-form-urlencoded"; + request.AllowAutoRedirect = false; + } + else if (method == "SOAP") + { + request.ContentType = "text/xml; charset=utf-8"; + request.AllowAutoRedirect = false; + + request.Headers.Add("SOAPAction", requestUri); + } + else + { + request.ContentType = ContentType; + request.AllowAutoRedirect = true; + } + + PreviousUri = uri; + RequestUri = request.RequestUri; + + if (Certificate != null) + request.ClientCertificates.Add(Certificate); + + if (Timeout != 0) + request.Timeout = Timeout; + + if (requestStreamProcessor != null) + using (Stream st = request.GetRequestStream()) + requestStreamProcessor(st); + + return request; + } + + public HttpStatusCode Request( + string requestUri, + string method, + ProcessStream requestStreamProcessor, + ProcessStream responseStreamProcessor) + { + HttpWebRequest request = PrepareRequest(method, requestUri, requestStreamProcessor); + + using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse()) + using (Stream sm = resp.GetResponseStream()) + { + _statusCode = resp.StatusCode; + _location = resp.Headers["Location"]; + + if (resp.ResponseUri.AbsoluteUri.StartsWith(BaseUri) == false) + BaseUri = resp.ResponseUri.Scheme + "://" + resp.ResponseUri.Host; + + CookieCollection cc = request.CookieContainer.GetCookies(request.RequestUri); + + // This code fixes the situation when a server sets a cookie without the 'path'. + // IE takes this as the root ('/') value, + // the HttpWebRequest class as the RequestUri.AbsolutePath value. + // + foreach (Cookie c in cc) + if (c.Path == request.RequestUri.AbsolutePath) + CookieContainer.Add(new Cookie(c.Name, c.Value, "/", c.Domain)); + + if (responseStreamProcessor != null) + responseStreamProcessor(sm); + } + + return StatusCode; + } + + public IEnumerable<string> Request( + string requestUri, + string method, + ProcessStream requestStreamProcessor) + { + HttpWebRequest request = PrepareRequest(method, requestUri, requestStreamProcessor); + + using (HttpWebResponse resp = (HttpWebResponse)request.GetResponse()) + using (Stream sm = resp.GetResponseStream()) + using (StreamReader sr = new StreamReader(sm, Encoding.Default)) + { + _statusCode = resp.StatusCode; + _location = resp.Headers["Location"]; + + if (resp.ResponseUri.AbsoluteUri.StartsWith(BaseUri) == false) + BaseUri = resp.ResponseUri.Scheme + "://" + resp.ResponseUri.Host; + + CookieCollection cc = request.CookieContainer.GetCookies(request.RequestUri); + + // This code fixes the case when a server sets a cookie without the 'path'. + // IE takes this as the root ('/') value, + // the HttpWebRequest class as the RequestUri.AbsolutePath value. + // + foreach (Cookie c in cc) + if (c.Path == request.RequestUri.AbsolutePath) + CookieContainer.Add(new Cookie(c.Name, c.Value, "/", c.Domain)); + + while (true) + { + string str = sr.ReadLine(); + + if (str == null) + break; + + yield return str; + } + } + } + + class DefaultRequestStreamProcessor + { + public DefaultRequestStreamProcessor(string data) + { + _data = data; + } + + readonly string _data; + + public void Process(Stream stream) + { + byte[] bytes = Encoding.ASCII.GetBytes(_data); + stream.Write(bytes, 0, bytes.Length); + } + } + + class DefaultResponseStreamProcessor + { + public DefaultResponseStreamProcessor(HttpReader reader) + { + _reader = reader; + } + + readonly HttpReader _reader; + + public void Process(Stream stream) + { + using (StreamReader sr = new StreamReader(stream, Encoding.Default)) + _reader._html = sr.ReadToEnd(); + } + } + + public HttpStatusCode Get(string requestUri) + { + DefaultResponseStreamProcessor rp = new DefaultResponseStreamProcessor(this); + + return Request(requestUri, "GET", null, rp.Process); + } + + public HttpStatusCode Get(string requestUri, ProcessStream responseStreamProcessor) + { + return Request(requestUri, "GET", null, responseStreamProcessor); + } + + public HttpStatusCode Post( + string requestUri, + string postData) + { + return Post( + requestUri, + new DefaultRequestStreamProcessor(postData).Process, + new DefaultResponseStreamProcessor(this).Process); + } + + public HttpStatusCode Post( + string requestUri, + ProcessStream requestStreamProcessor) + { + return Post( + requestUri, + requestStreamProcessor, + new DefaultResponseStreamProcessor(this).Process); + } + + public HttpStatusCode Post( + string requestUri, + string postData, + ProcessStream responseStreamProcessor) + { + return Post( + requestUri, + new ProcessStream(new DefaultRequestStreamProcessor(postData).Process), + responseStreamProcessor); + } + + public HttpStatusCode Post( + string requestUri, + ProcessStream requestStreamProcessor, + ProcessStream responseStreamProcessor) + { + Request(requestUri, "POST", requestStreamProcessor, responseStreamProcessor); + + for (int i = 0; i < 10; i++) + { + bool post = false; + + switch (StatusCode) + { + case HttpStatusCode.MultipleChoices: // 300 + case HttpStatusCode.MovedPermanently: // 301 + case HttpStatusCode.Found: // 302 + case HttpStatusCode.SeeOther: // 303 + break; + + case HttpStatusCode.TemporaryRedirect: // 307 + post = true; + break; + + default: + return StatusCode; + } + + if (Location == null) + break; + + Uri uri = new Uri(new Uri(PreviousUri), Location); + + BaseUri = uri.Scheme + "://" + uri.Host; + requestUri = uri.AbsolutePath + uri.Query; + + Request( + requestUri, + post? "POST": "GET", + post? requestStreamProcessor: null, + responseStreamProcessor); + } + + return StatusCode; + } + + private HttpStatusCode Soap( + string soapAction, + ProcessStream inputStreamProcessor, + ProcessStream outputStreamProcessor) + { + return Request("\"" + soapAction + "\"", "SOAP", inputStreamProcessor, outputStreamProcessor); + } + + public HttpStatusCode Soap(string soapAction, string postData) + { + return Soap(soapAction, + new DefaultRequestStreamProcessor(postData).Process, + new DefaultResponseStreamProcessor(this).Process); + } + + public HttpStatusCode Soap(string soapAction, string postData, ProcessStream outputStreamProcessor) + { + return Soap( + soapAction, + new DefaultRequestStreamProcessor(postData).Process, + outputStreamProcessor); + } + + public IEnumerable<string> SoapEx(string soapAction, string postData) + { + return Request("\"" + soapAction + "\"", "SOAP", new DefaultRequestStreamProcessor(postData).Process); + } + + #endregion + + #region Download + + public void Download(string requestUri, string fileName) + { + string uri = BaseUri + requestUri; + + WebClient request = new WebClient(); + + if (Proxy != null) request.Proxy = Proxy; + if (Credentials != null) request.Credentials = Credentials; + + foreach (string key in Headers.Keys) + request.Headers.Add(key, Headers[key].ToString()); + + request.DownloadFile(uri, fileName); + } + + #endregion + } +}