├── .gitignore ├── Aliyun_MQ_SDK ├── Libs │ └── log4net.dll ├── Runtime │ ├── Internal │ │ ├── Transform │ │ │ ├── IMarshaller.cs │ │ │ ├── IUnmarshaller.cs │ │ │ ├── IResponseUnmarshaller.cs │ │ │ ├── RequestMarshallException.cs │ │ │ ├── IWebResponseData.cs │ │ │ ├── ResponseUnmarshallException.cs │ │ │ ├── XmlMarshaller.cs │ │ │ ├── UnmarshallerContext.cs │ │ │ ├── XmlUnmarshaller.cs │ │ │ ├── ResponseUnmarshallers.cs │ │ │ ├── HttpWebRequestResponseData.cs │ │ │ └── HttpClientResponseData.cs │ │ ├── Auth │ │ │ ├── IServiceSigner.cs │ │ │ └── MQSigner.cs │ │ ├── Util │ │ │ └── Extensions.cs │ │ ├── ErrorResponse.cs │ │ ├── IRequest.cs │ │ ├── WebServiceRequest.cs │ │ └── DefaultRequest.cs │ ├── Enumerations.cs │ ├── Pipeline │ │ ├── ErrorHandler │ │ │ ├── IExceptionHandler.cs │ │ │ ├── ExceptionHandler.cs │ │ │ ├── WebExceptionHandler.cs │ │ │ ├── ErrorHandler.cs │ │ │ └── HttpErrorResponseExceptionHandler.cs │ │ ├── Handlers │ │ │ ├── CredentialsRetriever.cs │ │ │ ├── Signer.cs │ │ │ ├── GenericHandler.cs │ │ │ ├── Marshaller.cs │ │ │ └── Unmarshaller.cs │ │ ├── HttpErrorResponseException.cs │ │ ├── RuntimeAsyncResult.cs │ │ ├── RetryHandler │ │ │ ├── RetryPolicy.cs │ │ │ ├── RetryHandler.cs │ │ │ └── DefaultRetryPolicy.cs │ │ ├── PipelineHandler.cs │ │ ├── IPiplelineHandler.cs │ │ ├── Contexts.cs │ │ └── HttpHandler │ │ │ └── IHttpRequestFactory.cs │ ├── WebServiceResponse.cs │ ├── ServiceCredentials.cs │ ├── AliyunServiceException.cs │ ├── HttpClientBasedAliyunServiceClient.cs │ └── AliyunServiceClient.cs ├── Model │ ├── AckMessageResponse.cs │ ├── ConsumeMessageResponse.cs │ ├── exp │ │ ├── ErrorCode.cs │ │ ├── SubscriptionNotExistException.cs │ │ ├── MQException.cs │ │ ├── MalformedXMLException.cs │ │ ├── InvalidArgumentException.cs │ │ ├── MessageNotExistException.cs │ │ ├── TopicNotExistException.cs │ │ ├── ReceiptHandleErrorException.cs │ │ └── AckMessageException.cs │ ├── PublishMessageResponse.cs │ ├── AckMessageRequest.cs │ ├── PublishMessageRequest.cs │ ├── Internal │ │ └── MarshallTransformations │ │ │ ├── ConsumeMessageRequestMarshaller.cs │ │ │ ├── AckMessageRequestMarshaller.cs │ │ │ ├── PublishMessageRequestMarshaller.cs │ │ │ ├── PublishMessageResponseUnmarshaller.cs │ │ │ ├── ErrorResponseUnmarshaller.cs │ │ │ ├── AckMessageResponseUnmarshaller.cs │ │ │ └── ConsumeMessageResponseUnmarshaller.cs │ ├── ConsumeMessageRequest.cs │ ├── TopicMessage.cs │ └── Message.cs ├── MQConfig.cs ├── Aliyun_MQ_SDK.csproj ├── Aliyun_MQ_SDK.nlog ├── Util │ ├── MqLogManager.cs │ ├── CryptoUtil.cs │ └── Constants.cs ├── MQClient.cs ├── MQConsumer.cs └── MQProducer.cs ├── Aliyun_MQ_SDK.sln ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | Aliyun_MQ_SDK/bin/ 2 | Aliyun_MQ_SDK/obj/ 3 | .git/ 4 | .git 5 | .vs/ 6 | .vs 7 | .DS_Store 8 | .idea -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Libs/log4net.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aliyunmq/mq-http-csharp-sdk/HEAD/Aliyun_MQ_SDK/Libs/log4net.dll -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/IMarshaller.cs: -------------------------------------------------------------------------------- 1 | namespace Aliyun.MQ.Runtime.Internal.Transform 2 | { 3 | public interface IMarshaller 4 | { 5 | T Marshall(R input); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/IUnmarshaller.cs: -------------------------------------------------------------------------------- 1 | namespace Aliyun.MQ.Runtime.Internal.Transform 2 | { 3 | public interface IUnmarshaller 4 | { 5 | T Unmarshall(R input); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Enumerations.cs: -------------------------------------------------------------------------------- 1 | namespace Aliyun.MQ.Runtime 2 | { 3 | 4 | public enum SigningAlgorithm 5 | { 6 | HmacSHA1, 7 | HmacSHA256 8 | }; 9 | 10 | public enum HttpMethod 11 | { 12 | GET, 13 | PUT, 14 | POST, 15 | DELETE 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Auth/IServiceSigner.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal.Util; 2 | 3 | namespace Aliyun.MQ.Runtime.Internal.Auth 4 | { 5 | public partial interface IServiceSigner 6 | { 7 | void Sign(IRequest request, string accessKeyId, string secretAccessKey, string stsToken); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/AckMessageResponse.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using Aliyun.MQ.Model.Internal.MarshallTransformations; 7 | 8 | namespace Aliyun.MQ.Model 9 | { 10 | public partial class AckMessageResponse : WebServiceResponse 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/IResponseUnmarshaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace Aliyun.MQ.Runtime.Internal.Transform 5 | { 6 | public interface IResponseUnmarshaller : IUnmarshaller 7 | { 8 | AliyunServiceException UnmarshallException(R input, Exception innerException, HttpStatusCode statusCode); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/ErrorHandler/IExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Aliyun.MQ.Runtime.Pipeline.ErrorHandler 4 | { 5 | public interface IExceptionHandler 6 | { 7 | bool Handle(IExecutionContext executionContext, Exception exception); 8 | } 9 | 10 | public interface IExceptionHandler : IExceptionHandler where T : Exception 11 | { 12 | bool HandleException(IExecutionContext executionContext, T exception); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/MQConfig.cs: -------------------------------------------------------------------------------- 1 | 2 | using Aliyun.MQ.Runtime; 3 | 4 | namespace Aliyun.MQ 5 | { 6 | public partial class MQConfig : ClientConfig 7 | { 8 | public MQConfig() 9 | { 10 | } 11 | 12 | public override string ServiceVersion 13 | { 14 | get 15 | { 16 | return "2015-06-06"; 17 | } 18 | } 19 | 20 | public override string ServiceName 21 | { 22 | get 23 | { 24 | return "Aliyun.MQ"; 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/ConsumeMessageResponse.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Model.Internal.MarshallTransformations; 2 | using Aliyun.MQ.Runtime; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Text; 7 | 8 | namespace Aliyun.MQ.Model 9 | { 10 | public partial class ConsumeMessageResponse : WebServiceResponse 11 | { 12 | private List _messages = new List(); 13 | 14 | public List Messages 15 | { 16 | get { return this._messages; } 17 | set { this._messages = value; } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/ErrorHandler/ExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Aliyun.MQ.Runtime.Internal.Util; 3 | 4 | namespace Aliyun.MQ.Runtime.Pipeline.ErrorHandler 5 | { 6 | public abstract class ExceptionHandler : IExceptionHandler where T : Exception 7 | { 8 | protected ExceptionHandler() 9 | { 10 | } 11 | 12 | public bool Handle(IExecutionContext executionContext, Exception exception) 13 | { 14 | return HandleException(executionContext, exception as T); 15 | } 16 | 17 | public abstract bool HandleException(IExecutionContext executionContext, T exception); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Util/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | 4 | namespace Aliyun.MQ.Runtime.Internal.Util 5 | { 6 | internal static partial class Extensions 7 | { 8 | private static readonly long ticksPerSecond = TimeSpan.FromSeconds(1).Ticks; 9 | private static readonly double tickFrequency = ticksPerSecond / (double)Stopwatch.Frequency; 10 | public static long GetElapsedDateTimeTicks(this Stopwatch self) 11 | { 12 | double stopwatchTicks = self.ElapsedTicks; 13 | long ticks = (long)(stopwatchTicks * tickFrequency); 14 | return ticks; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/ErrorCode.cs: -------------------------------------------------------------------------------- 1 | 2 | namespace Aliyun.MQ.Model.Exp 3 | { 4 | public static class ErrorCode 5 | { 6 | public const string InternalError = "InternalError"; 7 | 8 | public const string InvalidArgument = "InvalidArgument"; 9 | 10 | public const string MessageNotExist = "MessageNotExist"; 11 | 12 | public const string TopicNotExist = "TopicNotExist"; 13 | public const string SubscriptionNotExist = "SubscriptionNotExist"; 14 | 15 | public const string ReceiptHandleError = "ReceiptHandleError"; 16 | public const string MalformedXML = "MalformedXML"; 17 | 18 | public const string AckMessageFail = "AckMessageFail"; 19 | 20 | } 21 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/RequestMarshallException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Aliyun.MQ.Runtime.Internal.Transform 5 | { 6 | internal class RequestMarshallException : InvalidOperationException, ISerializable 7 | { 8 | public RequestMarshallException(string message) 9 | : base(message) 10 | { 11 | } 12 | 13 | public RequestMarshallException(string message, Exception innerException) 14 | : base(message, innerException) 15 | { 16 | } 17 | 18 | protected RequestMarshallException(SerializationInfo info, StreamingContext context) 19 | : base(info, context) 20 | { 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/IWebResponseData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Runtime.Internal.Transform 6 | { 7 | public interface IWebResponseData 8 | { 9 | long ContentLength { get; } 10 | string ContentType { get; } 11 | HttpStatusCode StatusCode { get; } 12 | bool IsSuccessStatusCode { get; } 13 | string[] GetHeaderNames(); 14 | bool IsHeaderPresent(string headerName); 15 | string GetHeaderValue(string headerName); 16 | 17 | IHttpResponseBody ResponseBody { get; } 18 | } 19 | 20 | public interface IHttpResponseBody : IDisposable 21 | { 22 | Stream OpenResponse(); 23 | 24 | System.Threading.Tasks.Task OpenResponseAsync(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Aliyun_MQ_SDK.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | Always 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/ResponseUnmarshallException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Aliyun.MQ.Runtime.Internal.Transform 5 | { 6 | [Serializable] 7 | internal class ResponseUnmarshallException : InvalidOperationException, ISerializable 8 | { 9 | public ResponseUnmarshallException() 10 | { 11 | } 12 | 13 | public ResponseUnmarshallException(string message) 14 | : base(message) 15 | { 16 | } 17 | 18 | public ResponseUnmarshallException(string message, Exception innerException) 19 | : base(message, innerException) 20 | { 21 | } 22 | 23 | protected ResponseUnmarshallException(SerializationInfo info, StreamingContext context) 24 | : base(info, context) 25 | { 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/ErrorResponse.cs: -------------------------------------------------------------------------------- 1 | namespace Aliyun.MQ.Runtime.Internal 2 | { 3 | public class ErrorResponse 4 | { 5 | private string _code; 6 | private string _message; 7 | private string _requestId; 8 | private string _hostId; 9 | 10 | public string Code 11 | { 12 | get { return _code; } 13 | set { _code = value; } 14 | } 15 | 16 | public string Message 17 | { 18 | get { return _message; } 19 | set { _message = value; } 20 | } 21 | 22 | public string RequestId 23 | { 24 | get { return _requestId; } 25 | set { _requestId = value; } 26 | } 27 | 28 | public string HostId 29 | { 30 | get { return _hostId; } 31 | set { _hostId = value; } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/ErrorHandler/WebExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Net; 3 | using Aliyun.MQ.Runtime.Internal.Util; 4 | 5 | namespace Aliyun.MQ.Runtime.Pipeline.ErrorHandler 6 | { 7 | public class WebExceptionHandler : ExceptionHandler 8 | { 9 | public WebExceptionHandler() : 10 | base() 11 | { 12 | } 13 | 14 | public override bool HandleException(IExecutionContext executionContext, WebException exception) 15 | { 16 | var requestContext = executionContext.RequestContext; 17 | var httpErrorResponse = exception.Response as HttpWebResponse; 18 | 19 | var message = string.Format(CultureInfo.InvariantCulture, 20 | "A WebException with status {0} was thrown, caused by {1}", exception.Status, exception.Message); 21 | throw new AliyunServiceException(message, exception); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/Handlers/CredentialsRetriever.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal.Util; 2 | 3 | namespace Aliyun.MQ.Runtime.Pipeline.Handlers 4 | { 5 | public class CredentialsRetriever : GenericHandler 6 | { 7 | public CredentialsRetriever(ServiceCredentials credentials) 8 | { 9 | this.Credentials = credentials; 10 | } 11 | 12 | protected ServiceCredentials Credentials 13 | { 14 | get; 15 | private set; 16 | } 17 | 18 | protected override void PreInvoke(IExecutionContext executionContext) 19 | { 20 | ImmutableCredentials ic = null; 21 | if (Credentials != null && (Credentials is BasicServiceCredentials)) 22 | { 23 | try 24 | { 25 | ic = Credentials.GetCredentials(); 26 | } 27 | finally 28 | { 29 | } 30 | } 31 | 32 | executionContext.RequestContext.ImmutableCredentials = ic; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/HttpErrorResponseException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Aliyun.MQ.Runtime.Internal.Transform; 3 | 4 | namespace Aliyun.MQ.Runtime.Pipeline 5 | { 6 | /// 7 | /// HttpErrorResponseException 8 | /// 9 | public class HttpErrorResponseException : Exception 10 | { 11 | /// 12 | /// Gets and sets original response data. 13 | /// 14 | public IWebResponseData Response { get; private set; } 15 | 16 | public HttpErrorResponseException(IWebResponseData response) 17 | { 18 | this.Response = response; 19 | } 20 | 21 | public HttpErrorResponseException(string message, IWebResponseData response) 22 | : base(message) 23 | { 24 | this.Response = response; 25 | } 26 | 27 | public HttpErrorResponseException(string message, Exception innerException, IWebResponseData response) 28 | : base(message,innerException) 29 | { 30 | this.Response = response; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aliyun_MQ_SDK", "Aliyun_MQ_SDK\Aliyun_MQ_SDK.csproj", "{74B011A2-B082-4749-B6C4-9EEB8BEAF9C5}" 5 | EndProject 6 | Global 7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 8 | Debug|Any CPU = Debug|Any CPU 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {74B011A2-B082-4749-B6C4-9EEB8BEAF9C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 13 | {74B011A2-B082-4749-B6C4-9EEB8BEAF9C5}.Debug|Any CPU.Build.0 = Debug|Any CPU 14 | {74B011A2-B082-4749-B6C4-9EEB8BEAF9C5}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {74B011A2-B082-4749-B6C4-9EEB8BEAF9C5}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(MonoDevelopProperties) = preSolution 18 | Policies = $0 19 | $0.TextStylePolicy = $1 20 | $1.inheritsSet = null 21 | $1.scope = text/x-csharp 22 | $0.CSharpFormattingPolicy = $2 23 | $2.scope = text/x-csharp 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 aliyun.mq 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/SubscriptionNotExistException.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Model.Exp 6 | { 7 | public class SubscriptionNotExistException : MQException 8 | { 9 | public SubscriptionNotExistException(string message) 10 | : base(message) 11 | { } 12 | 13 | public SubscriptionNotExistException(string message, Exception innerException) 14 | : base(message, innerException) 15 | { } 16 | 17 | public SubscriptionNotExistException(Exception innerException) 18 | : base(innerException) 19 | { } 20 | 21 | public SubscriptionNotExistException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 22 | : base(message, errorCode, requestId, hostId, statusCode) 23 | { } 24 | 25 | public SubscriptionNotExistException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 26 | : base(message, innerException, errorCode, requestId, hostId, statusCode) 27 | { } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/MQException.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Net; 4 | using Aliyun.MQ.Runtime; 5 | 6 | namespace Aliyun.MQ.Model.Exp 7 | { 8 | public class MQException : AliyunServiceException 9 | { 10 | public MQException(string message) 11 | : base(message) 12 | { 13 | } 14 | 15 | public MQException(string message, Exception innerException) 16 | : base(message, innerException) 17 | { 18 | } 19 | 20 | public MQException(Exception innerException) 21 | : base(innerException.Message, innerException) 22 | { 23 | } 24 | 25 | public MQException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 26 | : base(message, errorCode, requestId, hostId, statusCode) 27 | { 28 | } 29 | 30 | public MQException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 31 | : base(message, innerException, errorCode, requestId, hostId, statusCode) 32 | { 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Aliyun_MQ_SDK.nlog: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/MalformedXMLException.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Model.Exp 6 | { 7 | public class MalformedXMLException : MQException 8 | { 9 | /// 10 | /// Constructs a new MalformedXMLException with the specified error message. 11 | /// 12 | public MalformedXMLException(string message) 13 | : base(message) {} 14 | 15 | public MalformedXMLException(string message, Exception innerException) 16 | : base(message, innerException) {} 17 | 18 | public MalformedXMLException(Exception innerException) 19 | : base(innerException) {} 20 | 21 | public MalformedXMLException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 22 | : base(message, errorCode, requestId, hostId, statusCode) { } 23 | 24 | public MalformedXMLException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 25 | : base(message, innerException, errorCode, requestId, hostId, statusCode) { } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/InvalidArgumentException.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Model.Exp 6 | { 7 | public class InvalidArgumentException : MQException 8 | { 9 | /// 10 | /// Constructs a new InvalidArgumentException with the specified error message. 11 | /// 12 | public InvalidArgumentException(string message) 13 | : base(message) {} 14 | 15 | public InvalidArgumentException(string message, Exception innerException) 16 | : base(message, innerException) {} 17 | 18 | public InvalidArgumentException(Exception innerException) 19 | : base(innerException) {} 20 | 21 | public InvalidArgumentException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 22 | : base(message, innerException, errorCode, requestId, hostId, statusCode) {} 23 | 24 | public InvalidArgumentException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 25 | : base(message, errorCode, requestId, hostId, statusCode) {} 26 | 27 | } 28 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Util/MqLogManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using NLog; 5 | using NLog.Config; 6 | 7 | 8 | namespace Aliyun.MQ.Util 9 | { 10 | /** 11 | * HTTP client Log Manager. 12 | * 13 | * Configure component logging, please refer to https://github.com/NLog/NLog/wiki/Configure-component-logging 14 | */ 15 | public class MqLogManager 16 | { 17 | public static LogFactory Instance 18 | { 19 | get { return LazyInstance.Value; } 20 | } 21 | 22 | private static readonly Lazy LazyInstance = 23 | new Lazy(() => { return BuildLogFactory(); }); 24 | 25 | private static LogFactory BuildLogFactory() 26 | { 27 | // Use name of current assembly to construct NLog config filename 28 | Assembly thisAssembly = Assembly.GetExecutingAssembly(); 29 | string configFilePath = Path.ChangeExtension(thisAssembly.Location, ".nlog"); 30 | 31 | LogFactory logFactory = new LogFactory(); 32 | logFactory.Configuration = new XmlLoggingConfiguration(configFilePath, logFactory); 33 | return logFactory; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/MessageNotExistException.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Model.Exp 6 | { 7 | /// 8 | /// MessageNotExistException 9 | /// 10 | public class MessageNotExistException : MQException 11 | { 12 | /// 13 | /// Constructs a new MessageNotExistException with the specified error message. 14 | /// 15 | public MessageNotExistException(string message) 16 | : base(message) {} 17 | 18 | public MessageNotExistException(string message, Exception innerException) 19 | : base(message, innerException) {} 20 | 21 | public MessageNotExistException(Exception innerException) 22 | : base(innerException) {} 23 | 24 | public MessageNotExistException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 25 | : base(message, errorCode, requestId, hostId, statusCode) { } 26 | 27 | public MessageNotExistException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 28 | : base(message, innerException, errorCode, requestId, hostId, statusCode) { } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/Handlers/Signer.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal.Util; 2 | 3 | namespace Aliyun.MQ.Runtime.Pipeline.Handlers 4 | { 5 | public class Signer : GenericHandler 6 | { 7 | protected override void PreInvoke(IExecutionContext executionContext) 8 | { 9 | if (ShouldSign(executionContext.RequestContext)) 10 | { 11 | SignRequest(executionContext.RequestContext); 12 | executionContext.RequestContext.IsSigned = true; 13 | } 14 | } 15 | 16 | private static bool ShouldSign(IRequestContext requestContext) 17 | { 18 | return !requestContext.IsSigned; 19 | } 20 | 21 | internal static void SignRequest(IRequestContext requestContext) 22 | { 23 | ImmutableCredentials immutableCredentials = requestContext.ImmutableCredentials; 24 | 25 | if (immutableCredentials == null) 26 | return; 27 | 28 | try 29 | { 30 | requestContext.Signer.Sign(requestContext.Request, immutableCredentials.AccessKey, immutableCredentials.SecretKey, immutableCredentials.SecurityToken); 31 | } 32 | finally 33 | { 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/TopicNotExistException.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Model.Exp 6 | { 7 | /// 8 | /// TopicNotExistException 9 | /// 10 | public class TopicNotExistException : MQException 11 | { 12 | /// 13 | /// Constructs a new TopicNotExistException with the specified error message. 14 | /// 15 | public TopicNotExistException(string message) 16 | : base(message) 17 | { } 18 | 19 | public TopicNotExistException(string message, Exception innerException) 20 | : base(message, innerException) 21 | { } 22 | 23 | public TopicNotExistException(Exception innerException) 24 | : base(innerException) 25 | { } 26 | 27 | public TopicNotExistException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 28 | : base(message, errorCode, requestId, hostId, statusCode) 29 | { } 30 | 31 | public TopicNotExistException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 32 | : base(message, innerException, errorCode, requestId, hostId, statusCode) 33 | { } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/ReceiptHandleErrorException.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Model.Exp 6 | { 7 | /// 8 | /// ReceiptHandleErrorException 9 | /// 10 | public class ReceiptHandleErrorException : MQException 11 | { 12 | /// 13 | /// Constructs a new ReceiptHandleErrorException with the specified error message. 14 | /// 15 | public ReceiptHandleErrorException(string message) 16 | : base(message) {} 17 | 18 | public ReceiptHandleErrorException(string message, Exception innerException) 19 | : base(message, innerException) {} 20 | 21 | public ReceiptHandleErrorException(Exception innerException) 22 | : base(innerException) {} 23 | 24 | public ReceiptHandleErrorException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 25 | : base(message, errorCode, requestId, hostId, statusCode) { } 26 | 27 | public ReceiptHandleErrorException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 28 | : base(message, innerException, errorCode, requestId, hostId, statusCode) { } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/XmlMarshaller.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Util; 2 | using System; 3 | using System.IO; 4 | using System.Xml.Serialization; 5 | 6 | namespace Aliyun.MQ.Runtime.Internal.Transform 7 | { 8 | internal class XmlMarshaller : IMarshaller 9 | { 10 | private static readonly XmlSerializer _serializer = new XmlSerializer(typeof(TRequest)); 11 | 12 | public Stream Marshall(TRequest requestObject) 13 | { 14 | MemoryStream stream = null; 15 | var gotException = false; 16 | try 17 | { 18 | stream = new MemoryStream(); 19 | var namespaces = new XmlSerializerNamespaces(); 20 | namespaces.Add(string.Empty, Constants.MQ_XML_NAMESPACE); 21 | _serializer.Serialize(stream, requestObject, namespaces); 22 | stream.Seek(0, SeekOrigin.Begin); 23 | } 24 | catch (InvalidOperationException ex) 25 | { 26 | gotException = true; 27 | throw new RequestMarshallException(ex.Message, ex); 28 | } 29 | finally 30 | { 31 | if (gotException && stream != null) 32 | { 33 | stream.Close(); 34 | } 35 | } 36 | return stream; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/WebServiceResponse.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | 5 | namespace Aliyun.MQ.Runtime 6 | { 7 | /// 8 | /// Abstract class for Response objects, contains response headers, 9 | /// and no result information. 10 | /// 11 | public class WebServiceResponse 12 | { 13 | private IDictionary _headers = new Dictionary(StringComparer.OrdinalIgnoreCase); 14 | private long _contentLength; 15 | private HttpStatusCode _httpStatusCode; 16 | 17 | /// 18 | /// Returns the headers of the HTTP response. 19 | /// 20 | public IDictionary Headers 21 | { 22 | get { return _headers; } 23 | set { _headers = value; } 24 | } 25 | 26 | /// 27 | /// Returns the content length of the HTTP response. 28 | /// 29 | public long ContentLength 30 | { 31 | get { return this._contentLength; } 32 | set { this._contentLength = value; } 33 | } 34 | 35 | /// 36 | /// Returns the status code of the HTTP response. 37 | /// 38 | public HttpStatusCode HttpStatusCode 39 | { 40 | get { return this._httpStatusCode; } 41 | set { this._httpStatusCode = value; } 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/Handlers/GenericHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Aliyun.MQ.Runtime.Internal; 3 | 4 | namespace Aliyun.MQ.Runtime.Pipeline.Handlers 5 | { 6 | public abstract class GenericHandler : PipelineHandler 7 | { 8 | public override void InvokeSync(IExecutionContext executionContext) 9 | { 10 | PreInvoke(executionContext); 11 | base.InvokeSync(executionContext); 12 | PostInvoke(executionContext); 13 | } 14 | 15 | public override IAsyncResult InvokeAsync(IAsyncExecutionContext executionContext) 16 | { 17 | PreInvoke(ExecutionContext.CreateFromAsyncContext(executionContext)); 18 | return base.InvokeAsync(executionContext); 19 | } 20 | 21 | protected override void InvokeAsyncCallback(IAsyncExecutionContext executionContext) 22 | { 23 | PostInvoke(ExecutionContext.CreateFromAsyncContext(executionContext)); 24 | base.InvokeAsyncCallback(executionContext); 25 | } 26 | 27 | public override System.Threading.Tasks.Task InvokeAsync(IExecutionContext executionContext) 28 | { 29 | PreInvoke(executionContext); 30 | return base.InvokeAsync(executionContext); 31 | } 32 | 33 | protected virtual void PreInvoke(IExecutionContext executionContext) { } 34 | 35 | protected virtual void PostInvoke(IExecutionContext executionContext) { } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MQ HTTP C# SDK 2 | Aliyun MQ Documents: http://www.aliyun.com/product/ons 3 | 4 | Aliyun MQ Console: https://ons.console.aliyun.com 5 | 6 | ## Use 7 | 8 | 1. 下载最新版csharp sdk,解压后将工程导入到VisualStudio,其中Aliyun_MQ_SDK就是sdk所在的目录; 9 | 2. Sample中替换相关的参数 10 | 11 | ## Note 12 | 1. Http consumer only support timer msg (less than 3 days), no matter the msg is produced from http or tcp protocol. 13 | 2. Order is only supported at special server cluster. 14 | 15 | ## Samples (github) 16 | 17 | [Publish Message](https://github.com/aliyunmq/mq-http-samples/blob/master/csharp/producer.cs) 18 | 19 | [Consume Message](https://github.com/aliyunmq/mq-http-samples/blob/master/csharp/consumer.cs) 20 | 21 | [Transaction Message](https://github.com/aliyunmq/mq-http-samples/blob/master/csharp/trans_producer.cs) 22 | 23 | [Publish Order Message](https://github.com/aliyunmq/mq-http-samples/blob/master/csharp/order_producer.cs) 24 | 25 | [Consume Order Message](https://github.com/aliyunmq/mq-http-samples/blob/master/csharp/order_consumer.cs) 26 | 27 | ### Sample (code.aliyun.com) 28 | 29 | [Publish Message](https://code.aliyun.com/aliware_rocketmq/mq-http-samples/blob/master/csharp/producer.cs) 30 | 31 | [Consume Message](https://code.aliyun.com/aliware_rocketmq/mq-http-samples/blob/master/csharp/consumer.cs) 32 | 33 | [Transaction Message](https://code.aliyun.com/aliware_rocketmq/mq-http-samples/blob/master/csharp/trans_producer.cs) 34 | 35 | [Publish Order Message](https://code.aliyun.com/aliware_rocketmq/mq-http-samples/blob/master/csharp/order_producer.cs) 36 | 37 | [Consume Order Message](https://code.aliyun.com/aliware_rocketmq/mq-http-samples/blob/master/csharp/order_consumer.cs) -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/UnmarshallerContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace Aliyun.MQ.Runtime.Internal.Transform 5 | { 6 | public abstract class UnmarshallerContext : IDisposable 7 | { 8 | private bool disposed = false; 9 | protected IWebResponseData WebResponseData { get; set; } 10 | 11 | public Stream ResponseStream { get; set; } 12 | 13 | public IWebResponseData ResponseData 14 | { 15 | get { return WebResponseData; } 16 | } 17 | 18 | #region Dispose Pattern Implementation 19 | 20 | protected virtual void Dispose(bool disposing) 21 | { 22 | if (!this.disposed) 23 | { 24 | if (disposing) 25 | { 26 | if (this.ResponseStream != null) 27 | { 28 | ResponseStream.Dispose(); 29 | ResponseStream = null; 30 | } 31 | } 32 | this.disposed = true; 33 | } 34 | } 35 | 36 | public void Dispose() 37 | { 38 | this.Dispose(true); 39 | GC.SuppressFinalize(this); 40 | } 41 | 42 | #endregion 43 | } 44 | 45 | public class XmlUnmarshallerContext : UnmarshallerContext 46 | { 47 | 48 | #region Constructors 49 | 50 | public XmlUnmarshallerContext(Stream responseStream, IWebResponseData responseData) 51 | { 52 | this.ResponseStream = responseStream; 53 | this.WebResponseData = responseData; 54 | } 55 | 56 | #endregion 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/PublishMessageResponse.cs: -------------------------------------------------------------------------------- 1 | 2 | using Aliyun.MQ.Runtime; 3 | 4 | namespace Aliyun.MQ.Model 5 | { 6 | public partial class PublishMessageResponse : WebServiceResponse 7 | { 8 | private string _messageBodyMD5; 9 | private string _messageId; 10 | private string _receiptHandle; 11 | 12 | public string MessageBodyMD5 13 | { 14 | get { return this._messageBodyMD5; } 15 | set { this._messageBodyMD5 = value; } 16 | } 17 | 18 | // Check to see if BodyMD5 property is set 19 | internal bool IsSetMessageBodyMD5() 20 | { 21 | return this._messageBodyMD5 != null; 22 | } 23 | 24 | public string MessageId 25 | { 26 | get { return this._messageId; } 27 | set { this._messageId = value; } 28 | } 29 | 30 | // Check to see if MessageId property is set 31 | internal bool IsSetMessageId() 32 | { 33 | return this._messageId != null; 34 | } 35 | 36 | public string ReeceiptHandle 37 | { 38 | get { return this._receiptHandle; } 39 | set { this._receiptHandle = value; } 40 | } 41 | 42 | internal bool IsSetReeceiptHandle() 43 | { 44 | return !string.IsNullOrEmpty(_receiptHandle); 45 | } 46 | 47 | public override string ToString() 48 | { 49 | return IsSetReeceiptHandle() 50 | ? string.Format("(MessageId {0}, MessageBodyMD5 {1}, Handle {2})", _messageId, _messageBodyMD5, _receiptHandle) 51 | : string.Format("(MessageId {0}, MessageBodyMD5 {1})", _messageId, _messageBodyMD5); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/XmlUnmarshaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using System.Xml; 5 | using System.Xml.Serialization; 6 | 7 | namespace Aliyun.MQ.Runtime.Internal.Transform 8 | { 9 | internal class XmlUnmarshaller : IUnmarshaller 10 | { 11 | private static readonly XmlSerializer _serializer = new XmlSerializer(typeof(TResponse)); 12 | 13 | public TResponse Unmarshall(Stream responseStream) 14 | { 15 | return this.Unmarshall(responseStream, false); 16 | } 17 | 18 | public TResponse Unmarshall(Stream responseStream, bool keepOpenOnException = false) 19 | { 20 | bool dispose = true; 21 | try 22 | { 23 | return (TResponse)_serializer.Deserialize(responseStream); 24 | } 25 | catch (XmlException ex) 26 | { 27 | if (keepOpenOnException) 28 | { 29 | dispose = false; 30 | } 31 | throw new ResponseUnmarshallException(ex.Message, ex); 32 | } 33 | catch (InvalidOperationException ex) 34 | { 35 | if (keepOpenOnException) 36 | { 37 | dispose = false; 38 | } 39 | throw new ResponseUnmarshallException(ex.Message, ex); 40 | } 41 | finally 42 | { 43 | if (dispose) 44 | { 45 | responseStream.Dispose(); 46 | } 47 | else 48 | { 49 | responseStream.Seek(0, SeekOrigin.Begin); 50 | } 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/AckMessageRequest.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace Aliyun.MQ.Model 8 | { 9 | public partial class AckMessageRequest: WebServiceRequest 10 | { 11 | private string _instanceId; 12 | private string _topicName; 13 | private string _consumer; 14 | private List _receiptHandles = new List(); 15 | private string _trans; 16 | 17 | public AckMessageRequest(string topicName, string consumer, List receiptHandles) 18 | { 19 | this._topicName = topicName; 20 | this._consumer = consumer; 21 | this._receiptHandles = receiptHandles; 22 | } 23 | 24 | public string TopicName 25 | { 26 | get { return this._topicName; } 27 | } 28 | 29 | public string Consumer 30 | { 31 | get { return this._consumer; } 32 | } 33 | 34 | public List ReceiptHandles 35 | { 36 | get { return this._receiptHandles; } 37 | set { this._receiptHandles = value; } 38 | } 39 | 40 | public bool IsSetReceiptHandles() 41 | { 42 | return _receiptHandles.Any(); 43 | } 44 | 45 | public string IntanceId 46 | { 47 | get { return this._instanceId; } 48 | set { this._instanceId = value; } 49 | } 50 | 51 | public bool IsSetInstance() 52 | { 53 | return !string.IsNullOrEmpty(this._instanceId); 54 | } 55 | 56 | internal string Trasaction 57 | { 58 | set { this._trans = value; } 59 | get { return this._trans; } 60 | } 61 | 62 | internal bool IsSetTransaction() 63 | { 64 | return !string.IsNullOrEmpty(this._trans); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/IRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace Aliyun.MQ.Runtime.Internal 6 | { 7 | public interface IRequest 8 | { 9 | string RequestName 10 | { 11 | get; 12 | } 13 | 14 | IDictionary Headers 15 | { 16 | get; 17 | } 18 | 19 | bool UseQueryString 20 | { 21 | get; 22 | set; 23 | } 24 | 25 | IDictionary Parameters 26 | { 27 | get; 28 | } 29 | 30 | IDictionary SubResources 31 | { 32 | get; 33 | } 34 | 35 | void AddSubResource(string subResource); 36 | 37 | void AddSubResource(string subResource, string value); 38 | 39 | string HttpMethod 40 | { 41 | get; 42 | set; 43 | } 44 | 45 | Uri Endpoint 46 | { 47 | get; 48 | set; 49 | } 50 | 51 | string ResourcePath 52 | { 53 | get; 54 | set; 55 | } 56 | 57 | byte[] Content 58 | { 59 | get; 60 | set; 61 | } 62 | 63 | Stream ContentStream 64 | { 65 | get; 66 | set; 67 | } 68 | 69 | long OriginalStreamPosition 70 | { 71 | get; 72 | set; 73 | } 74 | 75 | string ServiceName 76 | { 77 | get; 78 | } 79 | 80 | WebServiceRequest OriginalRequest 81 | { 82 | get; 83 | } 84 | 85 | bool Suppress404Exceptions 86 | { 87 | get; 88 | set; 89 | } 90 | 91 | bool IsRequestStreamRewindable(); 92 | 93 | bool MayContainRequestBody(); 94 | 95 | bool HasRequestBody(); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/exp/AckMessageException.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime; 2 | using System.Collections.Generic; 3 | 4 | namespace Aliyun.MQ.Model.Exp 5 | { 6 | public class AckMessageException : AliyunServiceException 7 | { 8 | private List _errorItems = new List(); 9 | 10 | public AckMessageException() : base(Aliyun.MQ.Model.Exp.ErrorCode.AckMessageFail) 11 | { 12 | this.ErrorCode = Aliyun.MQ.Model.Exp.ErrorCode.AckMessageFail; 13 | } 14 | 15 | public List ErrorItems 16 | { 17 | get { return this._errorItems; } 18 | set { this._errorItems = value; } 19 | } 20 | } 21 | 22 | public class AckMessageErrorItem 23 | { 24 | private string _errorCode; 25 | private string _errorMessage; 26 | private string _receiptHandle; 27 | 28 | public AckMessageErrorItem() 29 | { 30 | } 31 | 32 | public AckMessageErrorItem(string errorCode, string errorMessage, string receiptHandle) 33 | { 34 | this._errorCode = errorCode; 35 | this._errorMessage = errorMessage; 36 | this._receiptHandle = receiptHandle; 37 | } 38 | 39 | public override string ToString() 40 | { 41 | return string.Format("ErrorCode is {0}, ErrorMessage is {1}, ReceiptHandle is {2}", 42 | _errorCode, _errorMessage, _receiptHandle); 43 | } 44 | 45 | public string ErrorCode 46 | { 47 | get { return this._errorCode; } 48 | set { this._errorCode = value; } 49 | } 50 | 51 | public string ErrorMessage 52 | { 53 | get { return this._errorMessage; } 54 | set { this._errorMessage = value; } 55 | } 56 | 57 | public string ReceiptHandle 58 | { 59 | get { return this._receiptHandle; } 60 | set { this._receiptHandle = value; } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/PublishMessageRequest.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using Aliyun.MQ.Runtime.Internal; 4 | 5 | namespace Aliyun.MQ.Model 6 | { 7 | public partial class PublishMessageRequest: WebServiceRequest 8 | { 9 | private string _messageBody; 10 | private string _messageTag; 11 | private string _properties; 12 | private string _topicName; 13 | private string _instanceId; 14 | 15 | public PublishMessageRequest() { } 16 | 17 | public PublishMessageRequest(string messageBody) 18 | : this(messageBody, null) 19 | { 20 | } 21 | 22 | public PublishMessageRequest(string messageBody, string messageTag) 23 | { 24 | _messageBody = messageBody; 25 | _messageTag = messageTag; 26 | } 27 | 28 | public string MessageBody 29 | { 30 | get { return this._messageBody; } 31 | set { this._messageBody = value; } 32 | } 33 | 34 | internal bool IsSetMessageBody() 35 | { 36 | return this._messageBody != null; 37 | } 38 | 39 | public string MessageTag 40 | { 41 | get { return this._messageTag; } 42 | set { this._messageTag = value; } 43 | } 44 | 45 | internal bool IsSetMessageTag() 46 | { 47 | return this._messageTag != null; 48 | } 49 | 50 | public string TopicName 51 | { 52 | get { return this._topicName; } 53 | set { this._topicName = value; } 54 | } 55 | 56 | internal bool IsSetTopicName() 57 | { 58 | return this._topicName != null; 59 | } 60 | 61 | public string IntanceId 62 | { 63 | get { return this._instanceId; } 64 | set { this._instanceId = value; } 65 | } 66 | 67 | public bool IsSetInstance() 68 | { 69 | return !string.IsNullOrEmpty(this._instanceId); 70 | } 71 | 72 | public string Properties 73 | { 74 | get { return this._properties; } 75 | set { this._properties = value; } 76 | } 77 | 78 | public bool IsSetProperties() 79 | { 80 | return !string.IsNullOrEmpty(this._properties); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/ServiceCredentials.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Aliyun.MQ.Runtime 4 | { 5 | public class ImmutableCredentials 6 | { 7 | #region Properties 8 | 9 | public string AccessKey { get; private set; } 10 | 11 | public string SecretKey { get; private set; } 12 | 13 | public string SecurityToken { get; private set;} 14 | 15 | #endregion 16 | 17 | 18 | #region Constructors 19 | 20 | public ImmutableCredentials(string accessKeyId, string secretAccessKey, string stsToken) 21 | { 22 | if (string.IsNullOrEmpty(accessKeyId)) throw new ArgumentNullException("accessKeyId"); 23 | if (string.IsNullOrEmpty(secretAccessKey)) throw new ArgumentNullException("secretAccessKey"); 24 | if (string.IsNullOrEmpty(stsToken)) 25 | { 26 | SecurityToken = null; 27 | } 28 | else { 29 | SecurityToken = stsToken; 30 | } 31 | 32 | 33 | AccessKey = accessKeyId; 34 | SecretKey = secretAccessKey; 35 | } 36 | 37 | private ImmutableCredentials() { } 38 | 39 | #endregion 40 | 41 | 42 | #region Public methods 43 | 44 | public ImmutableCredentials Copy() 45 | { 46 | ImmutableCredentials credentials = new ImmutableCredentials 47 | { 48 | AccessKey = this.AccessKey, 49 | SecretKey = this.SecretKey, 50 | SecurityToken = this.SecurityToken, 51 | }; 52 | return credentials; 53 | } 54 | 55 | #endregion 56 | } 57 | 58 | public abstract class ServiceCredentials 59 | { 60 | public abstract ImmutableCredentials GetCredentials(); 61 | } 62 | 63 | public class BasicServiceCredentials : ServiceCredentials 64 | { 65 | #region Private members 66 | 67 | private ImmutableCredentials _credentials; 68 | 69 | #endregion 70 | 71 | 72 | #region Constructors 73 | 74 | public BasicServiceCredentials(string accessKey, string secretKey, string stsToken) 75 | { 76 | if (!string.IsNullOrEmpty(accessKey)) 77 | { 78 | _credentials = new ImmutableCredentials(accessKey, secretKey, stsToken); 79 | } 80 | } 81 | 82 | #endregion 83 | 84 | 85 | #region Abstract class overrides 86 | 87 | public override ImmutableCredentials GetCredentials() 88 | { 89 | if (this._credentials == null) 90 | return null; 91 | 92 | return _credentials.Copy(); 93 | } 94 | 95 | #endregion 96 | 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Internal/MarshallTransformations/ConsumeMessageRequestMarshaller.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime; 2 | using Aliyun.MQ.Runtime.Internal; 3 | using Aliyun.MQ.Runtime.Internal.Transform; 4 | using Aliyun.MQ.Util; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Text; 9 | 10 | namespace Aliyun.MQ.Model.Internal.MarshallTransformations 11 | { 12 | class ConsumeMessageRequestMarshaller : IMarshaller, IMarshaller 13 | { 14 | public IRequest Marshall(WebServiceRequest input) 15 | { 16 | return this.Marshall((ConsumeMessageRequest)input); 17 | } 18 | 19 | public IRequest Marshall(ConsumeMessageRequest publicRequest) 20 | { 21 | IRequest request = new DefaultRequest(publicRequest, Constants.MQ_SERVICE_NAME); 22 | request.HttpMethod = HttpMethod.GET.ToString(); 23 | request.ResourcePath = Constants.TOPIC_PRE_RESOURCE + publicRequest.TopicName 24 | + Constants.MESSAGE_SUB_RESOURCE; 25 | PopulateSpecialParameters(publicRequest, request.Parameters); 26 | return request; 27 | } 28 | 29 | private static void PopulateSpecialParameters(ConsumeMessageRequest request, IDictionary paramters) 30 | { 31 | paramters.Add(Constants.PARAMETER_CONSUMER, request.Consumer); 32 | if (request.IsSetInstance()) 33 | { 34 | paramters.Add(Constants.PARAMETER_NS, request.IntanceId); 35 | } 36 | if (request.IsSetWaitSeconds() && request.WaitSeconds > 0 && request.WaitSeconds < 31) 37 | { 38 | paramters.Add(Constants.PARAMETER_WAIT_SECONDS, request.WaitSeconds.ToString()); 39 | } 40 | paramters.Add(Constants.PARAMETER_BATCH_SIZE, request.BatchSize.ToString()); 41 | if (request.IsSetMessageTag()) 42 | { 43 | paramters.Add(Constants.PARAMETER_CONSUME_TAG, request.MessageTag); 44 | } 45 | if (request.IsSetTransaction()) 46 | { 47 | paramters.Add(Constants.PARAMETER_TRANSACTION, request.Trasaction); 48 | } 49 | } 50 | 51 | private static ConsumeMessageRequestMarshaller _instance = new ConsumeMessageRequestMarshaller(); 52 | public static ConsumeMessageRequestMarshaller Instance 53 | { 54 | get 55 | { 56 | return _instance; 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/ConsumeMessageRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Aliyun.MQ.Runtime.Internal; 6 | 7 | namespace Aliyun.MQ.Model 8 | { 9 | public partial class ConsumeMessageRequest: WebServiceRequest 10 | { 11 | private string _instanceId; 12 | private string _topicName; 13 | private string _consumer; 14 | private string _messageTag; 15 | private uint _batchSize; 16 | private uint? _waitSeconds; 17 | private string _trans; 18 | 19 | public ConsumeMessageRequest(string topicName, string consumer) 20 | { 21 | this._topicName = topicName; 22 | this._consumer = consumer; 23 | } 24 | 25 | public ConsumeMessageRequest(string topicName, string consumer, string messageTag) 26 | { 27 | this._topicName = topicName; 28 | this._consumer = consumer; 29 | this._messageTag = messageTag; 30 | } 31 | 32 | public string TopicName 33 | { 34 | get { return this._topicName; } 35 | } 36 | 37 | public string Consumer 38 | { 39 | get { return this._consumer; } 40 | } 41 | 42 | public string MessageTag 43 | { 44 | get { return this._messageTag; } 45 | } 46 | 47 | public bool IsSetMessageTag() 48 | { 49 | return this._messageTag != null; 50 | } 51 | 52 | public bool IsSetWaitSeconds() 53 | { 54 | return this._waitSeconds.HasValue; 55 | } 56 | 57 | public uint WaitSeconds 58 | { 59 | get { return this._waitSeconds.GetValueOrDefault(); } 60 | set { this._waitSeconds = value; } 61 | } 62 | 63 | public uint BatchSize 64 | { 65 | get { return this._batchSize; } 66 | set { this._batchSize = value; } 67 | } 68 | 69 | public string IntanceId 70 | { 71 | get { return this._instanceId; } 72 | set { this._instanceId = value; } 73 | } 74 | 75 | public bool IsSetInstance() 76 | { 77 | return !string.IsNullOrEmpty(this._instanceId); 78 | } 79 | 80 | internal string Trasaction 81 | { 82 | set { this._trans = value; } 83 | get { return this._trans; } 84 | } 85 | 86 | internal bool IsSetTransaction() 87 | { 88 | return !string.IsNullOrEmpty(this._trans); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/MQClient.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using Aliyun.MQ.Model.Exp; 4 | using Aliyun.MQ.Runtime; 5 | using Aliyun.MQ.Runtime.Internal.Auth; 6 | 7 | namespace Aliyun.MQ 8 | { 9 | public partial class MQClient : HttpClientBasedAliyunServiceClient 10 | { 11 | #region Constructors 12 | 13 | public MQClient(string accessKeyId, string secretAccessKey, string regionEndpoint, int maxErrorRetry = 3) 14 | : base(accessKeyId, secretAccessKey, new MQConfig { RegionEndpoint = new Uri(regionEndpoint), MaxErrorRetry = maxErrorRetry}, null) 15 | { 16 | } 17 | 18 | public MQClient(string accessKeyId, string secretAccessKey, string regionEndpoint, string stsToken, int maxErrorRetry =3) 19 | : base(accessKeyId, secretAccessKey, new MQConfig { RegionEndpoint = new Uri(regionEndpoint), MaxErrorRetry = maxErrorRetry}, stsToken) 20 | { 21 | } 22 | 23 | #endregion 24 | 25 | #region Overrides 26 | 27 | protected override IServiceSigner CreateSigner() 28 | { 29 | return new MQSigner(); 30 | } 31 | 32 | #endregion 33 | 34 | #region Dispose 35 | 36 | protected override void Dispose(bool disposing) 37 | { 38 | base.Dispose(disposing); 39 | } 40 | 41 | #endregion 42 | 43 | 44 | public MQProducer GetProducer(string instanceId, string topicName) 45 | { 46 | if (string.IsNullOrEmpty(topicName)) { 47 | throw new MQException("TopicName is null or empty"); 48 | } 49 | return new MQProducer(instanceId, topicName, this); 50 | } 51 | 52 | public MQTransProducer GetTransProdcuer(string instanceId, string topicName, string groupId) 53 | { 54 | if (string.IsNullOrEmpty(topicName)) 55 | { 56 | throw new MQException("TopicName is null or empty"); 57 | } 58 | 59 | if (string.IsNullOrEmpty(groupId)) 60 | { 61 | throw new MQException("TopicName is null or empty"); 62 | } 63 | 64 | return new MQTransProducer(instanceId, topicName, groupId, this); 65 | } 66 | 67 | public MQConsumer GetConsumer(string instanceId, string topicName, String consumer, String messageTag) 68 | { 69 | if (string.IsNullOrEmpty(topicName)) 70 | { 71 | throw new MQException("TopicName is null or empty"); 72 | } 73 | if (string.IsNullOrEmpty(consumer)) 74 | { 75 | throw new MQException("Consumer is null or empty"); 76 | } 77 | return new MQConsumer(instanceId, topicName, consumer, messageTag, this); 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/Handlers/Marshaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Globalization; 4 | using Aliyun.MQ.Runtime.Internal; 5 | using Aliyun.MQ.Util; 6 | using Aliyun.MQ.Runtime.Internal.Util; 7 | 8 | namespace Aliyun.MQ.Runtime.Pipeline.Handlers 9 | { 10 | public class Marshaller : GenericHandler 11 | { 12 | protected override void PreInvoke(IExecutionContext executionContext) 13 | { 14 | try 15 | { 16 | 17 | IRequestContext requestContext = executionContext.RequestContext; 18 | requestContext.Request = requestContext.Marshaller.Marshall(requestContext.OriginalRequest); 19 | requestContext.Request.Endpoint = requestContext.ClientConfig.RegionEndpoint; 20 | AddRequiredHeaders(requestContext); 21 | AddOptionalHeaders(requestContext); 22 | } 23 | finally 24 | { 25 | } 26 | } 27 | 28 | private void AddRequiredHeaders(IRequestContext requestContext) 29 | { 30 | IDictionary headers = requestContext.Request.Headers; 31 | headers[Constants.UserAgentHeader] = requestContext.ClientConfig.UserAgent; 32 | if (requestContext.Request.ContentStream != null) 33 | headers[Constants.ContentLengthHeader] = requestContext.Request.ContentStream.Length.ToString(CultureInfo.InvariantCulture); 34 | headers[Constants.DateHeader] = AliyunSDKUtils.FormattedCurrentTimestampRFC822; 35 | headers[Constants.XMQVersionHeader] = requestContext.ClientConfig.ServiceVersion; 36 | if (!headers.ContainsKey(Constants.HostHeader)) 37 | { 38 | Uri requestEndpoint = requestContext.Request.Endpoint; 39 | var hostHeader = requestEndpoint.Host; 40 | if (!requestEndpoint.IsDefaultPort) 41 | hostHeader += ":" + requestEndpoint.Port; 42 | headers.Add(Constants.HostHeader, hostHeader); 43 | } 44 | } 45 | 46 | private void AddOptionalHeaders(IRequestContext requestContext) 47 | { 48 | WebServiceRequest originalRequest = requestContext.Request.OriginalRequest; 49 | IDictionary headers = requestContext.Request.Headers; 50 | if (originalRequest.IsSetContentType()) 51 | headers[Constants.ContentTypeHeader] = originalRequest.ContentType; 52 | else 53 | headers[Constants.ContentTypeHeader] = Constants.ContentTypeTextXml; 54 | if (originalRequest.IsSetContentMD5()) 55 | headers[Constants.ContentMD5Header] = originalRequest.ContentMD5; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Internal/MarshallTransformations/AckMessageRequestMarshaller.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime; 2 | using Aliyun.MQ.Runtime.Internal; 3 | using Aliyun.MQ.Runtime.Internal.Transform; 4 | using Aliyun.MQ.Util; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Text; 8 | using System.Xml; 9 | 10 | namespace Aliyun.MQ.Model.Internal.MarshallTransformations 11 | { 12 | public partial class AckMessageRequestMarshaller : IMarshaller, IMarshaller 13 | { 14 | public IRequest Marshall(WebServiceRequest input) 15 | { 16 | return this.Marshall((AckMessageRequest)input); 17 | } 18 | 19 | public IRequest Marshall(AckMessageRequest publicRequest) 20 | { 21 | MemoryStream stream = new MemoryStream(); 22 | XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8); 23 | writer.WriteStartDocument(); 24 | writer.WriteStartElement(Constants.XML_ROOT_RECEIPT_HANDLES, Constants.MQ_XML_NAMESPACE); 25 | foreach (string receiptHandle in publicRequest.ReceiptHandles) 26 | { 27 | writer.WriteElementString(Constants.XML_ELEMENT_RECEIPT_HANDLE, receiptHandle); 28 | } 29 | writer.WriteEndElement(); 30 | writer.WriteEndDocument(); 31 | writer.Flush(); 32 | stream.Seek(0, SeekOrigin.Begin); 33 | 34 | IRequest request = new DefaultRequest(publicRequest, Constants.MQ_SERVICE_NAME); 35 | request.HttpMethod = HttpMethod.DELETE.ToString(); 36 | request.ContentStream = stream; 37 | request.ResourcePath = Constants.TOPIC_PRE_RESOURCE + publicRequest.TopicName 38 | + Constants.MESSAGE_SUB_RESOURCE; 39 | PopulateSpecialParameters(publicRequest, request.Parameters); 40 | return request; 41 | } 42 | 43 | private static void PopulateSpecialParameters(AckMessageRequest request, IDictionary paramters) 44 | { 45 | paramters.Add(Constants.PARAMETER_CONSUMER, request.Consumer); 46 | if (request.IsSetInstance()) 47 | { 48 | paramters.Add(Constants.PARAMETER_NS, request.IntanceId); 49 | } 50 | if (request.IsSetTransaction()) 51 | { 52 | paramters.Add(Constants.PARAMETER_TRANSACTION, request.Trasaction); 53 | } 54 | } 55 | 56 | private static AckMessageRequestMarshaller _instance = new AckMessageRequestMarshaller(); 57 | public static AckMessageRequestMarshaller Instance 58 | { 59 | get 60 | { 61 | return _instance; 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Internal/MarshallTransformations/PublishMessageRequestMarshaller.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using Aliyun.MQ.Runtime; 3 | using Aliyun.MQ.Runtime.Internal; 4 | using Aliyun.MQ.Runtime.Internal.Transform; 5 | using Aliyun.MQ.Util; 6 | using System.Text; 7 | using System.Xml; 8 | using System.Collections.Generic; 9 | 10 | namespace Aliyun.MQ.Model.Internal.MarshallTransformations 11 | { 12 | /// 13 | /// PublishMessage Request Marshaller 14 | /// 15 | internal class PublishMessageRequestMarshaller : IMarshaller, IMarshaller 16 | { 17 | public IRequest Marshall(WebServiceRequest input) 18 | { 19 | return this.Marshall((PublishMessageRequest)input); 20 | } 21 | 22 | public IRequest Marshall(PublishMessageRequest publicRequest) 23 | { 24 | MemoryStream stream = new MemoryStream(); 25 | XmlTextWriter writer = new XmlTextWriter(stream, Encoding.UTF8); 26 | writer.WriteStartDocument(); 27 | writer.WriteStartElement(Constants.XML_ROOT_MESSAGE, Constants.MQ_XML_NAMESPACE); 28 | if (publicRequest.IsSetMessageBody()) 29 | writer.WriteElementString(Constants.XML_ELEMENT_MESSAGE_BODY, publicRequest.MessageBody); 30 | if (publicRequest.IsSetMessageTag()) 31 | writer.WriteElementString(Constants.XML_ELEMENT_MESSAGE_TAG, publicRequest.MessageTag); 32 | if (publicRequest.IsSetProperties()) 33 | writer.WriteElementString(Constants.XML_ELEMENT_MESSAGE_PROPERTIES, publicRequest.Properties); 34 | writer.WriteEndElement(); 35 | writer.WriteEndDocument(); 36 | writer.Flush(); 37 | 38 | stream.Seek(0, SeekOrigin.Begin); 39 | 40 | IRequest request = new DefaultRequest(publicRequest, Constants.MQ_SERVICE_NAME); 41 | 42 | request.HttpMethod = HttpMethod.POST.ToString(); 43 | request.ContentStream = stream; 44 | request.ResourcePath = Constants.TOPIC_PRE_RESOURCE + publicRequest.TopicName 45 | + Constants.MESSAGE_SUB_RESOURCE; 46 | PopulateSpecialParameters(publicRequest, request.Parameters); 47 | return request; 48 | } 49 | 50 | private static void PopulateSpecialParameters(PublishMessageRequest request, IDictionary paramters) 51 | { 52 | if (request.IsSetInstance()) { 53 | paramters.Add(Constants.PARAMETER_NS, request.IntanceId); 54 | } 55 | } 56 | 57 | private static PublishMessageRequestMarshaller _instance = new PublishMessageRequestMarshaller(); 58 | public static PublishMessageRequestMarshaller Instance 59 | { 60 | get 61 | { 62 | return _instance; 63 | } 64 | } 65 | } 66 | 67 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/AliyunServiceException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | 4 | namespace Aliyun.MQ.Runtime 5 | { 6 | public class AliyunServiceException : Exception 7 | { 8 | private HttpStatusCode statusCode; 9 | private string errorCode; 10 | private string requestId; 11 | private string hostId; 12 | 13 | public AliyunServiceException() 14 | : base() 15 | { 16 | } 17 | 18 | public AliyunServiceException(string message) 19 | : base(message) 20 | { 21 | } 22 | 23 | public AliyunServiceException(string message, Exception innerException) 24 | : base(message, innerException) 25 | { 26 | } 27 | 28 | public AliyunServiceException(string message, Exception innerException, HttpStatusCode statusCode) 29 | : base(message, innerException) 30 | { 31 | this.statusCode = statusCode; 32 | } 33 | 34 | public AliyunServiceException(Exception innerException) 35 | : base(innerException.Message, innerException) 36 | { 37 | } 38 | 39 | public AliyunServiceException(string message, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 40 | : base(message) 41 | { 42 | this.statusCode = statusCode; 43 | this.errorCode = errorCode; 44 | this.requestId = requestId; 45 | this.hostId = hostId; 46 | } 47 | 48 | public AliyunServiceException(string message, Exception innerException, string errorCode, string requestId, string hostId, HttpStatusCode statusCode) 49 | : base(message, innerException) 50 | { 51 | this.statusCode = statusCode; 52 | this.errorCode = errorCode; 53 | this.requestId = requestId; 54 | this.hostId = hostId; 55 | } 56 | 57 | /// 58 | /// The HTTP status code from the service response 59 | /// 60 | public HttpStatusCode StatusCode 61 | { 62 | get { return this.statusCode; } 63 | set { this.statusCode = value; } 64 | } 65 | 66 | /// 67 | /// The error code returned by the service 68 | /// 69 | public string ErrorCode 70 | { 71 | get { return this.errorCode; } 72 | set { this.errorCode = value; } 73 | } 74 | 75 | /// 76 | /// The id of the request which generated the exception. 77 | /// 78 | public string RequestId 79 | { 80 | get { return this.requestId; } 81 | set { this.requestId = value; } 82 | } 83 | 84 | /// 85 | /// The host id of the request which generated the exception. 86 | /// 87 | public string HostId 88 | { 89 | get { return this.hostId; } 90 | set { this.hostId = value; } 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/WebServiceRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Aliyun.MQ.Runtime.Internal 5 | { 6 | public abstract partial class WebServiceRequest 7 | { 8 | readonly IDictionary _parameters = new Dictionary(StringComparer.Ordinal); 9 | readonly IDictionary _headers = new Dictionary(StringComparer.OrdinalIgnoreCase); 10 | private string _contentType; 11 | private string _contentMD5; 12 | 13 | public IDictionary Headers 14 | { 15 | get 16 | { 17 | return this._headers; 18 | } 19 | } 20 | 21 | public void AddHeader(string headerName, string value) 22 | { 23 | Headers.Add(headerName, value); 24 | } 25 | 26 | public IDictionary Parameters 27 | { 28 | get 29 | { 30 | return this._parameters; 31 | } 32 | } 33 | 34 | public void AddParameter(string paramName, string value) 35 | { 36 | Parameters.Add(paramName, value); 37 | } 38 | 39 | public string ContentType 40 | { 41 | get { return this._contentType; } 42 | set { this._contentType = value; } 43 | } 44 | 45 | public bool IsSetContentType() 46 | { 47 | return this._contentType != null; 48 | } 49 | 50 | public string ContentMD5 51 | { 52 | get { return this._contentMD5; } 53 | set { this._contentMD5 = value; } 54 | } 55 | 56 | public bool IsSetContentMD5() 57 | { 58 | return this._contentMD5 != null; 59 | } 60 | 61 | private TimeSpan? _timeoutInternal; 62 | 63 | internal TimeSpan? TimeoutInternal 64 | { 65 | get { return this._timeoutInternal; } 66 | set 67 | { 68 | ClientConfig.ValidateTimeout(value); 69 | this._timeoutInternal = value; 70 | } 71 | } 72 | 73 | private TimeSpan? _readWriteTimeoutInternal; 74 | 75 | internal TimeSpan? ReadWriteTimeoutInternal 76 | { 77 | get { return this._readWriteTimeoutInternal; } 78 | set 79 | { 80 | ClientConfig.ValidateTimeout(value); 81 | this._readWriteTimeoutInternal = value; 82 | } 83 | } 84 | 85 | /// 86 | /// Gets or Sets a value indicating if "Expect: 100-continue" HTTP header will be 87 | /// sent by the client for this request. The default value is false. 88 | /// 89 | protected virtual bool Expect100Continue 90 | { 91 | get { return false; } 92 | } 93 | 94 | internal bool GetExpect100Continue() 95 | { 96 | return this.Expect100Continue; 97 | } 98 | 99 | internal virtual bool KeepAlive 100 | { 101 | get { return true; } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/RuntimeAsyncResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | 4 | namespace Aliyun.MQ.Runtime.Pipeline 5 | { 6 | public class RuntimeAsyncResult : IAsyncResult, IDisposable 7 | { 8 | private object _lockObj; 9 | private ManualResetEvent _waitHandle; 10 | private bool _disposed = false; 11 | private bool _callbackInvoked = false; 12 | 13 | public RuntimeAsyncResult(AsyncCallback asyncCallback, object asyncState) 14 | { 15 | _lockObj = new object(); 16 | _callbackInvoked = false; 17 | 18 | this.AsyncState = asyncState; 19 | this.IsCompleted = false; 20 | this.AsyncCallback = asyncCallback; 21 | this.CompletedSynchronously = false; 22 | } 23 | 24 | public AsyncCallback AsyncCallback { get; private set; } 25 | 26 | public object AsyncState { get; private set; } 27 | 28 | public WaitHandle AsyncWaitHandle 29 | { 30 | get 31 | { 32 | if (this._waitHandle != null) 33 | { 34 | return this._waitHandle; 35 | } 36 | 37 | lock (this._lockObj) 38 | { 39 | if (this._waitHandle == null) 40 | { 41 | this._waitHandle = new ManualResetEvent(this.IsCompleted); 42 | } 43 | } 44 | return this._waitHandle; 45 | } 46 | } 47 | 48 | public bool CompletedSynchronously { get; private set; } 49 | 50 | public bool IsCompleted { get; private set; } 51 | 52 | public Exception Exception { get; set; } 53 | 54 | public WebServiceResponse Response { get; set; } 55 | 56 | internal void SignalWaitHandle() 57 | { 58 | this.IsCompleted = true; 59 | if (this._waitHandle != null) 60 | { 61 | this._waitHandle.Set(); 62 | } 63 | } 64 | 65 | internal void HandleException(Exception exception) 66 | { 67 | this.Exception = exception; 68 | InvokeCallback(); 69 | } 70 | 71 | internal void InvokeCallback() 72 | { 73 | this.SignalWaitHandle(); 74 | if (!_callbackInvoked && this.AsyncCallback != null) 75 | { 76 | _callbackInvoked = true; 77 | this.AsyncCallback(this); 78 | } 79 | } 80 | 81 | #region Dispose Pattern Implementation 82 | 83 | protected virtual void Dispose(bool disposing) 84 | { 85 | if (!this._disposed) 86 | { 87 | if (disposing && _waitHandle != null) 88 | { 89 | #if WIN_RT 90 | _waitHandle.Dispose(); 91 | #else 92 | _waitHandle.Close(); 93 | #endif 94 | _waitHandle = null; 95 | } 96 | this._disposed = true; 97 | } 98 | } 99 | 100 | public void Dispose() 101 | { 102 | this.Dispose(true); 103 | GC.SuppressFinalize(this); 104 | } 105 | 106 | #endregion 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/RetryHandler/RetryPolicy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Aliyun.MQ.Runtime.Internal.Util; 3 | 4 | namespace Aliyun.MQ.Runtime.Pipeline.RetryHandler 5 | { 6 | /// 7 | /// A retry policy specifies all aspects of retry behavior. This includes conditions when the request should be retried, 8 | /// checks of retry limit, preparing the request before retry and introducing delay (backoff) before retries. 9 | /// 10 | public abstract class RetryPolicy 11 | { 12 | /// 13 | /// Maximum number of retries to be performed. 14 | /// This does not count the initial request. 15 | /// 16 | public int MaxRetries { get; protected set; } 17 | 18 | /// 19 | /// Checks if a retry should be performed with the given execution context and exception. 20 | /// 21 | /// The execution context which contains both the 22 | /// requests and response context. 23 | /// The exception throw after issuing the request. 24 | /// Returns true if the request should be retried, else false. 25 | public bool Retry(IExecutionContext executionContext, Exception exception) 26 | { 27 | return !RetryLimitReached(executionContext) && 28 | CanRetry(executionContext) && 29 | RetryForException(executionContext, exception); 30 | } 31 | 32 | /// 33 | /// Returns true if the request is in a state where it can be retried, else false. 34 | /// 35 | /// The execution context which contains both the 36 | /// requests and response context. 37 | /// Returns true if the request is in a state where it can be retried, else false. 38 | public abstract bool CanRetry(IExecutionContext executionContext); 39 | 40 | /// 41 | /// Return true if the request should be retried for the given exception. 42 | /// 43 | /// The execution context which contains both the 44 | /// requests and response context. 45 | /// The exception thrown by the previous request. 46 | /// Return true if the request should be retried. 47 | public abstract bool RetryForException(IExecutionContext executionContext, Exception exception); 48 | 49 | /// 50 | /// Checks if the retry limit is reached. 51 | /// 52 | /// The execution context which contains both the 53 | /// requests and response context. 54 | /// Return false if the request can be retried, based on number of retries. 55 | public abstract bool RetryLimitReached(IExecutionContext executionContext); 56 | 57 | /// 58 | /// Waits before retrying a request. 59 | /// 60 | /// The execution context which contains both the 61 | /// requests and response context. 62 | public abstract void WaitBeforeRetry(IExecutionContext executionContext); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/PipelineHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using Aliyun.MQ.Runtime.Internal; 4 | using Aliyun.MQ.Runtime.Internal.Util; 5 | 6 | namespace Aliyun.MQ.Runtime.Pipeline 7 | { 8 | public abstract partial class PipelineHandler : IPipelineHandler 9 | { 10 | public IPipelineHandler InnerHandler { get; set; } 11 | 12 | public IPipelineHandler OuterHandler { get; set; } 13 | 14 | public virtual void InvokeSync(IExecutionContext executionContext) 15 | { 16 | if (this.InnerHandler != null) 17 | { 18 | InnerHandler.InvokeSync(executionContext); 19 | return; 20 | } 21 | throw new InvalidOperationException("Cannot invoke InnerHandler. InnerHandler is not set."); 22 | } 23 | 24 | public virtual IAsyncResult InvokeAsync(IAsyncExecutionContext executionContext) 25 | { 26 | if (this.InnerHandler != null) 27 | { 28 | return InnerHandler.InvokeAsync(executionContext); 29 | } 30 | throw new InvalidOperationException("Cannot invoke InnerHandler. InnerHandler is not set."); 31 | } 32 | 33 | public virtual Task InvokeAsync(IExecutionContext executionContext) 34 | where T : WebServiceResponse, new() 35 | { 36 | if (this.InnerHandler != null) 37 | { 38 | return InnerHandler.InvokeAsync(executionContext); 39 | } 40 | throw new InvalidOperationException("Cannot invoke InnerHandler. InnerHandler is not set."); 41 | } 42 | 43 | public void AsyncCallback(IAsyncExecutionContext executionContext) 44 | { 45 | try 46 | { 47 | this.InvokeAsyncCallback(executionContext); 48 | } 49 | catch (Exception exception) 50 | { 51 | 52 | // An unhandled exception occured in the callback implementation. 53 | // Capture the exception and end the callback processing by signalling the 54 | // wait handle. 55 | 56 | var asyncResult = executionContext.ResponseContext.AsyncResult; 57 | asyncResult.Exception = exception; 58 | asyncResult.SignalWaitHandle(); 59 | if (asyncResult.AsyncCallback != null) 60 | { 61 | asyncResult.AsyncCallback(asyncResult); 62 | } 63 | } 64 | } 65 | 66 | protected virtual void InvokeAsyncCallback(IAsyncExecutionContext executionContext) 67 | { 68 | if (this.OuterHandler!=null) 69 | { 70 | this.OuterHandler.AsyncCallback(executionContext); 71 | } 72 | else 73 | { 74 | // No more outer handlers to process, signal completion 75 | executionContext.ResponseContext.AsyncResult.Response = 76 | executionContext.ResponseContext.Response; 77 | 78 | var asyncResult = executionContext.ResponseContext.AsyncResult; 79 | asyncResult.SignalWaitHandle(); 80 | if (asyncResult.AsyncCallback != null) 81 | { 82 | asyncResult.AsyncCallback(asyncResult); 83 | } 84 | } 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/IPiplelineHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Aliyun.MQ.Runtime.Internal.Util; 3 | 4 | namespace Aliyun.MQ.Runtime.Pipeline 5 | { 6 | /// 7 | /// Interface for a pipeline handler in a pipeline. 8 | /// 9 | public partial interface IPipelineHandler 10 | { 11 | /// 12 | /// The inner handler which is called after the current 13 | /// handler completes it's processing. 14 | /// 15 | IPipelineHandler InnerHandler { get; set; } 16 | 17 | /// 18 | /// The outer handler which encapsulates the current handler. 19 | /// 20 | IPipelineHandler OuterHandler { get; set; } 21 | 22 | /// 23 | /// Contains the processing logic for a synchronous request invocation. 24 | /// This method should call InnerHandler.InvokeSync to continue processing of the 25 | /// request by the pipeline, unless it's a terminating handler. 26 | /// 27 | /// The execution context which contains both the 28 | /// requests and response context. 29 | void InvokeSync(IExecutionContext executionContext); 30 | 31 | /// 32 | /// Contains the processing logic for an asynchronous request invocation. 33 | /// This method should call InnerHandler.InvokeSync to continue processing of the 34 | /// request by the pipeline, unless it's a terminating handler. 35 | /// 36 | /// The execution context which contains both the 37 | /// requests and response context. 38 | /// IAsyncResult which represent a async operation. 39 | IAsyncResult InvokeAsync(IAsyncExecutionContext executionContext); 40 | 41 | /// 42 | /// This callback method contains the processing logic that should be executed 43 | /// after the underlying asynchronous operation completes. 44 | /// This method is called as part of a callback chain which starts 45 | /// from the InvokeAsyncCallback method of the bottommost handler and then invokes 46 | /// each callback method of the handler above it. 47 | /// This method should call OuterHandler.AsyncCallback to continue processing of the 48 | /// request by the pipeline, unless it's the topmost handler. 49 | /// 50 | /// The execution context, it contains the 51 | /// request and response context. 52 | void AsyncCallback(IAsyncExecutionContext executionContext); 53 | 54 | /// 55 | /// Contains the processing logic for an asynchronous request invocation. 56 | /// This method should call InnerHandler.InvokeSync to continue processing of the 57 | /// request by the pipeline, unless it's a terminating handler. 58 | /// 59 | /// The response type for the current request. 60 | /// The execution context, it contains the 61 | /// request and response context. 62 | /// A task that represents the asynchronous operation. 63 | System.Threading.Tasks.Task InvokeAsync(IExecutionContext executionContext) 64 | where T : WebServiceResponse, new(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Internal/MarshallTransformations/PublishMessageResponseUnmarshaller.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using Aliyun.MQ.Runtime; 4 | using Aliyun.MQ.Runtime.Internal; 5 | using Aliyun.MQ.Runtime.Internal.Transform; 6 | using Aliyun.MQ.Util; 7 | using Aliyun.MQ.Model.Exp; 8 | using System.Xml; 9 | 10 | namespace Aliyun.MQ.Model.Internal.MarshallTransformations 11 | { 12 | internal class PublishMessageResponseUnmarshaller : XmlResponseUnmarshaller 13 | { 14 | public override WebServiceResponse Unmarshall(XmlUnmarshallerContext context) 15 | { 16 | XmlTextReader reader = new XmlTextReader(context.ResponseStream); 17 | PublishMessageResponse response = new PublishMessageResponse(); 18 | 19 | while (reader.Read()) 20 | { 21 | switch (reader.NodeType) 22 | { 23 | case XmlNodeType.Element: 24 | switch (reader.LocalName) 25 | { 26 | case Constants.XML_ELEMENT_MESSAGE_ID: 27 | reader.Read(); 28 | response.MessageId = reader.Value; 29 | break; 30 | case Constants.XML_ELEMENT_MESSAGE_BODY_MD5: 31 | reader.Read(); 32 | response.MessageBodyMD5 = reader.Value; 33 | break; 34 | case Constants.XML_ELEMENT_RECEIPT_HANDLE: 35 | reader.Read(); 36 | response.ReeceiptHandle = reader.Value; 37 | break; 38 | } 39 | break; 40 | } 41 | } 42 | reader.Close(); 43 | return response; 44 | } 45 | 46 | public override AliyunServiceException UnmarshallException(XmlUnmarshallerContext context, Exception innerException, HttpStatusCode statusCode) 47 | { 48 | ErrorResponse errorResponse = ErrorResponseUnmarshaller.Instance.Unmarshall(context); 49 | if (errorResponse.Code != null && errorResponse.Code.Equals(ErrorCode.TopicNotExist)) 50 | { 51 | return new TopicNotExistException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 52 | } 53 | if (errorResponse.Code != null && errorResponse.Code.Equals(ErrorCode.MalformedXML)) 54 | { 55 | return new MalformedXMLException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 56 | } 57 | if (errorResponse.Code != null && errorResponse.Code.Equals(ErrorCode.InvalidArgument)) 58 | { 59 | return new InvalidArgumentException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 60 | } 61 | return new MQException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 62 | } 63 | 64 | private static PublishMessageResponseUnmarshaller _instance = new PublishMessageResponseUnmarshaller(); 65 | public static PublishMessageResponseUnmarshaller Instance 66 | { 67 | get 68 | { 69 | return _instance; 70 | } 71 | } 72 | 73 | } 74 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/ResponseUnmarshallers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net; 3 | using System.IO; 4 | using Aliyun.MQ.Runtime.Internal.Util; 5 | using Aliyun.MQ.Util; 6 | 7 | namespace Aliyun.MQ.Runtime.Internal.Transform 8 | { 9 | public abstract class ResponseUnmarshaller : IResponseUnmarshaller 10 | { 11 | public virtual UnmarshallerContext CreateContext(IWebResponseData response, Stream stream) 12 | { 13 | if (response == null) 14 | { 15 | throw new WebException("The Web Response for a successful request is null!"); 16 | } 17 | 18 | return ConstructUnmarshallerContext(stream, response); 19 | } 20 | 21 | internal virtual bool HasStreamingProperty 22 | { 23 | get { return false; } 24 | } 25 | 26 | #region IResponseUnmarshaller Members 27 | 28 | public virtual AliyunServiceException UnmarshallException(UnmarshallerContext input, Exception innerException, HttpStatusCode statusCode) 29 | { 30 | throw new NotImplementedException(); 31 | } 32 | 33 | #endregion 34 | 35 | public WebServiceResponse UnmarshallResponse(UnmarshallerContext context) 36 | { 37 | var response = this.Unmarshall(context); 38 | response.ContentLength = context.ResponseData.ContentLength; 39 | response.HttpStatusCode = context.ResponseData.StatusCode; 40 | return response; 41 | } 42 | 43 | #region IUnmarshaller Members 44 | 45 | public abstract WebServiceResponse Unmarshall(UnmarshallerContext input); 46 | 47 | #endregion 48 | 49 | protected abstract UnmarshallerContext ConstructUnmarshallerContext(Stream responseStream, IWebResponseData response); 50 | } 51 | 52 | public abstract class XmlResponseUnmarshaller : ResponseUnmarshaller 53 | { 54 | public override WebServiceResponse Unmarshall(UnmarshallerContext input) 55 | { 56 | XmlUnmarshallerContext context = input as XmlUnmarshallerContext; 57 | if (context == null) 58 | throw new InvalidOperationException("Unsupported UnmarshallerContext"); 59 | 60 | WebServiceResponse response = this.Unmarshall(context); 61 | 62 | foreach (var headerName in context.ResponseData.GetHeaderNames()) 63 | response.Headers.Add(headerName, context.ResponseData.GetHeaderValue(headerName)); 64 | 65 | return response; 66 | } 67 | public override AliyunServiceException UnmarshallException(UnmarshallerContext input, Exception innerException, HttpStatusCode statusCode) 68 | { 69 | XmlUnmarshallerContext context = input as XmlUnmarshallerContext; 70 | if (context == null) 71 | throw new InvalidOperationException("Unsupported UnmarshallerContext"); 72 | 73 | return this.UnmarshallException(context, innerException, statusCode); 74 | } 75 | 76 | protected override UnmarshallerContext ConstructUnmarshallerContext(Stream responseStream, IWebResponseData response) 77 | { 78 | return new XmlUnmarshallerContext(responseStream, response); 79 | } 80 | 81 | public abstract WebServiceResponse Unmarshall(XmlUnmarshallerContext input); 82 | 83 | public abstract AliyunServiceException UnmarshallException(XmlUnmarshallerContext input, Exception innerException, HttpStatusCode statusCode); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Util/CryptoUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.IO; 4 | using System.Security.Cryptography; 5 | using System.Text; 6 | using Aliyun.MQ.Runtime; 7 | 8 | namespace Aliyun.MQ.Util 9 | { 10 | public interface ICryptoUtil 11 | { 12 | string HMACSign(string data, string key, SigningAlgorithm algorithmName); 13 | byte[] HMACSignBinary(byte[] data, byte[] key, SigningAlgorithm algorithmName); 14 | 15 | byte[] ComputeMD5Hash(byte[] data); 16 | byte[] ComputeMD5Hash(Stream steam); 17 | } 18 | 19 | public static partial class CryptoUtilFactory 20 | { 21 | static CryptoUtil util = new CryptoUtil(); 22 | 23 | public static ICryptoUtil CryptoInstance 24 | { 25 | get { return util; } 26 | } 27 | 28 | partial class CryptoUtil : ICryptoUtil 29 | { 30 | public string HMACSign(string data, string key, SigningAlgorithm algorithmName) 31 | { 32 | var binaryData = Encoding.UTF8.GetBytes(data); 33 | return HMACSign(binaryData, key, algorithmName); 34 | } 35 | 36 | public string HMACSign(byte[] data, string key, SigningAlgorithm algorithmName) 37 | { 38 | if (String.IsNullOrEmpty(key)) 39 | throw new ArgumentNullException("key", "Please specify a Secret Signing Key."); 40 | 41 | if (data == null || data.Length == 0) 42 | throw new ArgumentNullException("data", "Please specify data to sign."); 43 | 44 | KeyedHashAlgorithm algorithm = KeyedHashAlgorithm.Create(algorithmName.ToString().ToUpper(CultureInfo.InvariantCulture)); 45 | if (null == algorithm) 46 | throw new InvalidOperationException("Please specify a KeyedHashAlgorithm to use."); 47 | 48 | try 49 | { 50 | algorithm.Key = Encoding.UTF8.GetBytes(key); 51 | byte[] bytes = algorithm.ComputeHash(data); 52 | return Convert.ToBase64String(bytes); 53 | } 54 | finally 55 | { 56 | algorithm.Clear(); 57 | } 58 | } 59 | 60 | public byte[] ComputeMD5Hash(byte[] data) 61 | { 62 | byte[] hashed = MD5.Create().ComputeHash(data); 63 | return hashed; 64 | } 65 | 66 | public byte[] ComputeMD5Hash(Stream steam) 67 | { 68 | byte[] hashed = MD5.Create().ComputeHash(steam); 69 | return hashed; 70 | } 71 | 72 | public byte[] HMACSignBinary(byte[] data, byte[] key, SigningAlgorithm algorithmName) 73 | { 74 | if (key == null || key.Length == 0) 75 | throw new ArgumentNullException("key", "Please specify a Secret Signing Key."); 76 | 77 | if (data == null || data.Length == 0) 78 | throw new ArgumentNullException("data", "Please specify data to sign."); 79 | 80 | KeyedHashAlgorithm algorithm = KeyedHashAlgorithm.Create(algorithmName.ToString().ToUpper(CultureInfo.InvariantCulture)); 81 | if (null == algorithm) 82 | throw new InvalidOperationException("Please specify a KeyedHashAlgorithm to use."); 83 | 84 | try 85 | { 86 | algorithm.Key = key; 87 | byte[] bytes = algorithm.ComputeHash(data); 88 | return bytes; 89 | } 90 | finally 91 | { 92 | algorithm.Clear(); 93 | } 94 | } 95 | 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/ErrorHandler/ErrorHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net; 4 | using System.Globalization; 5 | using Aliyun.MQ.Runtime.Internal; 6 | 7 | namespace Aliyun.MQ.Runtime.Pipeline.ErrorHandler 8 | { 9 | public class ErrorHandler : PipelineHandler 10 | { 11 | private IDictionary _exceptionHandlers; 12 | 13 | public IDictionary ExceptionHandlers 14 | { 15 | get 16 | { 17 | return _exceptionHandlers; 18 | } 19 | } 20 | 21 | public ErrorHandler() 22 | { 23 | _exceptionHandlers = new Dictionary 24 | { 25 | {typeof(WebException), new WebExceptionHandler()}, 26 | {typeof(HttpErrorResponseException), new HttpErrorResponseExceptionHandler()} 27 | }; 28 | } 29 | 30 | public override void InvokeSync(IExecutionContext executionContext) 31 | { 32 | try 33 | { 34 | base.InvokeSync(executionContext); 35 | return; 36 | } 37 | catch (Exception exception) 38 | { 39 | DisposeReponse(executionContext.ResponseContext); 40 | bool rethrowOriginalException = ProcessException(executionContext, exception); 41 | if (rethrowOriginalException) 42 | { 43 | throw; 44 | } 45 | } 46 | } 47 | 48 | protected override void InvokeAsyncCallback(IAsyncExecutionContext executionContext) 49 | { 50 | // Unmarshall the response if an exception hasn't occured 51 | var exception = executionContext.ResponseContext.AsyncResult.Exception; 52 | if (exception != null) 53 | { 54 | DisposeReponse(executionContext.ResponseContext); 55 | try 56 | { 57 | bool rethrowOriginalException = ProcessException(ExecutionContext.CreateFromAsyncContext(executionContext), 58 | exception); 59 | if (rethrowOriginalException) 60 | { 61 | executionContext.ResponseContext.AsyncResult.Exception = exception; 62 | } 63 | } 64 | catch (Exception ex) 65 | { 66 | executionContext.ResponseContext.AsyncResult.Exception = ex; 67 | } 68 | } 69 | base.InvokeAsyncCallback(executionContext); 70 | } 71 | 72 | private static void DisposeReponse(IResponseContext responseContext) 73 | { 74 | if (responseContext.HttpResponse != null && 75 | responseContext.HttpResponse.ResponseBody != null) 76 | { 77 | responseContext.HttpResponse.ResponseBody.Dispose(); 78 | } 79 | } 80 | 81 | private bool ProcessException(IExecutionContext executionContext, Exception exception) 82 | { 83 | // Find the matching handler which can process the exception 84 | IExceptionHandler exceptionHandler = null; 85 | 86 | if (this.ExceptionHandlers.TryGetValue(exception.GetType(), out exceptionHandler)) 87 | { 88 | return exceptionHandler.Handle(executionContext, exception); 89 | } 90 | 91 | // No match found, rethrow the original exception. 92 | var message = string.Format(CultureInfo.InvariantCulture, 93 | "An unexpected exception {0} was thrown, caused by {1}", exception.GetType(), exception.Message); 94 | throw new AliyunServiceException(message, exception); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/HttpWebRequestResponseData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | 6 | namespace Aliyun.MQ.Runtime.Internal.Transform 7 | { 8 | public class HttpWebRequestResponseData : IWebResponseData 9 | { 10 | HttpWebResponse _response; 11 | string[] _headerNames; 12 | HashSet _headerNamesSet; 13 | HttpWebResponseBody _responseBody; 14 | 15 | public HttpWebRequestResponseData(HttpWebResponse response) 16 | { 17 | this._response = response; 18 | _responseBody = new HttpWebResponseBody(response); 19 | 20 | this.StatusCode = response.StatusCode; 21 | this.IsSuccessStatusCode = this.StatusCode >= HttpStatusCode.OK && this.StatusCode <= (HttpStatusCode)299; 22 | this.ContentType = response.ContentType; 23 | this.ContentLength = response.ContentLength; 24 | } 25 | 26 | public HttpStatusCode StatusCode { get; private set; } 27 | 28 | public bool IsSuccessStatusCode { get; private set; } 29 | 30 | public string ContentType { get; private set; } 31 | 32 | public long ContentLength { get; private set; } 33 | 34 | public bool IsHeaderPresent(string headerName) 35 | { 36 | if (_headerNamesSet == null) 37 | SetHeaderNames(); 38 | return _headerNamesSet.Contains(headerName); 39 | } 40 | 41 | public string[] GetHeaderNames() 42 | { 43 | if (_headerNames == null) 44 | { 45 | SetHeaderNames(); 46 | } 47 | return _headerNames; 48 | } 49 | 50 | public string GetHeaderValue(string name) 51 | { 52 | return this._response.GetResponseHeader(name); 53 | } 54 | 55 | private void SetHeaderNames() 56 | { 57 | var keys = this._response.Headers.Keys; 58 | _headerNames = new string[keys.Count]; 59 | for (int i = 0; i < keys.Count; i++) 60 | _headerNames[i] = keys[i]; 61 | _headerNamesSet = new HashSet(_headerNames, StringComparer.OrdinalIgnoreCase); 62 | } 63 | 64 | public IHttpResponseBody ResponseBody 65 | { 66 | get { return _responseBody; } 67 | } 68 | } 69 | 70 | public class HttpWebResponseBody : IHttpResponseBody 71 | { 72 | HttpWebResponse _response; 73 | bool _disposed = false; 74 | 75 | public HttpWebResponseBody(HttpWebResponse response) 76 | { 77 | _response = response; 78 | } 79 | 80 | public Stream OpenResponse() 81 | { 82 | if (_disposed) 83 | throw new ObjectDisposedException("HttpWebResponseBody"); 84 | 85 | return _response.GetResponseStream(); 86 | } 87 | 88 | public System.Threading.Tasks.Task OpenResponseAsync() 89 | { 90 | // There is no GetResponseStreamAsync on HttpWebResponse so just 91 | // reuse the sync version. 92 | return System.Threading.Tasks.Task.FromResult(OpenResponse()); 93 | } 94 | 95 | public void Dispose() 96 | { 97 | Dispose(true); 98 | GC.SuppressFinalize(this); 99 | } 100 | 101 | protected virtual void Dispose(bool disposing) 102 | { 103 | if (_disposed) 104 | return; 105 | 106 | if (disposing) 107 | { 108 | if (_response != null) 109 | _response.Close(); 110 | 111 | _disposed = true; 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Util/Constants.cs: -------------------------------------------------------------------------------- 1 | namespace Aliyun.MQ.Util 2 | { 3 | internal static class Constants 4 | { 5 | public const string MQ_SERVICE_NAME = "Aliyun.MQ"; 6 | 7 | public const string MQ_XML_NAMESPACE = "http://mq.aliyuncs.com/doc/v1"; 8 | public const string MQ_AUTHORIZATION_HEADER_PREFIX = "MQ"; 9 | public const string X_MQ_VERSION = "2015-06-06"; 10 | public const string X_MQ_HEADER_PREFIX = "x-mq-"; 11 | 12 | public const string XML_ROOT_ERRORS = "Errors"; 13 | public const string XML_ROOT_ERROR_RESPONSE = "Error"; 14 | public const string XML_ROOT_TOPICS = "Topics"; 15 | public const string XML_ROOT_MESSAGES = "Messages"; 16 | public const string XML_ROOT_MESSAGE = "Message"; 17 | public const string XML_ROOT_RECEIPT_HANDLES = "ReceiptHandles"; 18 | 19 | public const string XML_ELEMENT_CODE = "Code"; 20 | public const string XML_ELEMENT_ERROR_CODE = "ErrorCode"; 21 | public const string XML_ELEMENT_MESSAGE = "Message"; 22 | public const string XML_ELEMENT_ERROR_MESSAGE = "ErrorMessage"; 23 | public const string XML_ELEMENT_REQUEST_ID = "RequestId"; 24 | public const string XML_ELEMENT_HOST_ID = "HostId"; 25 | 26 | public const string XML_ELEMENT_MESSAGE_BODY = "MessageBody"; 27 | public const string XML_ELEMENT_MESSAGE_TAG = "MessageTag"; 28 | public const string XML_ELEMENT_MESSAGE_PROPERTIES = "Properties"; 29 | public const string XML_ELEMENT_MESSAGE_BODY_MD5 = "MessageBodyMD5"; 30 | public const string XML_ELEMENT_MESSAGE_ID = "MessageId"; 31 | public const string XML_ELEMENT_RECEIPT_HANDLE = "ReceiptHandle"; 32 | public const string XML_ELEMENT_PUBLISH_TIME = "PublishTime"; 33 | public const string XML_ELEMENT_NEXT_CONSUME_TIME = "NextConsumeTime"; 34 | public const string XML_ELEMENT_FIRST_CONSUME_TIME = "FirstConsumeTime"; 35 | public const string XML_ELEMENT_CONSUMED_TIMES = "ConsumedTimes"; 36 | 37 | public const string PARAMETER_WAIT_SECONDS = "waitseconds"; 38 | public const string PARAMETER_BATCH_SIZE = "numOfMessages"; 39 | public const string PARAMETER_CONSUMER = "consumer"; 40 | public const string PARAMETER_CONSUME_TAG = "tag"; 41 | public const string PARAMETER_NS = "ns"; 42 | public const string PARAMETER_TRANSACTION = "trans"; 43 | 44 | public const string MESSAGE_SUB_RESOURCE = "/messages"; 45 | public const string TOPIC_PRE_RESOURCE = "topics/"; 46 | 47 | 48 | public const string ContentTypeTextXml = "text/xml"; 49 | public const string ContentRangeHeader = "Content-Range"; 50 | public const string ContentEncodingHeader = "Content-Encoding"; 51 | public const string ContentDispositionHeader = "Content-Disposition"; 52 | public const string Expires = "Expires"; 53 | 54 | public const string ContentTypeHeader = "Content-Type"; 55 | public const string ContentLengthHeader = "Content-Length"; 56 | public const string ContentMD5Header = "Content-MD5"; 57 | public const string AuthorizationHeader = "Authorization"; 58 | public const string SecurityToken = "security-token"; 59 | 60 | 61 | public const string UserAgentHeader = "User-Agent"; 62 | public const string LocationHeader = "Location"; 63 | public const string HostHeader = "Host"; 64 | public const string DateHeader = "Date"; 65 | public const string AcceptHeader = "Accept"; 66 | 67 | public const string XMQVersionHeader = "x-mq-version"; 68 | 69 | public const string MESSAGE_PROPERTIES_TIMER_KEY = "__STARTDELIVERTIME"; 70 | public const string MESSAGE_PROPERTIES_TRANS_CHECK_KEY = "__TransCheckT"; 71 | public const string MESSAGE_PROPERTIES_MSG_KEY = "KEYS"; 72 | public const string MESSAGE_PROPERTIES_SHARDING = "__SHARDINGKEY"; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Internal/MarshallTransformations/ErrorResponseUnmarshaller.cs: -------------------------------------------------------------------------------- 1 | using System.Xml; 2 | using Aliyun.MQ.Runtime.Internal; 3 | using Aliyun.MQ.Runtime.Internal.Transform; 4 | using Aliyun.MQ.Util; 5 | 6 | namespace Aliyun.MQ.Model.Internal.MarshallTransformations 7 | { 8 | /// 9 | /// Response Unmarshaller for all Errors 10 | /// 11 | internal class ErrorResponseUnmarshaller : IUnmarshaller 12 | { 13 | /// 14 | /// Build an ErrorResponse from XML 15 | /// 16 | public ErrorResponse Unmarshall(XmlUnmarshallerContext context) 17 | { 18 | XmlTextReader reader = new XmlTextReader(context.ResponseStream); 19 | 20 | ErrorResponse errorResponse = new ErrorResponse(); 21 | while (reader.Read()) 22 | { 23 | switch (reader.NodeType) 24 | { 25 | case XmlNodeType.Element: 26 | if (reader.LocalName == Constants.XML_ELEMENT_CODE) 27 | { 28 | reader.Read(); 29 | errorResponse.Code = reader.Value; 30 | } 31 | if (reader.LocalName == Constants.XML_ELEMENT_MESSAGE) 32 | { 33 | reader.Read(); 34 | errorResponse.Message = reader.Value; 35 | } 36 | if (reader.LocalName == Constants.XML_ELEMENT_REQUEST_ID) 37 | { 38 | reader.Read(); 39 | errorResponse.RequestId = reader.Value; 40 | } 41 | if (reader.LocalName == Constants.XML_ELEMENT_HOST_ID) 42 | { 43 | reader.Read(); 44 | errorResponse.HostId = reader.Value; 45 | } 46 | break; 47 | } 48 | } 49 | reader.Close(); 50 | return errorResponse; 51 | } 52 | 53 | public ErrorResponse Unmarshall(XmlTextReader reader) 54 | { 55 | ErrorResponse errorResponse = new ErrorResponse(); 56 | do 57 | { 58 | switch (reader.NodeType) 59 | { 60 | case XmlNodeType.Element: 61 | if (reader.LocalName == Constants.XML_ELEMENT_CODE) 62 | { 63 | reader.Read(); 64 | errorResponse.Code = reader.Value; 65 | } 66 | if (reader.LocalName == Constants.XML_ELEMENT_MESSAGE) 67 | { 68 | reader.Read(); 69 | errorResponse.Message = reader.Value; 70 | } 71 | if (reader.LocalName == Constants.XML_ELEMENT_REQUEST_ID) 72 | { 73 | reader.Read(); 74 | errorResponse.RequestId = reader.Value; 75 | } 76 | if (reader.LocalName == Constants.XML_ELEMENT_HOST_ID) 77 | { 78 | reader.Read(); 79 | errorResponse.HostId = reader.Value; 80 | } 81 | break; 82 | } 83 | } while (reader.Read()); 84 | reader.Close(); 85 | return errorResponse; 86 | } 87 | 88 | private static ErrorResponseUnmarshaller _instance = new ErrorResponseUnmarshaller(); 89 | public static ErrorResponseUnmarshaller Instance 90 | { 91 | get 92 | { 93 | return _instance; 94 | } 95 | } 96 | } 97 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/TopicMessage.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using Aliyun.MQ.Util; 5 | 6 | namespace Aliyun.MQ.Model 7 | { 8 | 9 | public partial class TopicMessage 10 | { 11 | private string _id; 12 | private string _bodyMD5; 13 | // only transaction msg have 14 | private string _receiptHandle; 15 | 16 | private string _body; 17 | private string _messageTag; 18 | private IDictionary _properties = new Dictionary(); 19 | 20 | 21 | public TopicMessage(string body) 22 | { 23 | this._body = body; 24 | } 25 | 26 | public TopicMessage(string body, string messageTag) 27 | { 28 | this._body = body; 29 | this._messageTag = messageTag; 30 | } 31 | 32 | 33 | public string Id 34 | { 35 | get { return this._id; } 36 | set { this._id = value; } 37 | } 38 | 39 | // Check to see if Id property is set 40 | internal bool IsSetId() 41 | { 42 | return this._id != null; 43 | } 44 | 45 | public string Body 46 | { 47 | get { return this._body; } 48 | } 49 | 50 | public string MessageTag 51 | { 52 | get { return this._messageTag; } 53 | set { this._messageTag = value; } 54 | } 55 | 56 | public bool IsSetBody() 57 | { 58 | return this._body != null; 59 | } 60 | 61 | public string BodyMD5 62 | { 63 | get { return this._bodyMD5; } 64 | set { this._bodyMD5 = value; } 65 | } 66 | 67 | internal bool IsSetBodyMD5() 68 | { 69 | return this._bodyMD5 != null; 70 | } 71 | 72 | /// 73 | /// 发送事务消息的消息句柄,普通消息为空 74 | /// 75 | /// The receipt handle. 76 | public string ReceiptHandle 77 | { 78 | get { return this._receiptHandle; } 79 | set { this._receiptHandle = value; } 80 | } 81 | 82 | public IDictionary Properties 83 | { 84 | get { return this._properties; } 85 | set { this._properties = value; } 86 | } 87 | 88 | public void PutProperty(string key, string value) 89 | { 90 | this._properties.Add(key, value); 91 | } 92 | 93 | /// 94 | /// 定时消息,单位毫秒(ms),在指定时间戳(当前时间之后)进行投递。如果被设置成当前时间戳之前的某个时刻,消息将立刻投递给消费者 95 | /// 96 | /// Millis. 97 | public long StartDeliverTime 98 | { 99 | set { this._properties.Add(Constants.MESSAGE_PROPERTIES_TIMER_KEY, value.ToString()); } 100 | } 101 | 102 | /// 103 | /// Sets the message key. 104 | /// 105 | /// Key. 106 | public string MessageKey 107 | { 108 | set { this._properties.Add(Constants.MESSAGE_PROPERTIES_MSG_KEY, value); } 109 | } 110 | 111 | /// 112 | /// 在消息属性中添加第一次消息回查的最快时间,单位秒,并且表征这是一条事务消息 113 | /// 114 | /// The trans check immunity time. 115 | public uint TransCheckImmunityTime 116 | { 117 | set { this._properties.Add(Constants.MESSAGE_PROPERTIES_TRANS_CHECK_KEY, value.ToString()); } 118 | } 119 | 120 | /// 121 | /// 分区顺序消息中区分不同分区的关键字段,sharding key 于普通消息的 key 是完全不同的概念。全局顺序消息,该字段可以设置为任意非空字符串。 122 | /// 123 | /// The message's sharding key. 124 | public string ShardingKey 125 | { 126 | set { this._properties.Add(Constants.MESSAGE_PROPERTIES_SHARDING, value); } 127 | } 128 | 129 | internal bool IsSetReeceiptHandle() 130 | { 131 | return !string.IsNullOrEmpty(_receiptHandle); 132 | } 133 | 134 | public override string ToString() 135 | { 136 | return IsSetReeceiptHandle() 137 | ? string.Format("(MessageId {0}, MessageBodyMD5 {1}, Handle {2})", _id, _bodyMD5, _receiptHandle) 138 | : string.Format("(MessageId {0}, MessageBodyMD5 {1})", _id, _bodyMD5); 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Message.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Collections.Generic; 4 | using Aliyun.MQ.Util; 5 | 6 | namespace Aliyun.MQ.Model 7 | { 8 | 9 | public partial class Message 10 | { 11 | private string _id; 12 | private string _receiptHandle; 13 | private string _bodyMD5; 14 | private string _body; 15 | 16 | private string _messageTag; 17 | private long _publishTime; 18 | private long _nextConsumeTime; 19 | private long _firstConsumeTime; 20 | 21 | private uint _consumedTimes; 22 | 23 | private readonly IDictionary _properties = new Dictionary(); 24 | 25 | public Message() { } 26 | 27 | 28 | public string Id 29 | { 30 | get { return this._id; } 31 | set { this._id = value; } 32 | } 33 | 34 | // Check to see if Id property is set 35 | internal bool IsSetId() 36 | { 37 | return this._id != null; 38 | } 39 | 40 | public string ReceiptHandle 41 | { 42 | get { return this._receiptHandle; } 43 | set { this._receiptHandle = value; } 44 | } 45 | 46 | internal bool IsSetReceiptHandle() 47 | { 48 | return this._receiptHandle != null; 49 | } 50 | 51 | public string Body 52 | { 53 | get { return this._body; } 54 | set { this._body = value; } 55 | } 56 | 57 | internal bool IsSetBody() 58 | { 59 | return this._body != null; 60 | } 61 | 62 | public string BodyMD5 63 | { 64 | get { return this._bodyMD5; } 65 | set { this._bodyMD5 = value; } 66 | } 67 | 68 | internal bool IsSetBodyMD5() 69 | { 70 | return this._bodyMD5 != null; 71 | } 72 | 73 | public string MessageTag 74 | { 75 | get { return this._messageTag; } 76 | set { this._messageTag = value; } 77 | } 78 | 79 | public long PublishTime 80 | { 81 | get { return this._publishTime; } 82 | set { this._publishTime = value; } 83 | } 84 | 85 | public long NextConsumeTime 86 | { 87 | get { return this._nextConsumeTime; } 88 | set { this._nextConsumeTime = value; } 89 | } 90 | 91 | /// 92 | /// it's meaningless for orderly consume 93 | /// 94 | public long FirstConsumeTime 95 | { 96 | get { return this._firstConsumeTime; } 97 | set { this._firstConsumeTime = value; } 98 | } 99 | 100 | public uint ConsumedTimes 101 | { 102 | get { return this._consumedTimes; } 103 | set { this._consumedTimes = value; } 104 | } 105 | 106 | public IDictionary Properties 107 | { 108 | get { return this._properties; } 109 | } 110 | 111 | public string GetProperty(string key) 112 | { 113 | return this._properties[key]; 114 | } 115 | 116 | public string MessageKey 117 | { 118 | get { return this._properties[Constants.MESSAGE_PROPERTIES_MSG_KEY]; } 119 | } 120 | 121 | public long StartDeliverTime 122 | { 123 | get 124 | { 125 | return _properties.ContainsKey(Constants.MESSAGE_PROPERTIES_TIMER_KEY) 126 | ? long.Parse(this._properties[Constants.MESSAGE_PROPERTIES_TIMER_KEY]) 127 | : 0; 128 | } 129 | } 130 | 131 | public uint TransCheckImmunityTime 132 | { 133 | get 134 | { 135 | return _properties.ContainsKey(Constants.MESSAGE_PROPERTIES_TRANS_CHECK_KEY) 136 | ? uint.Parse(this._properties[Constants.MESSAGE_PROPERTIES_TRANS_CHECK_KEY]) 137 | : 0; 138 | } 139 | } 140 | 141 | public String ShardingKey 142 | { 143 | get { return this._properties[Constants.MESSAGE_PROPERTIES_SHARDING]; } 144 | } 145 | 146 | public override string ToString() 147 | { 148 | return string.Format( 149 | "ID:{0}, PublishTime:{1}, NextConsumeTime:{2}, ConsumedTimes:{3}, " + 150 | "\nTag:{4}, BodyMD5:{5}, NextConsumeTime:{6}" + 151 | "\nBody:{7}" + 152 | "\nProperties:{8}" + 153 | "\nMessageKey:{9}", 154 | Id, PublishTime, NextConsumeTime, ConsumedTimes, 155 | MessageTag, BodyMD5, NextConsumeTime, Body, AliyunSDKUtils.DictToString(Properties), 156 | MessageKey 157 | ); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/Handlers/Unmarshaller.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal; 2 | using Aliyun.MQ.Runtime.Internal.Transform; 3 | using Aliyun.MQ.Runtime.Internal.Util; 4 | 5 | namespace Aliyun.MQ.Runtime.Pipeline.Handlers 6 | { 7 | public class Unmarshaller : PipelineHandler 8 | { 9 | public override void InvokeSync(IExecutionContext executionContext) 10 | { 11 | base.InvokeSync(executionContext); 12 | 13 | if (executionContext.ResponseContext.HttpResponse.IsSuccessStatusCode) 14 | { 15 | // Unmarshall the http response. 16 | Unmarshall(executionContext); 17 | } 18 | } 19 | 20 | /// 21 | /// Unmarshalls the response returned by the HttpHandler. 22 | /// 23 | /// The response type for the current request. 24 | /// The execution context, it contains the 25 | /// request and response context. 26 | /// A task that represents the asynchronous operation. 27 | public override async System.Threading.Tasks.Task InvokeAsync(IExecutionContext executionContext) 28 | { 29 | await base.InvokeAsync(executionContext).ConfigureAwait(false); 30 | // Unmarshall the response 31 | await UnmarshallAsync(executionContext).ConfigureAwait(false); 32 | return (T)executionContext.ResponseContext.Response; 33 | } 34 | 35 | /// 36 | /// Unmarshalls the HTTP response. 37 | /// 38 | /// 39 | /// The execution context, it contains the request and response context. 40 | /// 41 | private async System.Threading.Tasks.Task UnmarshallAsync(IExecutionContext executionContext) 42 | { 43 | var requestContext = executionContext.RequestContext; 44 | var responseContext = executionContext.ResponseContext; 45 | 46 | { 47 | var unmarshaller = requestContext.Unmarshaller; 48 | try 49 | { 50 | var responseStream = await responseContext.HttpResponse. 51 | ResponseBody.OpenResponseAsync().ConfigureAwait(false); 52 | var context = unmarshaller.CreateContext(responseContext.HttpResponse, responseStream); 53 | 54 | var response = UnmarshallResponse(context, requestContext); 55 | responseContext.Response = response; 56 | } 57 | finally 58 | { 59 | if (!unmarshaller.HasStreamingProperty) 60 | responseContext.HttpResponse.ResponseBody.Dispose(); 61 | } 62 | } 63 | } 64 | 65 | protected override void InvokeAsyncCallback(IAsyncExecutionContext executionContext) 66 | { 67 | // Unmarshall the response if an exception hasn't occured 68 | if (executionContext.ResponseContext.AsyncResult.Exception == null) 69 | { 70 | Unmarshall(ExecutionContext.CreateFromAsyncContext(executionContext)); 71 | } 72 | base.InvokeAsyncCallback(executionContext); 73 | } 74 | 75 | private void Unmarshall(IExecutionContext executionContext) 76 | { 77 | var requestContext = executionContext.RequestContext; 78 | var responseContext = executionContext.ResponseContext; 79 | 80 | try 81 | { 82 | var unmarshaller = requestContext.Unmarshaller; 83 | try 84 | { 85 | var context = unmarshaller.CreateContext(responseContext.HttpResponse, 86 | responseContext.HttpResponse.ResponseBody.OpenResponse()); 87 | 88 | var response = UnmarshallResponse(context, requestContext); 89 | responseContext.Response = response; 90 | } 91 | finally 92 | { 93 | if (!unmarshaller.HasStreamingProperty) 94 | responseContext.HttpResponse.ResponseBody.Dispose(); 95 | } 96 | } 97 | finally 98 | { 99 | } 100 | } 101 | 102 | private WebServiceResponse UnmarshallResponse(UnmarshallerContext context, 103 | IRequestContext requestContext) 104 | { 105 | var unmarshaller = requestContext.Unmarshaller; 106 | WebServiceResponse response = null; 107 | try 108 | { 109 | response = unmarshaller.UnmarshallResponse(context); 110 | } 111 | finally 112 | { 113 | } 114 | 115 | return response; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/RetryHandler/RetryHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Aliyun.MQ.Runtime.Internal; 3 | 4 | namespace Aliyun.MQ.Runtime.Pipeline.RetryHandler 5 | { 6 | /// 7 | /// The retry handler has the generic logic for retrying requests. 8 | /// It uses a retry policy which specifies when 9 | /// a retry should be performed. 10 | /// 11 | public class RetryHandler : PipelineHandler 12 | { 13 | /// 14 | /// The retry policy which specifies when 15 | /// a retry should be performed. 16 | /// 17 | public RetryPolicy RetryPolicy { get; private set; } 18 | 19 | /// 20 | /// Constructor which takes in a retry policy. 21 | /// 22 | /// Retry Policy 23 | public RetryHandler(RetryPolicy retryPolicy) 24 | { 25 | this.RetryPolicy = retryPolicy; 26 | } 27 | 28 | /// 29 | /// Invokes the inner handler and performs a retry, if required as per the 30 | /// retry policy. 31 | /// 32 | /// The execution context which contains both the 33 | /// requests and response context. 34 | public override void InvokeSync(IExecutionContext executionContext) 35 | { 36 | var requestContext = executionContext.RequestContext; 37 | bool shouldRetry = false; 38 | do 39 | { 40 | try 41 | { 42 | base.InvokeSync(executionContext); 43 | try 44 | { 45 | if (requestContext.Request.ContentStream != null) 46 | { 47 | requestContext.Request.ContentStream.Close(); 48 | } 49 | } 50 | catch (Exception) 51 | { 52 | } 53 | return; 54 | } 55 | catch (Exception exception) 56 | { 57 | shouldRetry = this.RetryPolicy.Retry(executionContext, exception); 58 | if (!shouldRetry) 59 | { 60 | throw; 61 | } 62 | else 63 | { 64 | requestContext.Retries++; 65 | } 66 | } 67 | 68 | PrepareForRetry(requestContext); 69 | 70 | try 71 | { 72 | this.RetryPolicy.WaitBeforeRetry(executionContext); 73 | } 74 | finally 75 | { 76 | } 77 | 78 | } while (shouldRetry); 79 | } 80 | 81 | /// 82 | /// Invokes the inner handler and performs a retry, if required as per the 83 | /// retry policy. 84 | /// 85 | /// The execution context which contains both the 86 | /// requests and response context. 87 | protected override void InvokeAsyncCallback(IAsyncExecutionContext executionContext) 88 | { 89 | var requestContext = executionContext.RequestContext; 90 | var responseContext = executionContext.ResponseContext; 91 | var exception = responseContext.AsyncResult.Exception; 92 | 93 | if (exception != null) 94 | { 95 | var syncExecutionContext = ExecutionContext.CreateFromAsyncContext(executionContext); 96 | var shouldRetry = this.RetryPolicy.Retry(syncExecutionContext, exception); 97 | if (shouldRetry) 98 | { 99 | requestContext.Retries++; 100 | 101 | PrepareForRetry(requestContext); 102 | 103 | try 104 | { 105 | this.RetryPolicy.WaitBeforeRetry(syncExecutionContext); 106 | } 107 | finally 108 | { 109 | } 110 | 111 | // Retry by calling InvokeAsync 112 | this.InvokeAsync(executionContext); 113 | return; 114 | } 115 | } 116 | 117 | // Call outer handler 118 | base.InvokeAsyncCallback(executionContext); 119 | } 120 | 121 | /// 122 | /// Prepares the request for retry. 123 | /// 124 | /// Request context containing the state of the request. 125 | internal static void PrepareForRetry(IRequestContext requestContext) 126 | { 127 | if (requestContext.Request.ContentStream != null && 128 | requestContext.Request.OriginalStreamPosition >= 0) 129 | { 130 | var stream = requestContext.Request.ContentStream; 131 | stream.Position = requestContext.Request.OriginalStreamPosition; 132 | } 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/Contexts.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal; 2 | using Aliyun.MQ.Runtime.Internal.Auth; 3 | using Aliyun.MQ.Runtime.Internal.Transform; 4 | using System; 5 | using Aliyun.MQ.Runtime.Pipeline; 6 | 7 | namespace Aliyun.MQ.Runtime.Pipeline 8 | { 9 | public interface IRequestContext 10 | { 11 | WebServiceRequest OriginalRequest { get; } 12 | string RequestName { get; } 13 | IMarshaller Marshaller { get; } 14 | ResponseUnmarshaller Unmarshaller { get; } 15 | IServiceSigner Signer { get; } 16 | ClientConfig ClientConfig { get; } 17 | ImmutableCredentials ImmutableCredentials { get; set; } 18 | 19 | System.Threading.CancellationToken CancellationToken { get; } 20 | 21 | IRequest Request { get; set; } 22 | bool IsSigned { get; set; } 23 | bool IsAsync { get; } 24 | int Retries { get; set; } 25 | } 26 | 27 | public interface IResponseContext 28 | { 29 | WebServiceResponse Response { get; set; } 30 | IWebResponseData HttpResponse { get; set; } 31 | } 32 | 33 | public interface IAsyncRequestContext : IRequestContext 34 | { 35 | AsyncCallback Callback { get; } 36 | object State { get; } 37 | } 38 | 39 | public interface IAsyncResponseContext : IResponseContext 40 | { 41 | RuntimeAsyncResult AsyncResult { get; set; } 42 | } 43 | 44 | public interface IExecutionContext 45 | { 46 | IResponseContext ResponseContext { get; } 47 | IRequestContext RequestContext { get; } 48 | } 49 | 50 | public interface IAsyncExecutionContext 51 | { 52 | IAsyncResponseContext ResponseContext { get; } 53 | IAsyncRequestContext RequestContext { get; } 54 | 55 | object RuntimeState { get; set; } 56 | } 57 | } 58 | 59 | namespace Aliyun.MQ.Runtime.Internal 60 | { 61 | public class RequestContext : IRequestContext 62 | { 63 | public RequestContext() 64 | { 65 | } 66 | 67 | public IRequest Request { get; set; } 68 | public IServiceSigner Signer { get; set; } 69 | public ClientConfig ClientConfig { get; set; } 70 | public int Retries { get; set; } 71 | public bool IsSigned { get; set; } 72 | public bool IsAsync { get; set; } 73 | 74 | public System.Threading.CancellationToken CancellationToken { get; set; } 75 | public WebServiceRequest OriginalRequest { get; set; } 76 | public IMarshaller Marshaller { get; set; } 77 | public ResponseUnmarshaller Unmarshaller { get; set; } 78 | public ImmutableCredentials ImmutableCredentials { get; set; } 79 | 80 | public string RequestName 81 | { 82 | get { return this.OriginalRequest.GetType().Name; } 83 | } 84 | } 85 | 86 | public class AsyncRequestContext : RequestContext, IAsyncRequestContext 87 | { 88 | public AsyncRequestContext(): 89 | base() 90 | { 91 | } 92 | 93 | public AsyncCallback Callback { get; set; } 94 | public object State { get; set; } 95 | } 96 | 97 | public class ResponseContext : IResponseContext 98 | { 99 | public WebServiceResponse Response { get; set; } 100 | public IWebResponseData HttpResponse { get; set; } 101 | } 102 | 103 | public class AsyncResponseContext : ResponseContext, IAsyncResponseContext 104 | { 105 | public RuntimeAsyncResult AsyncResult { get; set; } 106 | } 107 | 108 | public class ExecutionContext : IExecutionContext 109 | { 110 | public IRequestContext RequestContext { get; private set; } 111 | public IResponseContext ResponseContext { get; private set; } 112 | 113 | public ExecutionContext() 114 | { 115 | this.RequestContext = new RequestContext(); 116 | this.ResponseContext = new ResponseContext(); 117 | } 118 | 119 | public ExecutionContext(IRequestContext requestContext, IResponseContext responseContext) 120 | { 121 | this.RequestContext = requestContext; 122 | this.ResponseContext = responseContext; 123 | } 124 | 125 | public static IExecutionContext CreateFromAsyncContext(IAsyncExecutionContext asyncContext) 126 | { 127 | return new ExecutionContext(asyncContext.RequestContext, 128 | asyncContext.ResponseContext); 129 | } 130 | } 131 | 132 | public class AsyncExecutionContext : IAsyncExecutionContext 133 | { 134 | public IAsyncResponseContext ResponseContext { get; private set; } 135 | public IAsyncRequestContext RequestContext { get; private set; } 136 | 137 | public object RuntimeState { get; set; } 138 | 139 | public AsyncExecutionContext() 140 | { 141 | this.RequestContext = new AsyncRequestContext(); 142 | this.ResponseContext = new AsyncResponseContext(); 143 | } 144 | 145 | public AsyncExecutionContext(IAsyncRequestContext requestContext, IAsyncResponseContext responseContext) 146 | { 147 | this.RequestContext = requestContext; 148 | this.ResponseContext = responseContext; 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/HttpClientBasedAliyunServiceClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Threading; 7 | using Aliyun.MQ.Runtime.Internal; 8 | using Aliyun.MQ.Runtime.Internal.Auth; 9 | using Aliyun.MQ.Runtime.Internal.Transform; 10 | using Aliyun.MQ.Runtime.Pipeline; 11 | using Aliyun.MQ.Runtime.Pipeline.ErrorHandler; 12 | using Aliyun.MQ.Runtime.Pipeline.Handlers; 13 | using Aliyun.MQ.Runtime.Pipeline.HttpHandler; 14 | using Aliyun.MQ.Runtime.Pipeline.RetryHandler; 15 | using ExecutionContext = Aliyun.MQ.Runtime.Internal.ExecutionContext; 16 | 17 | namespace Aliyun.MQ.Runtime 18 | { 19 | public abstract class HttpClientBasedAliyunServiceClient : IDisposable 20 | { 21 | private bool _disposed; 22 | 23 | protected RuntimePipeline RuntimePipeline { get; set; } 24 | protected ServiceCredentials Credentials { get; private set; } 25 | internal ClientConfig Config { get; private set; } 26 | 27 | internal HttpClientBasedAliyunServiceClient(ServiceCredentials credentials, ClientConfig config) 28 | { 29 | ServicePointManager.Expect100Continue = true; 30 | ServicePointManager.DefaultConnectionLimit = config.ConnectionLimit; 31 | ServicePointManager.MaxServicePointIdleTime = config.MaxIdleTime; 32 | 33 | this.Config = config; 34 | this.Credentials = credentials; 35 | Signer = CreateSigner(); 36 | 37 | Initialize(); 38 | 39 | BuildRuntimePipeline(); 40 | } 41 | 42 | protected IServiceSigner Signer { get; private set; } 43 | 44 | protected virtual void Initialize() 45 | { 46 | } 47 | 48 | protected virtual void CustomizeRuntimePipeline(RuntimePipeline pipeline) 49 | { 50 | } 51 | 52 | private void BuildRuntimePipeline() 53 | { 54 | // Replace HttpWebRequestFactory by HttpRequestMessageFactory 55 | var httpRequestFactory = new HttpRequestMessageFactory(Config); 56 | var httpHandler = new HttpHandler(httpRequestFactory, this); 57 | 58 | this.RuntimePipeline = new RuntimePipeline(new List 59 | { 60 | httpHandler, 61 | new Unmarshaller(), 62 | new ErrorHandler(), 63 | new Signer(), 64 | new CredentialsRetriever(this.Credentials), 65 | new RetryHandler(new DefaultRetryPolicy(this.Config.MaxErrorRetry)), 66 | new Marshaller() 67 | } 68 | ); 69 | 70 | CustomizeRuntimePipeline(this.RuntimePipeline); 71 | } 72 | 73 | internal HttpClientBasedAliyunServiceClient(string accessKeyId, string secretAccessKey, ClientConfig config, 74 | string stsToken) 75 | : this(new BasicServiceCredentials(accessKeyId, secretAccessKey, stsToken), config) 76 | { 77 | } 78 | 79 | 80 | public void Dispose() 81 | { 82 | Dispose(true); 83 | GC.SuppressFinalize(this); 84 | } 85 | 86 | protected abstract IServiceSigner CreateSigner(); 87 | 88 | protected virtual void Dispose(bool disposing) 89 | { 90 | return; 91 | } 92 | 93 | private void ThrowIfDisposed() 94 | { 95 | if (this._disposed) 96 | throw new ObjectDisposedException(GetType().FullName); 97 | } 98 | 99 | internal TResponse Invoke(TRequest request, 100 | IMarshaller marshaller, ResponseUnmarshaller unmarshaller) 101 | where TRequest : WebServiceRequest 102 | where TResponse : WebServiceResponse 103 | { 104 | ThrowIfDisposed(); 105 | 106 | var executionContext = new ExecutionContext( 107 | new RequestContext() 108 | { 109 | ClientConfig = this.Config, 110 | Marshaller = marshaller, 111 | OriginalRequest = request, 112 | Signer = Signer, 113 | Unmarshaller = unmarshaller, 114 | IsAsync = false 115 | }, 116 | new ResponseContext() 117 | ); 118 | 119 | var response = (TResponse)this.RuntimePipeline.InvokeSync(executionContext).Response; 120 | return response; 121 | } 122 | 123 | internal System.Threading.Tasks.Task InvokeAsync( 124 | TRequest request, 125 | IMarshaller marshaller, 126 | ResponseUnmarshaller unmarshaller, 127 | System.Threading.CancellationToken cancellationToken) 128 | where TRequest : WebServiceRequest 129 | where TResponse : WebServiceResponse, new() 130 | { 131 | var executionContext = new ExecutionContext( 132 | new RequestContext() 133 | { 134 | ClientConfig = this.Config, 135 | Marshaller = marshaller, 136 | OriginalRequest = request, 137 | Unmarshaller = unmarshaller, 138 | IsAsync = true, 139 | CancellationToken = cancellationToken, 140 | Signer = Signer, 141 | }, 142 | new ResponseContext() 143 | ); 144 | return this.RuntimePipeline.InvokeAsync(executionContext); 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Internal/MarshallTransformations/AckMessageResponseUnmarshaller.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime; 2 | using Aliyun.MQ.Runtime.Internal; 3 | using Aliyun.MQ.Runtime.Internal.Transform; 4 | using Aliyun.MQ.Util; 5 | using Aliyun.MQ.Model.Exp; 6 | using System; 7 | using System.Net; 8 | using System.Xml; 9 | 10 | namespace Aliyun.MQ.Model.Internal.MarshallTransformations 11 | { 12 | public class AckMessageResponseUnmarshaller : XmlResponseUnmarshaller 13 | { 14 | public override WebServiceResponse Unmarshall(XmlUnmarshallerContext context) 15 | { 16 | return new AckMessageResponse(); 17 | } 18 | 19 | public override AliyunServiceException UnmarshallException(XmlUnmarshallerContext context, Exception innerException, HttpStatusCode statusCode) 20 | { 21 | XmlTextReader reader = new XmlTextReader(context.ResponseStream); 22 | 23 | ErrorResponse errorResponse = new ErrorResponse(); 24 | while (reader.Read()) 25 | { 26 | switch (reader.NodeType) 27 | { 28 | case XmlNodeType.Element: 29 | if (reader.LocalName == Constants.XML_ROOT_ERROR_RESPONSE) 30 | { 31 | return UnmarshallNormalError(reader, innerException, statusCode); 32 | } 33 | else 34 | { 35 | AckMessageException ackMessageException = UnmarshallAckMessageError(reader); 36 | ackMessageException.RequestId = context.ResponseData.GetHeaderValue("x-mq-request-id"); 37 | return ackMessageException; 38 | } 39 | } 40 | } 41 | return new MQException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 42 | } 43 | 44 | private AckMessageException UnmarshallAckMessageError(XmlTextReader reader) 45 | { 46 | AckMessageException ackMessageException = new AckMessageException(); 47 | AckMessageErrorItem item = null; 48 | 49 | while (reader.Read()) 50 | { 51 | switch (reader.NodeType) 52 | { 53 | case XmlNodeType.Element: 54 | switch (reader.LocalName) 55 | { 56 | case Constants.XML_ROOT_ERROR_RESPONSE: 57 | item = new AckMessageErrorItem(); 58 | break; 59 | case Constants.XML_ELEMENT_ERROR_CODE: 60 | reader.Read(); 61 | item.ErrorCode = reader.Value; 62 | break; 63 | case Constants.XML_ELEMENT_ERROR_MESSAGE: 64 | reader.Read(); 65 | item.ErrorMessage = reader.Value; 66 | break; 67 | case Constants.XML_ELEMENT_RECEIPT_HANDLE: 68 | reader.Read(); 69 | item.ReceiptHandle = reader.Value; 70 | break; 71 | } 72 | break; 73 | case XmlNodeType.EndElement: 74 | if (reader.LocalName == Constants.XML_ROOT_ERROR_RESPONSE) 75 | { 76 | ackMessageException.ErrorItems.Add(item); 77 | } 78 | break; 79 | } 80 | } 81 | reader.Close(); 82 | return ackMessageException; 83 | } 84 | 85 | private AliyunServiceException UnmarshallNormalError(XmlTextReader reader, Exception innerException, HttpStatusCode statusCode) 86 | { 87 | ErrorResponse errorResponse = ErrorResponseUnmarshaller.Instance.Unmarshall(reader); 88 | if (errorResponse.Code != null) 89 | { 90 | switch (errorResponse.Code) 91 | { 92 | case ErrorCode.SubscriptionNotExist: 93 | return new SubscriptionNotExistException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 94 | case ErrorCode.TopicNotExist: 95 | return new TopicNotExistException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 96 | case ErrorCode.InvalidArgument: 97 | return new InvalidArgumentException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 98 | case ErrorCode.ReceiptHandleError: 99 | return new ReceiptHandleErrorException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 100 | } 101 | } 102 | return new MQException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 103 | } 104 | 105 | private static AckMessageResponseUnmarshaller _instance = new AckMessageResponseUnmarshaller(); 106 | public static AckMessageResponseUnmarshaller Instance 107 | { 108 | get 109 | { 110 | return _instance; 111 | } 112 | } 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Transform/HttpClientResponseData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Net; 6 | using System.Net.Http; 7 | using System.Net.Http.Headers; 8 | using System.Threading.Tasks; 9 | 10 | namespace Aliyun.MQ.Runtime.Internal.Transform 11 | { 12 | public class HttpClientResponseData : IWebResponseData 13 | { 14 | HttpResponseMessageBody _response; 15 | string[] _headerNames; 16 | Dictionary _headers; 17 | HashSet _headerNamesSet; 18 | 19 | internal HttpClientResponseData(HttpResponseMessage response) 20 | : this(response, null, false) 21 | { 22 | } 23 | 24 | internal HttpClientResponseData(HttpResponseMessage response, HttpClient httpClient, bool disposeClient) 25 | { 26 | _response = new HttpResponseMessageBody(response, httpClient, disposeClient); 27 | 28 | this.StatusCode = response.StatusCode; 29 | this.IsSuccessStatusCode = response.IsSuccessStatusCode; 30 | this.ContentLength = response.Content.Headers.ContentLength ?? 0; 31 | 32 | if (response.Content.Headers.ContentType != null) 33 | { 34 | this.ContentType = response.Content.Headers.ContentType.MediaType; 35 | } 36 | CopyHeaderValues(response); 37 | } 38 | 39 | public HttpStatusCode StatusCode { get; private set; } 40 | 41 | public bool IsSuccessStatusCode { get; private set; } 42 | 43 | public string ContentType { get; private set; } 44 | 45 | public long ContentLength { get; private set; } 46 | 47 | public string GetHeaderValue(string headerName) 48 | { 49 | string headerValue; 50 | if(_headers.TryGetValue(headerName, out headerValue)) 51 | return headerValue; 52 | 53 | return string.Empty; 54 | } 55 | 56 | public bool IsHeaderPresent(string headerName) 57 | { 58 | return _headerNamesSet.Contains(headerName); 59 | } 60 | 61 | public string[] GetHeaderNames() 62 | { 63 | return _headerNames; 64 | } 65 | 66 | private void CopyHeaderValues(HttpResponseMessage response) 67 | { 68 | List headerNames = new List(); 69 | _headers = new Dictionary(10, StringComparer.OrdinalIgnoreCase); 70 | 71 | foreach (KeyValuePair> kvp in response.Headers) 72 | { 73 | headerNames.Add(kvp.Key); 74 | var headerValue = GetFirstHeaderValue(response.Headers, kvp.Key); 75 | _headers.Add(kvp.Key, headerValue); 76 | } 77 | 78 | if (response.Content != null) 79 | { 80 | foreach (var kvp in response.Content.Headers) 81 | { 82 | if (!headerNames.Contains(kvp.Key)) 83 | { 84 | headerNames.Add(kvp.Key); 85 | var headerValue = GetFirstHeaderValue(response.Content.Headers, kvp.Key); 86 | _headers.Add(kvp.Key, headerValue); 87 | } 88 | } 89 | } 90 | _headerNames = headerNames.ToArray(); 91 | _headerNamesSet = new HashSet(_headerNames, StringComparer.OrdinalIgnoreCase); 92 | } 93 | 94 | private string GetFirstHeaderValue(HttpHeaders headers, string key) 95 | { 96 | IEnumerable headerValues = null; 97 | if (headers.TryGetValues(key, out headerValues)) 98 | return headerValues.FirstOrDefault(); 99 | 100 | return string.Empty; 101 | } 102 | 103 | public IHttpResponseBody ResponseBody 104 | { 105 | get { return _response; } 106 | } 107 | } 108 | 109 | [CLSCompliant(false)] 110 | public class HttpResponseMessageBody : IHttpResponseBody 111 | { 112 | HttpClient _httpClient; 113 | HttpResponseMessage _response; 114 | bool _disposeClient = false; 115 | bool _disposed = false; 116 | 117 | public HttpResponseMessageBody(HttpResponseMessage response, HttpClient httpClient, bool disposeClient) 118 | { 119 | _httpClient = httpClient; 120 | _response = response; 121 | _disposeClient = disposeClient; 122 | } 123 | 124 | public Stream OpenResponse() 125 | { 126 | if (_disposed) 127 | throw new ObjectDisposedException("HttpWebResponseBody"); 128 | 129 | return _response.Content.ReadAsStreamAsync().Result; 130 | } 131 | 132 | public Task OpenResponseAsync() 133 | { 134 | if (_disposed) 135 | throw new ObjectDisposedException("HttpWebResponseBody"); 136 | 137 | return _response.Content.ReadAsStreamAsync(); 138 | } 139 | 140 | public void Dispose() 141 | { 142 | Dispose(true); 143 | GC.SuppressFinalize(this); 144 | } 145 | 146 | protected virtual void Dispose(bool disposing) 147 | { 148 | if (_disposed) 149 | return; 150 | 151 | if (disposing) 152 | { 153 | if (_response != null) 154 | _response.Dispose(); 155 | 156 | if (_httpClient != null && _disposeClient) 157 | _httpClient.Dispose(); 158 | 159 | _disposed = true; 160 | } 161 | } 162 | 163 | 164 | } 165 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Model/Internal/MarshallTransformations/ConsumeMessageResponseUnmarshaller.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal.Transform; 2 | using System; 3 | using Aliyun.MQ.Runtime; 4 | using System.Net; 5 | using Aliyun.MQ.Util; 6 | using Aliyun.MQ.Runtime.Internal; 7 | using Aliyun.MQ.Model.Exp; 8 | 9 | namespace Aliyun.MQ.Model.Internal.MarshallTransformations 10 | { 11 | class ConsumeMessageResponseUnmarshaller : XmlResponseUnmarshaller 12 | { 13 | public override WebServiceResponse Unmarshall(XmlUnmarshallerContext context) 14 | { 15 | System.Xml.XmlTextReader reader = new System.Xml.XmlTextReader(context.ResponseStream); 16 | ConsumeMessageResponse consumeMessageResponse = new ConsumeMessageResponse(); 17 | Message message = null; 18 | 19 | while (reader.Read()) 20 | { 21 | switch (reader.NodeType) 22 | { 23 | case System.Xml.XmlNodeType.Element: 24 | switch (reader.LocalName) 25 | { 26 | case Constants.XML_ROOT_MESSAGE: 27 | message = new Message(); 28 | break; 29 | case Constants.XML_ELEMENT_MESSAGE_ID: 30 | reader.Read(); 31 | message.Id = reader.Value; 32 | break; 33 | case Constants.XML_ELEMENT_RECEIPT_HANDLE: 34 | reader.Read(); 35 | message.ReceiptHandle = reader.Value; 36 | break; 37 | case Constants.XML_ELEMENT_MESSAGE_BODY_MD5: 38 | reader.Read(); 39 | message.BodyMD5 = reader.Value; 40 | break; 41 | case Constants.XML_ELEMENT_MESSAGE_BODY: 42 | reader.Read(); 43 | message.Body = reader.Value; 44 | break; 45 | case Constants.XML_ELEMENT_PUBLISH_TIME: 46 | reader.Read(); 47 | message.PublishTime = long.Parse(reader.Value); 48 | break; 49 | case Constants.XML_ELEMENT_NEXT_CONSUME_TIME: 50 | reader.Read(); 51 | message.NextConsumeTime = long.Parse(reader.Value); 52 | break; 53 | case Constants.XML_ELEMENT_FIRST_CONSUME_TIME: 54 | reader.Read(); 55 | message.FirstConsumeTime = long.Parse(reader.Value); 56 | break; 57 | case Constants.XML_ELEMENT_CONSUMED_TIMES: 58 | reader.Read(); 59 | message.ConsumedTimes = uint.Parse(reader.Value); 60 | break; 61 | case Constants.XML_ELEMENT_MESSAGE_TAG: 62 | reader.Read(); 63 | message.MessageTag = reader.Value; 64 | break; 65 | case Constants.XML_ELEMENT_MESSAGE_PROPERTIES: 66 | reader.Read(); 67 | AliyunSDKUtils.StringToDict(reader.Value, message.Properties); 68 | break; 69 | } 70 | break; 71 | case System.Xml.XmlNodeType.EndElement: 72 | if (reader.LocalName == Constants.XML_ROOT_MESSAGE) 73 | { 74 | consumeMessageResponse.Messages.Add(message); 75 | } 76 | break; 77 | } 78 | } 79 | reader.Close(); 80 | return consumeMessageResponse; 81 | } 82 | 83 | public override AliyunServiceException UnmarshallException(XmlUnmarshallerContext context, Exception innerException, HttpStatusCode statusCode) 84 | { 85 | ErrorResponse errorResponse = ErrorResponseUnmarshaller.Instance.Unmarshall(context); 86 | if (errorResponse.Code != null && errorResponse.Code.Equals(ErrorCode.TopicNotExist)) 87 | { 88 | return new TopicNotExistException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 89 | } 90 | if (errorResponse.Code != null && errorResponse.Code.Equals(ErrorCode.SubscriptionNotExist)) 91 | { 92 | return new SubscriptionNotExistException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 93 | } 94 | if (errorResponse.Code != null && errorResponse.Code.Equals(ErrorCode.MessageNotExist)) 95 | { 96 | return new MessageNotExistException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 97 | } 98 | return new MQException(errorResponse.Message, innerException, errorResponse.Code, errorResponse.RequestId, errorResponse.HostId, statusCode); 99 | } 100 | 101 | private static ConsumeMessageResponseUnmarshaller _instance = new ConsumeMessageResponseUnmarshaller(); 102 | public static ConsumeMessageResponseUnmarshaller Instance 103 | { 104 | get 105 | { 106 | return _instance; 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/HttpHandler/IHttpRequestFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using Aliyun.MQ.Runtime.Internal.Transform; 5 | 6 | namespace Aliyun.MQ.Runtime.Pipeline.HttpHandler 7 | { 8 | /// 9 | /// The interface for a HTTP request factory. 10 | /// 11 | /// The type used by the underlying HTTP API to represent the request body. 12 | public interface IHttpRequestFactory : IDisposable 13 | { 14 | /// 15 | /// Creates an HTTP request for the given URI. 16 | /// 17 | /// The request URI. 18 | /// An HTTP request. 19 | IHttpRequest CreateHttpRequest(Uri requestUri); 20 | } 21 | 22 | /// 23 | /// The interface for an HTTP request that is agnostic of the underlying HTTP API. 24 | /// 25 | /// The type used by the underlying HTTP API to represent the HTTP request content. 26 | public interface IHttpRequest : IDisposable 27 | { 28 | /// 29 | /// The HTTP method or verb. 30 | /// 31 | string Method { get; set; } 32 | 33 | /// 34 | /// The request URI. 35 | /// 36 | Uri RequestUri { get; } 37 | 38 | /// 39 | /// Configures a request as per the request context. 40 | /// 41 | /// The request context. 42 | void ConfigureRequest(IRequestContext requestContext); 43 | 44 | /// 45 | /// Sets the headers on the request. 46 | /// 47 | /// A dictionary of header names and values. 48 | void SetRequestHeaders(IDictionary headers); 49 | 50 | /// 51 | /// Gets a handle to the request content. 52 | /// 53 | /// The request content. 54 | TRequestContent GetRequestContent(); 55 | 56 | /// 57 | /// Returns the HTTP response. 58 | /// 59 | /// The HTTP response. 60 | IWebResponseData GetResponse(); 61 | 62 | /// 63 | /// Writes a stream to the request body. 64 | /// 65 | /// The destination where the content stream is written. 66 | /// The content stream to be written. 67 | /// HTTP content headers. 68 | /// The request context. 69 | void WriteToRequestBody(TRequestContent requestContent, Stream contentStream, IDictionary contentHeaders, IRequestContext requestContext); 70 | 71 | /// 72 | /// Writes a byte array to the request body. 73 | /// 74 | /// The destination where the content stream is written. 75 | /// The content stream to be written. 76 | /// HTTP content headers. 77 | void WriteToRequestBody(TRequestContent requestContent, byte[] content, IDictionary contentHeaders); 78 | 79 | /// 80 | /// Aborts the HTTP request. 81 | /// 82 | void Abort(); 83 | 84 | /// 85 | /// Initiates the operation to gets a handle to the request content. 86 | /// 87 | /// The async callback invoked when the operation completes. 88 | /// The state object to be passed to the async callback. 89 | /// IAsyncResult that represents an async operation. 90 | IAsyncResult BeginGetRequestContent(AsyncCallback callback, object state); 91 | 92 | /// 93 | /// Ends the operation to gets a handle to the request content. 94 | /// 95 | /// IAsyncResult that represents an async operation. 96 | /// The request content. 97 | TRequestContent EndGetRequestContent(IAsyncResult asyncResult); 98 | 99 | /// 100 | /// Initiates the operation to Returns the HTTP response. 101 | /// 102 | /// The async callback invoked when the operation completes. 103 | /// The state object to be passed to the async callback. 104 | /// IAsyncResult that represents an async operation. 105 | IAsyncResult BeginGetResponse(AsyncCallback callback, object state); 106 | 107 | /// 108 | /// Ends the operation to Returns the HTTP response. 109 | /// 110 | /// IAsyncResult that represents an async operation. 111 | /// The HTTP response. 112 | IWebResponseData EndGetResponse(IAsyncResult asyncResult); 113 | 114 | /// 115 | /// Gets a handle to the request content. 116 | /// 117 | /// 118 | 119 | System.Threading.Tasks.Task GetRequestContentAsync(); 120 | 121 | /// 122 | /// Returns the HTTP response. 123 | /// 124 | /// A cancellation token that can be used to cancel the asynchronous operation. 125 | /// 126 | System.Threading.Tasks.Task GetResponseAsync(System.Threading.CancellationToken cancellationToken); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/ErrorHandler/HttpErrorResponseExceptionHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Net; 4 | using System.IO; 5 | using System.Text; 6 | using Aliyun.MQ.Util; 7 | using Aliyun.MQ.Runtime.Internal.Transform; 8 | using Aliyun.MQ.Model.Exp; 9 | 10 | namespace Aliyun.MQ.Runtime.Pipeline.ErrorHandler 11 | { 12 | /// 13 | /// The exception handler for HttpErrorResponseException exception. 14 | /// 15 | public class HttpErrorResponseExceptionHandler : ExceptionHandler 16 | { 17 | /// 18 | /// The constructor for HttpErrorResponseExceptionHandler. 19 | /// 20 | public HttpErrorResponseExceptionHandler() : 21 | base() 22 | { 23 | } 24 | 25 | /// 26 | /// Handles an exception for the given execution context. 27 | /// 28 | /// The execution context, it contains the 29 | /// request and response context. 30 | /// The exception to handle. 31 | /// 32 | /// Returns a boolean value which indicates if the original exception 33 | /// should be rethrown. 34 | /// This method can also throw a new exception to replace the original exception. 35 | /// 36 | public override bool HandleException(IExecutionContext executionContext, HttpErrorResponseException exception) 37 | { 38 | var requestContext = executionContext.RequestContext; 39 | var httpErrorResponse = exception.Response; 40 | 41 | // If 404 was suppressed and successfully unmarshalled, 42 | // don't rethrow the original exception. 43 | if (HandleSuppressed404(executionContext, httpErrorResponse)) 44 | return false; 45 | 46 | AliyunServiceException errorResponseException = null; 47 | // Unmarshall the service error response and throw the corresponding service exception 48 | string responseContent = null; 49 | try 50 | { 51 | using (httpErrorResponse.ResponseBody) 52 | { 53 | var unmarshaller = requestContext.Unmarshaller; 54 | 55 | var errorContext = unmarshaller.CreateContext(httpErrorResponse, httpErrorResponse.ResponseBody.OpenResponse()); 56 | 57 | using (MemoryStream stream = new MemoryStream()) 58 | { 59 | AliyunSDKUtils.CopyTo(errorContext.ResponseStream, stream); 60 | stream.Seek(0, SeekOrigin.Begin); 61 | byte[] bytes = new byte[stream.Length]; 62 | stream.Read(bytes, 0, (int)stream.Length); 63 | responseContent = Encoding.UTF8.GetString(bytes); 64 | stream.Seek(0, SeekOrigin.Begin); 65 | 66 | errorContext.ResponseStream = stream; 67 | 68 | errorResponseException = unmarshaller.UnmarshallException(errorContext, 69 | exception, httpErrorResponse.StatusCode); 70 | Debug.Assert(errorResponseException != null); 71 | } 72 | } 73 | } 74 | catch (ResponseUnmarshallException unmarshallException) 75 | { 76 | if (responseContent != null) 77 | { 78 | throw new AliyunServiceException(responseContent, unmarshallException, 79 | ErrorCode.InternalError, 80 | null, null, httpErrorResponse.StatusCode); 81 | } 82 | throw; 83 | } 84 | 85 | throw errorResponseException; 86 | } 87 | 88 | /// 89 | /// Checks if a HTTP 404 status code is returned which needs to be suppressed and 90 | /// processes it. 91 | /// If a suppressed 404 is present, it unmarshalls the response and returns true to 92 | /// indicate that a suppressed 404 was processed, else returns false. 93 | /// 94 | /// The execution context, it contains the 95 | /// request and response context. 96 | /// 97 | /// 98 | /// If a suppressed 404 is present, returns true, else returns false. 99 | /// 100 | private bool HandleSuppressed404(IExecutionContext executionContext, IWebResponseData httpErrorResponse) 101 | { 102 | var requestContext = executionContext.RequestContext; 103 | var responseContext = executionContext.ResponseContext; 104 | 105 | // If the error is a 404 and the request is configured to supress it, 106 | // then unmarshall as much as we can. 107 | if (httpErrorResponse != null && 108 | httpErrorResponse.StatusCode == HttpStatusCode.NotFound && 109 | requestContext.Request.Suppress404Exceptions) 110 | { 111 | using (httpErrorResponse.ResponseBody) 112 | { 113 | var unmarshaller = requestContext.Unmarshaller; 114 | 115 | UnmarshallerContext errorContext = unmarshaller.CreateContext( 116 | httpErrorResponse, 117 | httpErrorResponse.ResponseBody.OpenResponse()); 118 | try 119 | { 120 | responseContext.Response = unmarshaller.Unmarshall(errorContext); 121 | responseContext.Response.ContentLength = httpErrorResponse.ContentLength; 122 | responseContext.Response.HttpStatusCode = httpErrorResponse.StatusCode; 123 | return true; 124 | } 125 | catch (Exception) 126 | { 127 | return false; 128 | } 129 | } 130 | } 131 | return false; 132 | } 133 | } 134 | } -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/DefaultRequest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using Aliyun.MQ.Model; 5 | 6 | namespace Aliyun.MQ.Runtime.Internal 7 | { 8 | internal class DefaultRequest : IRequest 9 | { 10 | readonly IDictionary parameters = new Dictionary(StringComparer.Ordinal); 11 | readonly IDictionary headers = new Dictionary(StringComparer.OrdinalIgnoreCase); 12 | readonly IDictionary subResources = new Dictionary(StringComparer.OrdinalIgnoreCase); 13 | 14 | Uri endpoint; 15 | string resourcePath; 16 | string serviceName; 17 | readonly WebServiceRequest originalRequest; 18 | byte[] content; 19 | Stream contentStream; 20 | string httpMethod = "GET"; 21 | bool useQueryString = false; 22 | string requestName; 23 | long originalStreamLength; 24 | 25 | public DefaultRequest(WebServiceRequest request, String serviceName) 26 | { 27 | if (request == null) throw new ArgumentNullException("request"); 28 | if (string.IsNullOrEmpty(serviceName)) throw new ArgumentNullException("serviceName"); 29 | 30 | this.serviceName = serviceName; 31 | this.originalRequest = request; 32 | this.requestName = this.originalRequest.GetType().Name; 33 | 34 | foreach (var header in request.Headers) 35 | this.Headers.Add(header.Key, header.Value); 36 | foreach (var param in request.Parameters) 37 | this.Parameters.Add(param.Key, param.Value); 38 | } 39 | 40 | public string RequestName 41 | { 42 | get { return this.requestName; } 43 | } 44 | 45 | public string HttpMethod 46 | { 47 | get 48 | { 49 | return this.httpMethod; 50 | } 51 | set 52 | { 53 | this.httpMethod = value; 54 | } 55 | } 56 | 57 | public bool UseQueryString 58 | { 59 | get 60 | { 61 | return this.useQueryString; 62 | } 63 | set 64 | { 65 | this.useQueryString = value; 66 | } 67 | } 68 | 69 | public WebServiceRequest OriginalRequest 70 | { 71 | get 72 | { 73 | return originalRequest; 74 | } 75 | } 76 | 77 | public IDictionary Headers 78 | { 79 | get 80 | { 81 | return this.headers; 82 | } 83 | } 84 | 85 | 86 | public IDictionary Parameters 87 | { 88 | get 89 | { 90 | return this.parameters; 91 | } 92 | } 93 | 94 | public IDictionary SubResources 95 | { 96 | get 97 | { 98 | return this.subResources; 99 | } 100 | } 101 | 102 | public void AddSubResource(string subResource) 103 | { 104 | AddSubResource(subResource, null); 105 | } 106 | 107 | public void AddSubResource(string subResource, string value) 108 | { 109 | SubResources.Add(subResource, value); 110 | } 111 | 112 | public Uri Endpoint 113 | { 114 | get 115 | { 116 | return this.endpoint; 117 | } 118 | set 119 | { 120 | this.endpoint = value; 121 | } 122 | } 123 | 124 | public string ResourcePath 125 | { 126 | get 127 | { 128 | return this.resourcePath; 129 | } 130 | set 131 | { 132 | this.resourcePath = value; 133 | } 134 | } 135 | 136 | public byte[] Content 137 | { 138 | get 139 | { 140 | return this.content; 141 | } 142 | set 143 | { 144 | this.content = value; 145 | } 146 | } 147 | 148 | public Stream ContentStream 149 | { 150 | get { return this.contentStream; } 151 | set 152 | { 153 | this.contentStream = value; 154 | OriginalStreamPosition = -1; 155 | if (this.contentStream != null && this.contentStream.CanSeek) 156 | OriginalStreamPosition = this.contentStream.Position; 157 | } 158 | } 159 | 160 | public long OriginalStreamPosition 161 | { 162 | get { return this.originalStreamLength; } 163 | set { this.originalStreamLength = value; } 164 | } 165 | 166 | public string ServiceName 167 | { 168 | get 169 | { 170 | return this.serviceName; 171 | } 172 | } 173 | 174 | public bool Suppress404Exceptions 175 | { 176 | get; 177 | set; 178 | } 179 | 180 | public bool IsRequestStreamRewindable() 181 | { 182 | // Retries may not be possible with a stream 183 | if (this.ContentStream != null) 184 | { 185 | // Retry is possible if stream is seekable 186 | return this.ContentStream.CanSeek; 187 | } 188 | return true; 189 | } 190 | 191 | public bool MayContainRequestBody() 192 | { 193 | return !this.UseQueryString && 194 | (this.HttpMethod == "POST" || 195 | this.HttpMethod == "PUT" || 196 | this.HttpMethod == "DELETE"); 197 | } 198 | 199 | public bool HasRequestBody() 200 | { 201 | return (this.HttpMethod == "POST" || 202 | this.HttpMethod == "PUT" || 203 | this.HttpMethod == "DELETE") && 204 | ((this.Content != null) || 205 | this.ContentStream != null); 206 | } 207 | } 208 | } 209 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Pipeline/RetryHandler/DefaultRetryPolicy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Net; 5 | using System.Threading; 6 | using Aliyun.MQ.Util; 7 | using NLog; 8 | 9 | namespace Aliyun.MQ.Runtime.Pipeline.RetryHandler 10 | { 11 | public class DefaultRetryPolicy : RetryPolicy 12 | { 13 | private static readonly Logger Logger = MqLogManager.Instance.GetCurrentClassLogger(); 14 | 15 | private int _maxBackoffInMilliseconds = (int)TimeSpan.FromSeconds(30).TotalMilliseconds; 16 | 17 | // Set of web exception status codes to retry on. 18 | private ICollection _webExceptionStatusesToRetryOn = new HashSet 19 | { 20 | WebExceptionStatus.ConnectFailure, 21 | WebExceptionStatus.ConnectionClosed, 22 | WebExceptionStatus.KeepAliveFailure, 23 | WebExceptionStatus.NameResolutionFailure, 24 | WebExceptionStatus.ReceiveFailure 25 | }; 26 | 27 | // Set of error codes to retry on. 28 | private ICollection _errorCodesToRetryOn = new HashSet 29 | { 30 | "Throttling", 31 | "RequestTimeout" 32 | }; 33 | 34 | public int MaxBackoffInMilliseconds 35 | { 36 | get { return _maxBackoffInMilliseconds; } 37 | set { _maxBackoffInMilliseconds = value; } 38 | } 39 | 40 | public ICollection ErrorCodesToRetryOn 41 | { 42 | get { return _errorCodesToRetryOn; } 43 | } 44 | 45 | public ICollection WebExceptionStatusesToRetryOn 46 | { 47 | get { return _webExceptionStatusesToRetryOn; } 48 | } 49 | 50 | public DefaultRetryPolicy(int maxRetries) 51 | { 52 | this.MaxRetries = maxRetries; 53 | } 54 | 55 | public override bool CanRetry(IExecutionContext executionContext) 56 | { 57 | return executionContext.RequestContext.Request.IsRequestStreamRewindable(); 58 | } 59 | 60 | public override bool RetryForException(IExecutionContext executionContext, Exception exception) 61 | { 62 | // An IOException was thrown by the underlying http client. 63 | if (exception is IOException) 64 | { 65 | // Don't retry IOExceptions that are caused by a ThreadAbortException 66 | if (IsInnerException(exception)) 67 | return false; 68 | 69 | // Retry all other IOExceptions 70 | return true; 71 | } 72 | 73 | // A AliyunServiceException was thrown by ErrorHandler 74 | var serviceException = exception as AliyunServiceException; 75 | if (serviceException != null) 76 | { 77 | /* 78 | * For 500 internal server errors and 503 service 79 | * unavailable errors, we want to retry, but we need to use 80 | * an exponential back-off strategy so that we don't overload 81 | * a server with a flood of retries. If we've surpassed our 82 | * retry limit we handle the error response as a non-retryable 83 | * error and go ahead and throw it back to the user as an exception. 84 | */ 85 | if (serviceException.StatusCode == HttpStatusCode.InternalServerError || 86 | serviceException.StatusCode == HttpStatusCode.ServiceUnavailable) 87 | { 88 | return true; 89 | } 90 | 91 | /* 92 | * Throttling is reported as a 400 or 503 error from services. To try and 93 | * smooth out an occasional throttling error, we'll pause and retry, 94 | * hoping that the pause is long enough for the request to get through 95 | * the next time. 96 | */ 97 | if ((serviceException.StatusCode == HttpStatusCode.BadRequest || 98 | serviceException.StatusCode == HttpStatusCode.ServiceUnavailable)) 99 | { 100 | string errorCode = serviceException.ErrorCode; 101 | if (this.ErrorCodesToRetryOn.Contains(errorCode)) 102 | { 103 | return true; 104 | } 105 | } 106 | 107 | WebException webException; 108 | if (IsInnerException(exception, out webException)) 109 | { 110 | if (this.WebExceptionStatusesToRetryOn.Contains(webException.Status)) 111 | { 112 | return true; 113 | } 114 | } 115 | } 116 | 117 | return false; 118 | } 119 | 120 | public override bool RetryLimitReached(IExecutionContext executionContext) 121 | { 122 | return executionContext.RequestContext.Retries >= this.MaxRetries; 123 | } 124 | 125 | public override void WaitBeforeRetry(IExecutionContext executionContext) 126 | { 127 | DefaultRetryPolicy.WaitBeforeRetry(executionContext.RequestContext.Retries, this.MaxBackoffInMilliseconds); 128 | } 129 | 130 | public static void WaitBeforeRetry(int retries, int maxBackoffInMilliseconds) 131 | { 132 | int delay = (int)(Math.Pow(4, retries) * 100); 133 | delay = Math.Min(delay, maxBackoffInMilliseconds); 134 | Logger.Info($"retries={retries}, delay={delay}"); 135 | AliyunSDKUtils.Sleep(delay); 136 | } 137 | 138 | protected static bool IsInnerException(Exception exception) 139 | where T : Exception 140 | { 141 | T innerException; 142 | return IsInnerException(exception, out innerException); 143 | } 144 | 145 | protected static bool IsInnerException(Exception exception, out T inner) 146 | where T : Exception 147 | { 148 | inner = null; 149 | var innerExceptionType = typeof(T); 150 | var currentException = exception; 151 | while (currentException.InnerException != null) 152 | { 153 | inner = currentException.InnerException as T; 154 | if (inner != null) 155 | { 156 | return true; 157 | } 158 | currentException = currentException.InnerException; 159 | } 160 | return false; 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/AliyunServiceClient.cs: -------------------------------------------------------------------------------- 1 | using Aliyun.MQ.Runtime.Internal; 2 | using Aliyun.MQ.Runtime.Internal.Auth; 3 | using Aliyun.MQ.Runtime.Internal.Transform; 4 | using Aliyun.MQ.Runtime.Pipeline; 5 | using Aliyun.MQ.Runtime.Pipeline.ErrorHandler; 6 | using Aliyun.MQ.Runtime.Pipeline.Handlers; 7 | using Aliyun.MQ.Runtime.Pipeline.HttpHandler; 8 | using Aliyun.MQ.Runtime.Pipeline.RetryHandler; 9 | using Aliyun.MQ.Util; 10 | using System; 11 | using System.Collections.Generic; 12 | using System.IO; 13 | using System.Net; 14 | using System.Text; 15 | 16 | namespace Aliyun.MQ.Runtime 17 | { 18 | public abstract class AliyunServiceClient : IDisposable 19 | { 20 | private bool _disposed; 21 | 22 | protected RuntimePipeline RuntimePipeline { get; set; } 23 | protected ServiceCredentials Credentials { get; private set; } 24 | internal ClientConfig Config { get; private set; } 25 | 26 | #region Constructors 27 | 28 | internal AliyunServiceClient(ServiceCredentials credentials, ClientConfig config) 29 | { 30 | ServicePointManager.Expect100Continue = true; 31 | ServicePointManager.DefaultConnectionLimit = config.ConnectionLimit; 32 | ServicePointManager.MaxServicePointIdleTime = config.MaxIdleTime; 33 | 34 | this.Config = config; 35 | this.Credentials = credentials; 36 | Signer = CreateSigner(); 37 | 38 | Initialize(); 39 | 40 | BuildRuntimePipeline(); 41 | } 42 | 43 | protected IServiceSigner Signer 44 | { 45 | get; 46 | private set; 47 | } 48 | 49 | internal AliyunServiceClient(string accessKeyId, string secretAccessKey, ClientConfig config, string stsToken) 50 | : this(new BasicServiceCredentials(accessKeyId, secretAccessKey, stsToken), config) 51 | { 52 | } 53 | 54 | protected virtual void Initialize() 55 | { 56 | } 57 | 58 | #endregion 59 | 60 | #region Invoke methods 61 | 62 | internal TResponse Invoke(TRequest request, 63 | IMarshaller marshaller, ResponseUnmarshaller unmarshaller) 64 | where TRequest: WebServiceRequest 65 | where TResponse : WebServiceResponse 66 | { 67 | ThrowIfDisposed(); 68 | 69 | var executionContext = new ExecutionContext( 70 | new RequestContext() 71 | { 72 | ClientConfig = this.Config, 73 | Marshaller = marshaller, 74 | OriginalRequest = request, 75 | Signer = Signer, 76 | Unmarshaller = unmarshaller, 77 | IsAsync = false 78 | }, 79 | new ResponseContext() 80 | ); 81 | 82 | var response = (TResponse)this.RuntimePipeline.InvokeSync(executionContext).Response; 83 | return response; 84 | } 85 | 86 | internal IAsyncResult BeginInvoke(TRequest request, 87 | IMarshaller marshaller, ResponseUnmarshaller unmarshaller, 88 | AsyncCallback callback, object state) 89 | where TRequest : WebServiceRequest 90 | { 91 | ThrowIfDisposed(); 92 | 93 | var executionContext = new AsyncExecutionContext( 94 | new AsyncRequestContext() 95 | { 96 | ClientConfig = this.Config, 97 | Marshaller = marshaller, 98 | OriginalRequest = request, 99 | Signer = Signer, 100 | Unmarshaller = unmarshaller, 101 | Callback = callback, 102 | State = state, 103 | IsAsync = true 104 | }, 105 | new AsyncResponseContext() 106 | ); 107 | 108 | var asyncResult = this.RuntimePipeline.InvokeAsync(executionContext); 109 | return asyncResult; 110 | } 111 | 112 | internal static TResponse EndInvoke(IAsyncResult result) 113 | where TResponse : WebServiceResponse 114 | { 115 | if (result == null) 116 | throw new ArgumentNullException("result", "Parameter result cannot be null."); 117 | 118 | var asyncResult = result as RuntimeAsyncResult; 119 | 120 | if (asyncResult == null) 121 | throw new ArgumentOutOfRangeException("result", "Parameter result is not of type RuntimeAsyncResult."); 122 | 123 | using (asyncResult) 124 | { 125 | if (!asyncResult.IsCompleted) 126 | { 127 | asyncResult.AsyncWaitHandle.WaitOne(); 128 | } 129 | 130 | if (asyncResult.Exception != null) 131 | { 132 | AliyunSDKUtils.PreserveStackTrace(asyncResult.Exception); 133 | throw asyncResult.Exception; 134 | } 135 | 136 | return (TResponse) asyncResult.Response; 137 | } 138 | } 139 | 140 | #endregion 141 | 142 | #region Dispose methods 143 | 144 | public void Dispose() 145 | { 146 | Dispose(true); 147 | GC.SuppressFinalize(this); 148 | } 149 | 150 | protected virtual void Dispose(bool disposing) 151 | { 152 | if (_disposed) 153 | return; 154 | 155 | if (disposing) 156 | { 157 | if (RuntimePipeline != null) 158 | RuntimePipeline.Dispose(); 159 | 160 | _disposed = true; 161 | } 162 | } 163 | 164 | private void ThrowIfDisposed() 165 | { 166 | if (this._disposed) 167 | throw new ObjectDisposedException(GetType().FullName); 168 | } 169 | 170 | #endregion 171 | 172 | protected abstract IServiceSigner CreateSigner(); 173 | protected virtual void CustomizeRuntimePipeline(RuntimePipeline pipeline) { } 174 | 175 | private void BuildRuntimePipeline() 176 | { 177 | var httpRequestFactory = new HttpWebRequestFactory(); 178 | var httpHandler = new HttpHandler(httpRequestFactory, this); 179 | 180 | this.RuntimePipeline = new RuntimePipeline(new List 181 | { 182 | httpHandler, 183 | new Unmarshaller(), 184 | new ErrorHandler(), 185 | new Signer(), 186 | new CredentialsRetriever(this.Credentials), 187 | new RetryHandler(new DefaultRetryPolicy(this.Config.MaxErrorRetry)), 188 | new Marshaller() 189 | } 190 | ); 191 | 192 | CustomizeRuntimePipeline(this.RuntimePipeline); 193 | } 194 | 195 | internal static Uri ComposeUrl(IRequest iRequest) 196 | { 197 | Uri url = iRequest.Endpoint; 198 | var resourcePath = iRequest.ResourcePath; 199 | if (resourcePath == null) 200 | resourcePath = string.Empty; 201 | else 202 | { 203 | if (resourcePath.StartsWith("//", StringComparison.Ordinal)) 204 | resourcePath = resourcePath.Substring(2); 205 | else if (resourcePath.StartsWith("/", StringComparison.Ordinal)) 206 | resourcePath = resourcePath.Substring(1); 207 | } 208 | 209 | var delim = "?"; 210 | var sb = new StringBuilder(); 211 | 212 | if (iRequest.SubResources.Count > 0) 213 | { 214 | foreach (var subResource in iRequest.SubResources) 215 | { 216 | sb.AppendFormat("{0}{1}", delim, subResource.Key); 217 | if (subResource.Value != null) 218 | sb.AppendFormat("={0}", subResource.Value); 219 | delim = "&"; 220 | } 221 | } 222 | 223 | if (iRequest.Parameters.Count > 0) 224 | { 225 | var queryString = AliyunSDKUtils.GetParametersAsString(iRequest.Parameters); 226 | sb.AppendFormat("{0}{1}", delim, queryString); 227 | } 228 | 229 | var parameterizedPath = string.Concat(resourcePath, sb); 230 | var uri = new Uri(url.AbsoluteUri + parameterizedPath); 231 | return uri; 232 | } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/MQConsumer.cs: -------------------------------------------------------------------------------- 1 | 2 | using Aliyun.MQ.Model; 3 | using Aliyun.MQ.Model.Internal.MarshallTransformations; 4 | using Aliyun.MQ.Runtime; 5 | using Aliyun.MQ.Util; 6 | using System.Collections.Generic; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | 10 | namespace Aliyun.MQ 11 | { 12 | public partial class MQConsumer 13 | { 14 | private string _instanceId; 15 | private string _topicName; 16 | private string _consumer; 17 | private string _messageTag; 18 | private readonly HttpClientBasedAliyunServiceClient _serviceClient; 19 | 20 | public MQConsumer(string instanceId, string topicName, string consumer, string messageTag, HttpClientBasedAliyunServiceClient serviceClient) 21 | { 22 | this._instanceId = instanceId; 23 | this._topicName = topicName; 24 | this._consumer = consumer; 25 | if (messageTag != null) 26 | { 27 | this._messageTag = AliyunSDKUtils.UrlEncode(messageTag, false); 28 | } 29 | this._serviceClient = serviceClient; 30 | } 31 | 32 | public string IntanceId 33 | { 34 | get { return this._instanceId; } 35 | } 36 | 37 | public bool IsSetInstance() 38 | { 39 | return !string.IsNullOrEmpty(this._instanceId); 40 | } 41 | 42 | public string TopicName 43 | { 44 | get { return this._topicName; } 45 | } 46 | 47 | public bool IsSetTopicName() 48 | { 49 | return this._topicName != null; 50 | } 51 | 52 | public string Consumer 53 | { 54 | get { return this._consumer; } 55 | } 56 | 57 | public bool IsSetConsumer() 58 | { 59 | return this._consumer != null; 60 | } 61 | 62 | public string MessageTag 63 | { 64 | get { return this._messageTag; } 65 | } 66 | 67 | public bool IsSetMessageTag() 68 | { 69 | return this._messageTag != null; 70 | } 71 | 72 | public AckMessageResponse AckMessage(List receiptHandles) 73 | { 74 | var request = new AckMessageRequest(this._topicName, this._consumer, receiptHandles); 75 | request.IntanceId = this._instanceId; 76 | var marshaller = new AckMessageRequestMarshaller(); 77 | var unmarshaller = AckMessageResponseUnmarshaller.Instance; 78 | 79 | return _serviceClient.Invoke(request, marshaller, unmarshaller); 80 | } 81 | 82 | public async Task AckMessageAsync(List receiptHandles) 83 | { 84 | var request = new AckMessageRequest(this._topicName, this._consumer, receiptHandles); 85 | request.IntanceId = this._instanceId; 86 | var marshaller = new AckMessageRequestMarshaller(); 87 | var unmarshaller = AckMessageResponseUnmarshaller.Instance; 88 | 89 | var ackMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, unmarshaller, default(CancellationToken)); 90 | return ackMessageResponse; 91 | } 92 | 93 | public List ConsumeMessage(uint batchSize) 94 | { 95 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 96 | request.IntanceId = this._instanceId; 97 | request.BatchSize = batchSize; 98 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 99 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 100 | 101 | ConsumeMessageResponse result = _serviceClient.Invoke(request, marshaller, unmarshaller); 102 | 103 | return result.Messages; 104 | } 105 | 106 | public async Task> ConsumeMessageAsync(uint batchSize) 107 | { 108 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 109 | request.IntanceId = this._instanceId; 110 | request.BatchSize = batchSize; 111 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 112 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 113 | 114 | var consumeMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, 115 | unmarshaller, default(CancellationToken)); 116 | return consumeMessageResponse.Messages; 117 | } 118 | 119 | public List ConsumeMessageOrderly(uint batchSize) 120 | { 121 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 122 | request.IntanceId = this._instanceId; 123 | request.BatchSize = batchSize; 124 | request.Trasaction = "order"; 125 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 126 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 127 | 128 | ConsumeMessageResponse result = _serviceClient.Invoke(request, marshaller, unmarshaller); 129 | return result.Messages; 130 | } 131 | 132 | public async Task> ConsumeMessageOrderlyAsync(uint batchSize) 133 | { 134 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 135 | request.IntanceId = this._instanceId; 136 | request.BatchSize = batchSize; 137 | request.Trasaction = "order"; 138 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 139 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 140 | 141 | var consumeMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, 142 | unmarshaller, default(CancellationToken)); 143 | return consumeMessageResponse.Messages; 144 | } 145 | 146 | public List ConsumeMessage(uint batchSize, uint waitSeconds) 147 | { 148 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 149 | request.IntanceId = this._instanceId; 150 | request.BatchSize = batchSize; 151 | request.WaitSeconds = waitSeconds; 152 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 153 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 154 | 155 | ConsumeMessageResponse result = _serviceClient.Invoke(request, marshaller, unmarshaller); 156 | 157 | return result.Messages; 158 | } 159 | 160 | public async Task> ConsumeMessageAsync(uint batchSize, uint waitSeconds) 161 | { 162 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 163 | request.IntanceId = this._instanceId; 164 | request.BatchSize = batchSize; 165 | request.WaitSeconds = waitSeconds; 166 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 167 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 168 | 169 | var consumeMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, unmarshaller, default(CancellationToken)); 170 | return consumeMessageResponse.Messages; 171 | } 172 | 173 | public List ConsumeMessageOrderly(uint batchSize, uint waitSeconds) 174 | { 175 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 176 | request.IntanceId = this._instanceId; 177 | request.BatchSize = batchSize; 178 | request.WaitSeconds = waitSeconds; 179 | request.Trasaction = "order"; 180 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 181 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 182 | 183 | ConsumeMessageResponse result = _serviceClient.Invoke(request, marshaller, unmarshaller); 184 | 185 | return result.Messages; 186 | } 187 | 188 | public async Task> ConsumeMessageOrderlyAsync(uint batchSize, uint waitSeconds) 189 | { 190 | var request = new ConsumeMessageRequest(this._topicName, this._consumer, this._messageTag); 191 | request.IntanceId = this._instanceId; 192 | request.BatchSize = batchSize; 193 | request.WaitSeconds = waitSeconds; 194 | request.Trasaction = "order"; 195 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 196 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 197 | 198 | var consumeMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, unmarshaller, default(CancellationToken)); 199 | return consumeMessageResponse.Messages; 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/MQProducer.cs: -------------------------------------------------------------------------------- 1 | 2 | using Aliyun.MQ.Model; 3 | using Aliyun.MQ.Model.Exp; 4 | using Aliyun.MQ.Model.Internal.MarshallTransformations; 5 | using Aliyun.MQ.Runtime; 6 | using Aliyun.MQ.Util; 7 | using System.Collections.Generic; 8 | using System.Threading; 9 | using System.Threading.Tasks; 10 | 11 | namespace Aliyun.MQ 12 | { 13 | public partial class MQProducer 14 | { 15 | 16 | protected string _topicName; 17 | protected string _instanceId; 18 | protected readonly HttpClientBasedAliyunServiceClient _serviceClient; 19 | 20 | public MQProducer(string instanceId, string topicName, HttpClientBasedAliyunServiceClient serviceClient) 21 | { 22 | this._instanceId = instanceId; 23 | this._topicName = topicName; 24 | this._serviceClient = serviceClient; 25 | } 26 | 27 | public string TopicName 28 | { 29 | get { return this._topicName; } 30 | } 31 | 32 | public bool IsSetTopicName() 33 | { 34 | return this._topicName != null; 35 | } 36 | 37 | public string IntanceId 38 | { 39 | get { return this._instanceId; } 40 | } 41 | 42 | public bool IsSetInstance() 43 | { 44 | return !string.IsNullOrEmpty(this._instanceId); 45 | } 46 | 47 | public TopicMessage PublishMessage(TopicMessage topicMessage) 48 | { 49 | var request = new PublishMessageRequest(topicMessage.Body, topicMessage.MessageTag); 50 | request.TopicName = this._topicName; 51 | request.IntanceId = this._instanceId; 52 | request.Properties = AliyunSDKUtils.DictToString(topicMessage.Properties); 53 | 54 | var marshaller = PublishMessageRequestMarshaller.Instance; 55 | var unmarshaller = PublishMessageResponseUnmarshaller.Instance; 56 | 57 | PublishMessageResponse result = _serviceClient.Invoke(request, marshaller, unmarshaller); 58 | 59 | TopicMessage retMsg = new TopicMessage(null); 60 | retMsg.Id = result.MessageId; 61 | retMsg.BodyMD5 = result.MessageBodyMD5; 62 | retMsg.ReceiptHandle = result.ReeceiptHandle; 63 | 64 | return retMsg; 65 | } 66 | 67 | public async Task PublishMessageAsync(TopicMessage topicMessage) 68 | { 69 | var request = new PublishMessageRequest(topicMessage.Body, topicMessage.MessageTag); 70 | request.TopicName = this._topicName; 71 | request.IntanceId = this._instanceId; 72 | request.Properties = AliyunSDKUtils.DictToString(topicMessage.Properties); 73 | 74 | var marshaller = PublishMessageRequestMarshaller.Instance; 75 | var unmarshaller = PublishMessageResponseUnmarshaller.Instance; 76 | var result = await _serviceClient.InvokeAsync(request, marshaller, 77 | unmarshaller, default(CancellationToken)); 78 | TopicMessage retMsg = new TopicMessage(null); 79 | retMsg.Id = result.MessageId; 80 | retMsg.BodyMD5 = result.MessageBodyMD5; 81 | retMsg.ReceiptHandle = result.ReeceiptHandle; 82 | return retMsg; 83 | } 84 | 85 | } 86 | 87 | public partial class MQTransProducer : MQProducer 88 | { 89 | private readonly string _groupId; 90 | 91 | public MQTransProducer(string instanceId, string topicName, string groupId, HttpClientBasedAliyunServiceClient serviceClient) : base(instanceId, topicName, serviceClient) 92 | { 93 | if (string.IsNullOrEmpty(groupId)) 94 | { 95 | throw new MQException("GroupId is null or empty!"); 96 | } 97 | this._groupId = groupId; 98 | } 99 | 100 | public string GroupId 101 | { 102 | get { return this._groupId; } 103 | } 104 | 105 | /// 106 | /// commit transaction msg, the consumer will receive the msg. 107 | /// 108 | /// The commit. 109 | /// Receipt handle. 110 | public AckMessageResponse Commit(string receiptHandle) 111 | { 112 | List handlers = new List 113 | { 114 | receiptHandle 115 | }; 116 | 117 | var request = new AckMessageRequest(this._topicName, this._groupId, handlers); 118 | request.IntanceId = this._instanceId; 119 | request.Trasaction = "commit"; 120 | var marshaller = new AckMessageRequestMarshaller(); 121 | var unmarshaller = AckMessageResponseUnmarshaller.Instance; 122 | 123 | return _serviceClient.Invoke(request, marshaller, unmarshaller); 124 | } 125 | 126 | public async Task CommitAsync(string receiptHandle) 127 | { 128 | List handlers = new List 129 | { 130 | receiptHandle 131 | }; 132 | 133 | var request = new AckMessageRequest(this._topicName, this._groupId, handlers); 134 | request.IntanceId = this._instanceId; 135 | request.Trasaction = "commit"; 136 | var marshaller = new AckMessageRequestMarshaller(); 137 | var unmarshaller = AckMessageResponseUnmarshaller.Instance; 138 | 139 | var ackMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, unmarshaller, default(CancellationToken)); 140 | return ackMessageResponse; 141 | } 142 | 143 | /// 144 | /// rollback transaction msg, the consumer will not receive the msg. 145 | /// 146 | /// The rollback. 147 | /// Receipt handle. 148 | public AckMessageResponse Rollback(string receiptHandle) 149 | { 150 | List handlers = new List 151 | { 152 | receiptHandle 153 | }; 154 | 155 | var request = new AckMessageRequest(this._topicName, this._groupId, handlers); 156 | request.IntanceId = this._instanceId; 157 | request.Trasaction = "rollback"; 158 | var marshaller = new AckMessageRequestMarshaller(); 159 | var unmarshaller = AckMessageResponseUnmarshaller.Instance; 160 | 161 | return _serviceClient.Invoke(request, marshaller, unmarshaller); 162 | } 163 | 164 | public async Task RollbackAsync(string receiptHandle) 165 | { 166 | List handlers = new List 167 | { 168 | receiptHandle 169 | }; 170 | 171 | var request = new AckMessageRequest(this._topicName, this._groupId, handlers); 172 | request.IntanceId = this._instanceId; 173 | request.Trasaction = "rollback"; 174 | var marshaller = new AckMessageRequestMarshaller(); 175 | var unmarshaller = AckMessageResponseUnmarshaller.Instance; 176 | 177 | var ackMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, unmarshaller, default(CancellationToken)); 178 | return ackMessageResponse; 179 | } 180 | 181 | /// 182 | /// Consumes the half tranaction message. 183 | /// 184 | /// The half message. 185 | /// Batch size. 1~16 186 | /// Wait seconds. 1~30 is valid, others will be ignored. 187 | public List ConsumeHalfMessage(uint batchSize, uint waitSeconds) 188 | { 189 | var request = new ConsumeMessageRequest(this._topicName, this._groupId, null); 190 | request.IntanceId = this._instanceId; 191 | request.BatchSize = batchSize; 192 | request.WaitSeconds = waitSeconds; 193 | request.Trasaction = "pop"; 194 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 195 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 196 | 197 | ConsumeMessageResponse result = _serviceClient.Invoke(request, marshaller, unmarshaller); 198 | 199 | return result.Messages; 200 | } 201 | 202 | public async Task> ConsumeHalfMessageAsync(uint batchSize, uint waitSeconds) 203 | { 204 | var request = new ConsumeMessageRequest(this._topicName, this._groupId, null); 205 | request.IntanceId = this._instanceId; 206 | request.BatchSize = batchSize; 207 | request.WaitSeconds = waitSeconds; 208 | request.Trasaction = "pop"; 209 | var marshaller = ConsumeMessageRequestMarshaller.Instance; 210 | var unmarshaller = ConsumeMessageResponseUnmarshaller.Instance; 211 | 212 | var consumeMessageResponse = await _serviceClient.InvokeAsync(request, marshaller, unmarshaller, default(CancellationToken)); 213 | return consumeMessageResponse.Messages; 214 | } 215 | } 216 | } 217 | -------------------------------------------------------------------------------- /Aliyun_MQ_SDK/Runtime/Internal/Auth/MQSigner.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Globalization; 6 | using System.Text.RegularExpressions; 7 | using Aliyun.MQ.Runtime.Internal.Util; 8 | using Aliyun.MQ.Util; 9 | 10 | namespace Aliyun.MQ.Runtime.Internal.Auth 11 | { 12 | internal class MQSigner : IServiceSigner 13 | { 14 | #region Immutable Properties 15 | 16 | static readonly Regex CompressWhitespaceRegex = new Regex("\\s+"); 17 | const SigningAlgorithm SignerAlgorithm = SigningAlgorithm.HmacSHA1; 18 | 19 | #endregion 20 | 21 | #region Public Signing Methods 22 | 23 | public void Sign(IRequest request, 24 | string accessKeyId, 25 | string secretAccessKey, 26 | string stsToken) 27 | { 28 | var signingRequest = SignRequest(request, secretAccessKey); 29 | var signingResult = new StringBuilder(); 30 | signingResult.AppendFormat("{0} {1}:{2}", 31 | Constants.MQ_AUTHORIZATION_HEADER_PREFIX, 32 | accessKeyId, 33 | signingRequest); 34 | request.Headers[Constants.AuthorizationHeader] = signingResult.ToString(); 35 | 36 | if (!string.IsNullOrEmpty(stsToken)) 37 | { 38 | request.Headers[Constants.SecurityToken] = stsToken; 39 | } 40 | } 41 | 42 | public string SignRequest(IRequest request, string secretAccessKey) 43 | { 44 | InitializeHeaders(request.Headers); 45 | 46 | var parametersToCanonicalize = GetParametersToCanonicalize(request); 47 | var canonicalParameters = CanonicalizeQueryParameters(parametersToCanonicalize); 48 | var canonicalResource = CanonicalizeResource(canonicalParameters, request.ResourcePath); 49 | var canonicalHeaders = CanonoicalizeHeaders(request.Headers); 50 | 51 | var canonicalRequest = CanonicalizeRequest(request.HttpMethod, 52 | request.Headers, 53 | canonicalHeaders, 54 | canonicalResource); 55 | 56 | return ComputeSignature(secretAccessKey, canonicalRequest); 57 | } 58 | 59 | #endregion 60 | 61 | #region Public Signing Helpers 62 | 63 | private static void InitializeHeaders(IDictionary headers) 64 | { 65 | // clean up any prior signature in the headers if resigning 66 | headers.Remove(Constants.AuthorizationHeader); 67 | } 68 | 69 | public static string ComputeSignature(string secretAccessKey, string canonicalRequest) 70 | { 71 | return ComputeKeyedHash(SignerAlgorithm, secretAccessKey, canonicalRequest); 72 | } 73 | 74 | public static string ComputeKeyedHash(SigningAlgorithm algorithm, string key, string data) 75 | { 76 | return CryptoUtilFactory.CryptoInstance.HMACSign(data, key, algorithm); 77 | } 78 | 79 | #endregion 80 | 81 | #region Private Signing Helpers 82 | 83 | protected static string CanonoicalizeHeaders(IDictionary headers) 84 | { 85 | var headersToCanonicalize = new SortedDictionary(StringComparer.OrdinalIgnoreCase); 86 | if (headers != null && headers.Count > 0) 87 | { 88 | foreach (var header in headers.Where(header => 89 | header.Key.ToLowerInvariant().StartsWith(Constants.X_MQ_HEADER_PREFIX))) 90 | { 91 | headersToCanonicalize.Add(header.Key.ToLowerInvariant(), header.Value); 92 | } 93 | } 94 | return CanonicalizeHeaders(headersToCanonicalize); 95 | } 96 | 97 | protected static string CanonicalizeResource(string canonicalQueryString, string resourcePath) 98 | { 99 | var canonicalResource = new StringBuilder(); 100 | canonicalResource.Append(CanonicalizeResourcePath(resourcePath)); 101 | if (canonicalQueryString != string.Empty) 102 | canonicalResource.AppendFormat("?{0}", canonicalQueryString); 103 | return canonicalResource.ToString(); 104 | } 105 | 106 | protected static string CanonicalizeResourcePath(string resourcePath) 107 | { 108 | if (string.IsNullOrEmpty(resourcePath) || resourcePath == "/") 109 | return "/"; 110 | 111 | var pathSegments = resourcePath.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); 112 | var canonicalizedPath = new StringBuilder(); 113 | foreach (var segment in pathSegments) 114 | { 115 | canonicalizedPath.AppendFormat("/{0}", segment); 116 | } 117 | 118 | if (resourcePath.EndsWith("/", StringComparison.Ordinal)) 119 | canonicalizedPath.Append("/"); 120 | 121 | return canonicalizedPath.ToString(); 122 | } 123 | 124 | protected static string CanonicalizeRequest(string httpMethod, 125 | IDictionary headers, 126 | string canonicalHeaders, 127 | string canonicalResource) 128 | { 129 | var canonicalRequest = new StringBuilder(); 130 | canonicalRequest.AppendFormat("{0}\n", httpMethod); 131 | 132 | var contentMD5 = string.Empty; 133 | if (headers.ContainsKey(Constants.ContentMD5Header)) 134 | contentMD5 = headers[Constants.ContentMD5Header]; 135 | canonicalRequest.AppendFormat("{0}\n", contentMD5); 136 | 137 | var contentType = string.Empty; 138 | if (headers.ContainsKey(Constants.ContentTypeHeader)) 139 | contentType = headers[Constants.ContentTypeHeader]; 140 | canonicalRequest.AppendFormat("{0}\n", contentType); 141 | 142 | canonicalRequest.AppendFormat("{0}\n", headers[Constants.DateHeader]); 143 | canonicalRequest.Append(canonicalHeaders); 144 | canonicalRequest.Append(canonicalResource); 145 | 146 | return canonicalRequest.ToString(); 147 | } 148 | 149 | protected static string CanonicalizeHeaders(ICollection> sortedHeaders) 150 | { 151 | if (sortedHeaders == null || sortedHeaders.Count == 0) 152 | return string.Empty; 153 | 154 | var builder = new StringBuilder(); 155 | foreach (var entry in sortedHeaders) 156 | { 157 | builder.Append(entry.Key.ToLower(CultureInfo.InvariantCulture)); 158 | builder.Append(":"); 159 | builder.Append(CompressSpaces(entry.Value)); 160 | builder.Append("\n"); 161 | } 162 | 163 | return builder.ToString(); 164 | } 165 | 166 | protected static IDictionary GetParametersToCanonicalize(IRequest request) 167 | { 168 | var parametersToCanonicalize = new Dictionary(); 169 | 170 | if (request.SubResources != null && request.SubResources.Count > 0) 171 | { 172 | foreach (var subResource in request.SubResources) 173 | { 174 | parametersToCanonicalize.Add(subResource.Key, subResource.Value); 175 | } 176 | } 177 | 178 | if (request.Parameters != null && request.Parameters.Count > 0) 179 | { 180 | foreach (var queryParameter in request.Parameters.Where(queryParameter => queryParameter.Value != null)) 181 | { 182 | parametersToCanonicalize.Add(queryParameter.Key, queryParameter.Value); 183 | } 184 | } 185 | 186 | return parametersToCanonicalize; 187 | } 188 | 189 | protected static string CanonicalizeQueryParameters(IDictionary parameters) 190 | { 191 | if (parameters == null || parameters.Count == 0) 192 | return string.Empty; 193 | 194 | var canonicalQueryString = new StringBuilder(); 195 | var queryParams = new SortedDictionary(parameters, StringComparer.Ordinal); 196 | foreach (var p in queryParams) 197 | { 198 | if (canonicalQueryString.Length > 0) 199 | canonicalQueryString.Append("&"); 200 | if (string.IsNullOrEmpty(p.Value)) 201 | canonicalQueryString.AppendFormat("{0}=", p.Key); 202 | else 203 | canonicalQueryString.AppendFormat("{0}={1}", p.Key, p.Value); 204 | } 205 | 206 | return canonicalQueryString.ToString(); 207 | } 208 | 209 | static string CompressSpaces(string data) 210 | { 211 | if (data == null || !data.Contains(" ")) 212 | return data; 213 | 214 | var compressed = CompressWhitespaceRegex.Replace(data, " "); 215 | return compressed; 216 | } 217 | 218 | #endregion 219 | } 220 | } 221 | --------------------------------------------------------------------------------