初始化

This commit is contained in:
2025-12-11 11:39:02 +08:00
commit 156d6ccb06
1708 changed files with 1162911 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
/*
* Created by SharpDevelop.
* User: xiaoming.yin
* Date: 2012/5/30
* Time: 14:21
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using Aliyun.Api.LOG.Common.Authentication;
using Aliyun.Api.LOG.Common.Handlers;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// Description of ExecutionContext.
/// </summary>
internal class ExecutionContext
{
/// <summary>
/// The default encoding (charset name).
/// </summary>
private const string DefaultEncoding = "utf-8";
private IList<IResponseHandler> _responseHandlers = new List<IResponseHandler>();
/// <summary>
/// Gets or sets the charset.
/// </summary>
public string Charset { get; set; }
/// <summary>
/// Gets or sets the request signer.
/// </summary>
public IRequestSigner Signer { get; set; }
/// <summary>
/// Gets or sets the credentials.
/// </summary>
public ServiceCredentials Credentials { get; set ;}
/// <summary>
/// Gets the list of <see cref="IResponseHandler" />.
/// </summary>
public IList<IResponseHandler> ResponseHandlers
{
get { return _responseHandlers; }
}
/// <summary>
/// Constructor.
/// </summary>
public ExecutionContext()
{
this.Charset = DefaultEncoding;
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) Alibaba Cloud Computing
* All rights reserved.
*
* 版权所有 C阿里云计算有限公司
*/
using System;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// Represents a HTTP method.
/// </summary>
internal enum HttpMethod
{
/// <summary>
/// Represents HTTP GET. Default value.
/// </summary>
Get = 0,
/// <summary>
/// Represents HTTP DELETE.
/// </summary>
Delete,
/// <summary>
/// Represents HTTP HEAD.
/// </summary>
Head,
/// <summary>
/// Represents HTTP POST.
/// </summary>
Post,
/// <summary>
/// Represents HTTP PUT.
/// </summary>
Put,
/// <summary>
/// Represents HTTP OPTIONS.
/// </summary>
Options,
}
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) Alibaba Cloud Computing
* All rights reserved.
*
* 版权所有 C阿里云计算有限公司
*/
using System;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// Represent the channel that communicates with an Aliyun Open Service.
/// </summary>
internal interface IServiceClient
{
/// <summary>
/// Sends a request to the service.
/// </summary>
/// <param name="request">The request data.</param>
/// <param name="context">The execution context.</param>
/// <returns>The response data.</returns>
ServiceResponse Send(ServiceRequest request, ExecutionContext context);
}
}

View File

@@ -0,0 +1,87 @@
/*
* Copyright (C) Alibaba Cloud Computing
* All rights reserved.
*
* 版权所有 C阿里云计算有限公司
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using Aliyun.Api.LOG;
using Aliyun.Api.LOG.Utilities;
using Aliyun.Api.LOG.Common;
using Aliyun.Api.LOG.Common.Communication;
using Aliyun.Api.LOG.Common.Handlers;
using Aliyun.Api.LOG.Common.Utilities;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// The default implementation of <see cref="IServiceClient" />.
/// </summary>
internal abstract class ServiceClient : IServiceClient
{
#region Fields and Properties
private ClientConfiguration _configuration;
public ClientConfiguration Configuration
{
get { return _configuration; }
}
#endregion
#region Constructors
protected ServiceClient(ClientConfiguration configuration)
{
Debug.Assert(configuration != null);
// Make a definsive copy to ensure the class is immutable.
_configuration = (ClientConfiguration)configuration.Clone();
}
public static ServiceClient Create(ClientConfiguration configuration)
{
return new ServiceClientImpl(configuration);
}
#endregion
#region IServiceClient Members
public ServiceResponse Send(ServiceRequest request, ExecutionContext context)
{
Debug.Assert(request != null);
SignRequest(request, context);
ServiceResponse response = SendCore(request, context);
HandleResponse(response, context.ResponseHandlers);
return response;
}
#endregion
protected abstract ServiceResponse SendCore(ServiceRequest request, ExecutionContext context);
internal static void SignRequest(ServiceRequest request, ExecutionContext context)
{
if (context.Signer != null)
{
context.Signer.Sign(request, context.Credentials);
}
}
protected static void HandleResponse(ServiceResponse response, IList<IResponseHandler> handlers)
{
foreach(IResponseHandler handler in handlers)
{
handler.Handle(response);
}
}
}
}

View File

@@ -0,0 +1,429 @@
/*
* Copyright (C) Alibaba Cloud Computing
* All rights reserved.
*
* 版权所有 C阿里云计算有限公司
*/
//#define __UT_TEST_0EC173788C65DD08DA60575219707632__
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Reflection;
using Aliyun.Api.LOG;
using Aliyun.Api.LOG.Common.Utilities;
using Aliyun.Api.LOG.Utilities;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// An default <see cref="ServiceClient"/> implementation that
/// communicates with Aliyun Services over the HTTP protocol.
/// </summary>
internal class ServiceClientImpl : ServiceClient
{
#region Embeded Classes
/// <summary>
/// Represents the async operation of requests in <see cref="ServiceClientImpl"/>.
/// </summary>
private class HttpAsyncResult : AsyncResult<ServiceResponse>
{
public HttpWebRequest WebRequest { get; set; }
public ExecutionContext Context { get; set; }
public HttpAsyncResult(AsyncCallback callback, object state)
: base(callback, state)
{
}
}
/// <summary>
/// Represents the response data of <see cref="ServiceClientImpl"/> requests.
/// </summary>
internal class ResponseImpl : ServiceResponse
{
private bool _disposed;
private HttpWebResponse _response;
private Exception _failure;
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
private HttpStatusCode _httpStatusCode = HttpStatusCode.OK;
#endif
public override HttpStatusCode StatusCode
{
get
{
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
return _httpStatusCode;
#else
return _response.StatusCode;
#endif
}
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
set {
_httpStatusCode = value;
}
#endif
}
public override Exception Failure {
get
{
return this._failure;
}
}
public override IDictionary<string, string> Headers
{
get
{
ThrowIfObjectDisposed();
if (_headers == null)
{
_headers = GetResponseHeaders(_response);
}
return _headers;
}
}
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
private Stream _stream;
#endif
public override Stream Content
{
get
{
ThrowIfObjectDisposed();
try
{
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
return _response != null ?
_response.GetResponseStream() : _stream;
#else
return _response != null ?
_response.GetResponseStream() : null;
#endif
}
catch (ProtocolViolationException ex)
{
throw new InvalidOperationException(ex.Message, ex);
}
}
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
set
{
_stream = value;
}
#endif
}
public ResponseImpl(HttpWebResponse httpWebResponse)
{
Debug.Assert(httpWebResponse != null);
_response = httpWebResponse;
Debug.Assert(this.IsSuccessful(), "This constructor only allows a successfull response.");
}
public ResponseImpl(WebException failure)
{
Debug.Assert(failure != null);
HttpWebResponse httpWebResponse = failure.Response as HttpWebResponse;
Debug.Assert(httpWebResponse != null);
_failure = failure;
_response = httpWebResponse;
Debug.Assert(!this.IsSuccessful(), "This constructor only allows a failed response.");
}
//#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
internal ResponseImpl()
{
}
//#endif
private static IDictionary<string, string> GetResponseHeaders(HttpWebResponse response)
{
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
if (response == null)
{
IDictionary<string, string> testHeaders = new Dictionary<String, String>();
testHeaders.Add(LogConsts.NAME_HEADER_AUTH, "LOG mockkeyid:EX2VSCpdyFrcysmBaQ+aokupwcg=");
return testHeaders;
}
#endif
var headers = response.Headers;
var result = new Dictionary<string, string>(headers.Count,StringComparer.OrdinalIgnoreCase);
for (int i = 0; i < headers.Count; i++)
{
var key = headers.Keys[i];
var value = headers.Get(key);
result.Add(key,
HttpUtils.ReEncode(
value,
HttpUtils.Iso88591Charset,
HttpUtils.UTF8Charset));
}
return result;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (_disposed)
{
return;
}
if (disposing)
{
if (_response != null)
{
_response.Close();
_response = null;
}
_disposed = true;
}
}
private void ThrowIfObjectDisposed()
{
if (_disposed)
{
throw new ObjectDisposedException(this.GetType().Name);
}
}
}
#endregion
#region Constructors
public ServiceClientImpl(ClientConfiguration configuration)
: base(configuration)
{
}
#endregion
#region Implementations
internal delegate ServiceResponse WebSend(HttpWebRequest request);
internal WebSend SendMethod = DefaultSend;
internal static ResponseImpl DefaultSend(HttpWebRequest request)
{
var response = request.GetResponse() as HttpWebResponse;
return new ResponseImpl(response);
}
private static ServiceResponse HandleException(WebException ex)
{
var response = ex.Response as HttpWebResponse;
if (response == null)
{
throw new LogException("LogRequestError", "request is failed.", ex);
}
else
{
return new ResponseImpl(ex);
}
}
protected override ServiceResponse SendCore(ServiceRequest serviceRequest,
ExecutionContext context)
{
try
{
serviceRequest.HttpRequest = HttpFactory.CreateWebRequest(serviceRequest, Configuration);
#if(!__UT_TEST_0EC173788C65DD08DA60575219707632__)
SetRequestContent(serviceRequest.HttpRequest, serviceRequest);
#endif
return SendMethod(serviceRequest.HttpRequest);
}
catch (WebException ex)
{
return HandleException(ex);
}
}
private static void SetRequestContent(HttpWebRequest webRequest,
ServiceRequest serviceRequest)
{
var data = serviceRequest.BuildRequestContent();
if (data == null ||
(serviceRequest.Method != HttpMethod.Put &&
serviceRequest.Method != HttpMethod.Post))
{
// Skip setting content body in this case.
webRequest.ContentLength = 0;
return;
}
// Write data to the request stream.
long userSetContentLength = -1;
if (serviceRequest.Headers.ContainsKey(Aliyun.Api.LOG.Common.Utilities.HttpHeaders.ContentLength))
{
userSetContentLength = long.Parse(serviceRequest.Headers[Aliyun.Api.LOG.Common.Utilities.HttpHeaders.ContentLength]);
}
long streamLength = data.Length - data.Position;
webRequest.ContentLength = (userSetContentLength >= 0 && userSetContentLength <= streamLength) ?
userSetContentLength : streamLength;
webRequest.KeepAlive = false;
try
{
webRequest.ServicePoint.ConnectionLeaseTimeout = 5000;
}
catch (Exception e)
{
// https://github.com/dotnet/standard/issues/642
}
webRequest.ServicePoint.MaxIdleTime = 5000;
webRequest.ServicePoint.ConnectionLimit = 1000;
webRequest.ServicePoint.Expect100Continue = false;
// Generate GUID for connection group name, force close it when request is done.
webRequest.ConnectionGroupName = Guid.NewGuid().ToString();
using (var requestStream = webRequest.GetRequestStream())
{
data.WriteTo(requestStream, webRequest.ContentLength);
data.Seek(0, SeekOrigin.Begin);
requestStream.Flush();
requestStream.Close();
}
data.Close();
data.Dispose();
}
#endregion
}
internal static class HttpFactory
{
internal static HttpWebRequest CreateWebRequest(ServiceRequest serviceRequest, ClientConfiguration configuration)
{
Debug.Assert(serviceRequest != null && configuration != null);
HttpWebRequest webRequest = WebRequest.Create(serviceRequest.BuildRequestUri()) as HttpWebRequest;
SetRequestHeaders(webRequest, serviceRequest, configuration);
SetRequestProxy(webRequest, configuration);
return webRequest;
}
// Set request headers
private static void SetRequestHeaders(HttpWebRequest webRequest, ServiceRequest serviceRequest,
ClientConfiguration configuration)
{
webRequest.Timeout = configuration.ConnectionTimeout;
webRequest.ReadWriteTimeout = configuration.ReadWriteTimeout;
webRequest.Method = serviceRequest.Method.ToString().ToUpperInvariant();
// Because it is not allowed to set common headers
// with the WebHeaderCollection.Add method,
// we have to call an internal method to skip validation.
foreach (var h in serviceRequest.Headers)
{
//if (h.Key.CompareTo(LogConsts.NAME_HEADER_HOST) == 0)
// webRequest.Host = h.Value;
//else if (h.Key.CompareTo(LogConsts.NAME_HEADER_DATE) == 0)
// webRequest.Date = DateUtils.ParseRfc822Date(h.Value);
//if (h.Key.CompareTo(LogConsts.NAME_HEADER_CONTENTTYPE) == 0)
// webRequest.ContentType = h.Value;
//else
webRequest.Headers.AddInternal(h.Key, h.Value);
}
// Set user-agent
if (!string.IsNullOrEmpty(configuration.UserAgent))
{
webRequest.UserAgent = configuration.UserAgent;
}
}
// Set proxy
private static void SetRequestProxy(HttpWebRequest webRequest, ClientConfiguration configuration)
{
// Perf Improvement:
// If HttpWebRequest.Proxy is not set to null explicitly,
// it will try to load the IE proxy settings including auto proxy detection,
// which is quite time consuming.
webRequest.Proxy = null;
// Set proxy if proxy settings are specified.
if (!string.IsNullOrEmpty(configuration.ProxyHost))
{
if (configuration.ProxyPort < 0)
{
webRequest.Proxy = new WebProxy(configuration.ProxyHost);
} else
{
webRequest.Proxy = new WebProxy(configuration.ProxyHost, configuration.ProxyPort);
}
if (!string.IsNullOrEmpty(configuration.ProxyUserName)) {
webRequest.Proxy.Credentials = String.IsNullOrEmpty(configuration.ProxyDomain) ?
new NetworkCredential(configuration.ProxyUserName, configuration.ProxyPassword ?? string.Empty) :
new NetworkCredential(configuration.ProxyUserName, configuration.ProxyPassword ?? string.Empty,
configuration.ProxyDomain);
}
}
}
}
internal static class HttpExtensions
{
private static MethodInfo _addInternalMethod;
private static ICollection<PlatformID> monoPlatforms = new List<PlatformID>
{ PlatformID.MacOSX, PlatformID.Unix };
private static bool? isMonoPlatform;
internal static void AddInternal(this WebHeaderCollection headers, string key, string value)
{
if (isMonoPlatform == null)
{
isMonoPlatform = monoPlatforms.Contains(System.Environment.OSVersion.Platform);
}
// HTTP headers should be encoded to iso-8859-1,
// however it will be encoded automatically by HttpWebRequest in mono.
if (isMonoPlatform == false)
// Encode headers for win platforms.
value = HttpUtils.ReEncode(
value,
HttpUtils.UTF8Charset,
HttpUtils.Iso88591Charset);
if (_addInternalMethod == null)
{
// Specify the internal method name for adding headers
// mono: AddWithoutValidate
// win: AddInternal
string internalMethodName = (isMonoPlatform == true) ? "AddWithoutValidate" : "AddInternal";
MethodInfo mi = typeof(WebHeaderCollection).GetMethod(
internalMethodName,
BindingFlags.NonPublic | BindingFlags.Instance,
null,
new Type[] { typeof(string), typeof(string) },
null);
_addInternalMethod = mi;
}
_addInternalMethod.Invoke(headers, new object[] { key, value });
}
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) Alibaba Cloud Computing
* All rights reserved.
*
* 版权所有 C阿里云计算有限公司
*/
using System;
using System.Collections.Generic;
using System.IO;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// Description of ServiceMessage.
/// </summary>
internal class ServiceMessage
{
// HTTP header keys are case-insensitive.
protected IDictionary<String, String> _headers;
/// <summary>
/// Gets the dictionary of HTTP headers.
/// </summary>
public virtual IDictionary<String, String> Headers
{
get { return _headers; }
}
/// <summary>
/// Gets or sets the content stream.
/// </summary>
public virtual Stream Content { get; set; }
/// <summary>
/// Constructor.
/// </summary>
public ServiceMessage()
{
}
}
}

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) Alibaba Cloud Computing
* All rights reserved.
*
* 版权所有 C阿里云计算有限公司
*/
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Aliyun.Api.LOG.Common.Utilities;
using System.Net;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// Represents the information for sending requests.
/// </summary>
internal class ServiceRequest : ServiceMessage, IDisposable
{
private bool _disposed;
private IDictionary<String, String> parameters =
new Dictionary<String, String>();
/// <summary>
/// Gets or sets the endpoint.
/// </summary>
public Uri Endpoint { get; set; }
/// <summary>
/// Gets or sets the resource path of the request URI.
/// </summary>
public String ResourcePath { get; set; }
/// <summary>
/// Gets or sets the HTTP method.
/// </summary>
public HttpMethod Method { get; set; }
public HttpWebRequest HttpRequest { get; set; }
/// <summary>
/// Gets the dictionary of the request parameters.
/// </summary>
public IDictionary<String, String> Parameters{
get { return parameters; }
}
/// <summary>
/// Gets whether the request can be repeated.
/// </summary>
public bool IsRepeatable
{
get { return this.Content == null || this.Content.CanSeek; }
}
/// <summary>
/// Constuctor.
/// </summary>
public ServiceRequest()
{
_headers = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Build the request URI from the request message.
/// </summary>
/// <returns></returns>
public string BuildRequestUri()
{
const string delimiter = "/";
String uri = Endpoint.ToString();
if (!uri.EndsWith(delimiter)
&& (ResourcePath == null ||
!ResourcePath.StartsWith(delimiter)))
{
uri += delimiter;
}
else if (uri.EndsWith(delimiter) && (ResourcePath != null && ResourcePath.StartsWith(delimiter)))
{
uri = uri.Substring(0, uri.Length - 1);
}
if (ResourcePath != null){
uri += ResourcePath;
}
if (IsParameterInUri())
{
String paramString = HttpUtils.GetRequestParameterString(parameters);
if (!string.IsNullOrEmpty(paramString))
{
uri += "?" + paramString;
}
}
return uri;
}
public Stream BuildRequestContent()
{
if (!IsParameterInUri())
{
String paramString = HttpUtils.GetRequestParameterString(parameters);
if (!string.IsNullOrEmpty(paramString))
{
byte[] buffer = Encoding.GetEncoding("utf-8").GetBytes(paramString);
Stream content = new MemoryStream();
content.Write(buffer, 0, buffer.Length);
content.Flush();
// Move the marker to the beginning for further read.
content.Seek(0, SeekOrigin.Begin);
return content;
}
}
return this.Content;
}
private bool IsParameterInUri()
{
bool requestHasPayload = this.Content != null;
bool requestIsPost = this.Method == HttpMethod.Post;
bool putParamsInUri = !requestIsPost || requestHasPayload;
return putParamsInUri;
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
if (Content != null)
{
Content.Close();
Content = null;
}
if (HttpRequest != null)
{
// force close connection group
//Console.WriteLine(HttpRequest.ConnectionGroupName + "[]" + HttpRequest.ConnectionGroupName.Length.ToString() + "[]" + HttpRequest.ServicePoint.CurrentConnections.ToString());
HttpRequest.ServicePoint.CloseConnectionGroup(HttpRequest.ConnectionGroupName);
HttpRequest.Abort();
HttpRequest = null;
}
_disposed = true;
}
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright (C) Alibaba Cloud Computing
* All rights reserved.
*
* 版权所有 C阿里云计算有限公司
*/
//#define __UT_TEST_0EC173788C65DD08DA60575219707632__
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
namespace Aliyun.Api.LOG.Common.Communication
{
/// <summary>
/// Represents the data of the responses of requests.
/// </summary>
internal abstract class ServiceResponse : ServiceMessage, IDisposable
{
public abstract HttpStatusCode StatusCode {
get;
#if(__UT_TEST_0EC173788C65DD08DA60575219707632__)
set;
#endif
}
public abstract Exception Failure { get; }
public virtual bool IsSuccessful()
{
return (int)this.StatusCode / 100 == (int)HttpStatusCode.OK / 100;
}
/// <summary>
/// Throws the exception from communication if the status code is not 2xx.
/// </summary>
public virtual void EnsureSuccessful()
{
if (!IsSuccessful())
{
// Disposing the content should help users: If users call EnsureSuccessStatusCode(), an exception is
// thrown if the response status code is != 2xx. I.e. the behavior is similar to a failed request (e.g.
// connection failure). Users don't expect to dispose the content in this case: If an exception is
// thrown, the object is responsible fore cleaning up its state.
if (Content != null)
{
Content.Dispose();
}
Debug.Assert(this.Failure != null);
throw this.Failure;
}
}
/// <summary>
/// Constructor.
/// </summary>
public ServiceResponse()
{
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
}
}
}