Format all code (#190)
This commit is contained in:
Родитель
e34b3a382c
Коммит
0d16226e19
|
@ -22,4 +22,4 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
|||
/// </summary>
|
||||
public const int CloseConnectionMessageType = 11;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
||||
{
|
||||
|
@ -24,4 +21,4 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
|||
/// <returns>A value that is <c>true</c> if the <see cref="ServerlessMessage"/> was successfully parsed; otherwise, <c>false</c>.</returns>
|
||||
bool TryParseMessage(ref ReadOnlySequence<byte> input, out ServerlessMessage message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ namespace Microsoft.AspNetCore.Internal
|
|||
public override bool CanRead => false;
|
||||
public override bool CanSeek => false;
|
||||
public override bool CanWrite => true;
|
||||
|
||||
public override long Position
|
||||
{
|
||||
get => throw new NotSupportedException();
|
||||
|
@ -258,10 +259,16 @@ namespace Microsoft.AspNetCore.Internal
|
|||
Debug.Assert(_bytesWritten == totalWritten + _position);
|
||||
}
|
||||
|
||||
public override void Flush() { }
|
||||
public override void Flush()
|
||||
{
|
||||
}
|
||||
|
||||
public override Task FlushAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
||||
|
||||
public override int Read(byte[] buffer, int offset, int count) => throw new NotSupportedException();
|
||||
|
||||
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
|
||||
|
||||
public override void SetLength(long value) => throw new NotSupportedException();
|
||||
|
||||
public override void WriteByte(byte value)
|
||||
|
@ -341,4 +348,4 @@ namespace Microsoft.AspNetCore.Internal
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using MessagePack;
|
||||
|
||||
namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
||||
|
@ -187,4 +186,4 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,9 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
||||
{
|
||||
|
@ -99,4 +97,4 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
@ -57,4 +56,4 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,7 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using MessagePack;
|
||||
|
||||
|
@ -49,4 +46,4 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
|||
return invocationMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,4 +32,4 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols
|
|||
[JsonProperty(PropertyName = "error")]
|
||||
public string Error { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
if (request?.Headers.TryGetValue(AuthHeaderName, out var authHeader) == true)
|
||||
{
|
||||
var authHeaderValue = authHeader.ToString();
|
||||
var authHeaderValue = authHeader.ToString();
|
||||
if (authHeaderValue.StartsWith(BearerPrefix, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var token = authHeaderValue.Substring(BearerPrefix.Length);
|
||||
|
@ -59,7 +59,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
// 'nbf' claim is greater than 'exp' claim
|
||||
ex is SecurityTokenInvalidLifetimeException ||
|
||||
|
||||
// Signature is not properly formatted.
|
||||
// Signature is not properly formatted.
|
||||
ex is SecurityTokenInvalidSignatureException ||
|
||||
|
||||
// 1. 'exp' claim is missing and TokenValidationParameters.RequireExpirationTime is true.
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
|
||||
|
@ -16,7 +15,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
/// User identity for a SignalR connection
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Custom claims that added to SignalR access token.
|
||||
/// </summary>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
|
|
|
@ -9,6 +9,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("accessToken")]
|
||||
public string AccessToken { get; set; }
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ using Microsoft.Extensions.Configuration;
|
|||
using Newtonsoft.Json;
|
||||
using BindingData = System.Collections.Generic.IReadOnlyDictionary<string, object>;
|
||||
using BindingDataContract = System.Collections.Generic.IReadOnlyDictionary<string, System.Type>;
|
||||
|
||||
// Func to transform Attribute,BindingData into value for cloned attribute property/constructor arg
|
||||
// Attribute is the new cloned attribute - null if constructor arg (new cloned attr not created yet)
|
||||
using BindingDataResolver = System.Func<System.Attribute, System.Collections.Generic.IReadOnlyDictionary<string, object>, object>;
|
||||
|
@ -21,6 +22,7 @@ using BindingDataResolver = System.Func<System.Attribute, System.Collections.Gen
|
|||
using Validator = System.Action<object>;
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
// Clone an attribute and resolve it.
|
||||
|
@ -98,7 +100,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
// transforms binding data to appropriate resolver (appsetting, autoresolve, or originalValue)
|
||||
private BindingDataResolver GetResolver(PropertyInfo propInfo, INameResolver nameResolver, BindingDataContract contract)
|
||||
{
|
||||
// Do the attribute lookups once upfront, and then cache them (via func closures) for subsequent runtime usage.
|
||||
// Do the attribute lookups once upfront, and then cache them (via func closures) for subsequent runtime usage.
|
||||
object originalValue = propInfo.GetValue(_source);
|
||||
ConnectionStringAttribute connStrAttr = propInfo.GetCustomAttribute<ConnectionStringAttribute>();
|
||||
AppSettingAttribute appSettingAttr = propInfo.GetCustomAttribute<AppSettingAttribute>();
|
||||
|
@ -109,7 +111,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
validator(originalValue);
|
||||
|
||||
// No special attributes, treat as literal.
|
||||
// No special attributes, treat as literal.
|
||||
return (newAttr, bindingData) => originalValue;
|
||||
}
|
||||
|
||||
|
@ -119,7 +121,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
throw new InvalidOperationException($"Property '{propInfo.Name}' can only be annotated with one of the types {nameof(AppSettingAttribute)}, {nameof(AutoResolveAttribute)}, and {nameof(ConnectionStringAttribute)}.");
|
||||
}
|
||||
|
||||
// attributes only work on string properties.
|
||||
// attributes only work on string properties.
|
||||
if (propInfo.PropertyType != typeof(string))
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(ConnectionStringAttribute)}, {nameof(AutoResolveAttribute)}, or {nameof(AppSettingAttribute)} property '{propInfo.Name}' must be of type string.");
|
||||
|
@ -144,7 +146,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return GetAutoResolveResolver(str, autoResolveAttr, nameResolver, propInfo, contract, validator);
|
||||
}
|
||||
|
||||
// Apply AutoResolve attribute
|
||||
// Apply AutoResolve attribute
|
||||
internal BindingDataResolver GetAutoResolveResolver(string originalValue, AutoResolveAttribute autoResolveAttr, INameResolver nameResolver, PropertyInfo propInfo, BindingDataContract contract, Validator validator)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(originalValue))
|
||||
|
@ -187,19 +189,19 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
throw new InvalidOperationException($"Unable to resolve the value for property '{propInfo.DeclaringType.Name}.{propInfo.Name}'. Make sure the setting exists and has a valid value.");
|
||||
}
|
||||
|
||||
// validate after the %% is substituted.
|
||||
// validate after the %% is substituted.
|
||||
validator(resolvedValue);
|
||||
|
||||
return (newAttr, bindingData) => resolvedValue;
|
||||
}
|
||||
|
||||
// Run validition. This needs to be run at different stages.
|
||||
// Run validition. This needs to be run at different stages.
|
||||
// In general, run as early as possible. If there are { } tokens, then we can't run until runtime.
|
||||
// But if there are no { }, we can run statically.
|
||||
// But if there are no { }, we can run statically.
|
||||
// If there's no [AutoResolve], [AppSettings], then we can run immediately.
|
||||
private static Validator GetValidatorFunc(PropertyInfo propInfo, bool dontLogValues)
|
||||
{
|
||||
// This implicitly caches the attribute lookup once and then shares for each runtime invocation.
|
||||
// This implicitly caches the attribute lookup once and then shares for each runtime invocation.
|
||||
var attrs = propInfo.GetCustomAttributes<ValidationAttribute>();
|
||||
|
||||
return (value) =>
|
||||
|
@ -225,8 +227,8 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
};
|
||||
}
|
||||
|
||||
// Resolve for AutoResolve.Default templates.
|
||||
// These only have access to the {sys} builtin variable and don't get access to trigger binding data.
|
||||
// Resolve for AutoResolve.Default templates.
|
||||
// These only have access to the {sys} builtin variable and don't get access to trigger binding data.
|
||||
internal static BindingDataResolver GetBuiltinTemplateResolver(string originalValue, INameResolver nameResolver, Validator validator)
|
||||
{
|
||||
string resolvedValue = nameResolver.ResolveWholeString(originalValue);
|
||||
|
@ -234,13 +236,13 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
var template = BindingTemplate.FromString(resolvedValue);
|
||||
if (!template.HasParameters)
|
||||
{
|
||||
// No { } tokens, bind eagerly up front.
|
||||
// No { } tokens, bind eagerly up front.
|
||||
validator(originalValue);
|
||||
}
|
||||
|
||||
SystemBindingData.ValidateStaticContract(template);
|
||||
|
||||
// For static default contracts, we only have access to the built in binding data.
|
||||
// For static default contracts, we only have access to the built in binding data.
|
||||
return (newAttr, bindingData) =>
|
||||
{
|
||||
var newValue = template.Bind(SystemBindingData.GetSystemBindingData(bindingData));
|
||||
|
@ -257,7 +259,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
if (!template.HasParameters)
|
||||
{
|
||||
// No { } tokens, bind eagerly up front.
|
||||
// No { } tokens, bind eagerly up front.
|
||||
validator(resolvedValue);
|
||||
}
|
||||
|
||||
|
@ -334,7 +336,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
if (bindingData == null)
|
||||
{
|
||||
// Skip validation if no binding data provided. We can't do the { } substitutions.
|
||||
// Skip validation if no binding data provided. We can't do the { } substitutions.
|
||||
return template?.Pattern;
|
||||
}
|
||||
|
||||
|
@ -363,7 +365,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
}
|
||||
}
|
||||
|
||||
// return the default policy
|
||||
// return the default policy
|
||||
return new DefaultResolutionPolicy();
|
||||
}
|
||||
|
||||
|
@ -377,16 +379,16 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
/// Class providing support for built in system binding expressions
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// It's expected this class is created and added to the binding data.
|
||||
/// It's expected this class is created and added to the binding data.
|
||||
/// </remarks>
|
||||
private class SystemBindingData
|
||||
{
|
||||
// The public name for this binding in the binding expressions.
|
||||
// The public name for this binding in the binding expressions.
|
||||
public const string Name = "sys";
|
||||
|
||||
// An internal name for this binding that uses characters that gaurantee it can't be overwritten by a user.
|
||||
// This is never seen by the user.
|
||||
// This ensures that we can always unambiguously retrieve this later.
|
||||
// An internal name for this binding that uses characters that gaurantee it can't be overwritten by a user.
|
||||
// This is never seen by the user.
|
||||
// This ensures that we can always unambiguously retrieve this later.
|
||||
private const string InternalKeyName = "$sys";
|
||||
|
||||
private static readonly IReadOnlyDictionary<string, Type> DefaultSystemContract = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase)
|
||||
|
@ -395,13 +397,13 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
};
|
||||
|
||||
/// <summary>
|
||||
/// The method name that the binding lives in.
|
||||
/// The method name can be override by the <see cref="FunctionNameAttribute"/>
|
||||
/// The method name that the binding lives in.
|
||||
/// The method name can be override by the <see cref="FunctionNameAttribute"/>
|
||||
/// </summary>
|
||||
public string MethodName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the current UTC date.
|
||||
/// Get the current UTC date.
|
||||
/// </summary>
|
||||
public DateTime UtcNow => DateTime.UtcNow;
|
||||
|
||||
|
@ -411,7 +413,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
public Guid RandGuid => Guid.NewGuid();
|
||||
|
||||
// Given a full bindingData, create a binding data with just the system object .
|
||||
// This can be used when resolving default contracts that shouldn't be using an instance binding data.
|
||||
// This can be used when resolving default contracts that shouldn't be using an instance binding data.
|
||||
internal static IReadOnlyDictionary<string, object> GetSystemBindingData(IReadOnlyDictionary<string, object> bindingData)
|
||||
{
|
||||
var data = GetFromData(bindingData);
|
||||
|
@ -422,8 +424,8 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return systemBindingData;
|
||||
}
|
||||
|
||||
// Validate that a template only uses static (non-instance) binding variables.
|
||||
// Enforces we're not referring to other data from the trigger.
|
||||
// Validate that a template only uses static (non-instance) binding variables.
|
||||
// Enforces we're not referring to other data from the trigger.
|
||||
internal static void ValidateStaticContract(BindingTemplate template)
|
||||
{
|
||||
try
|
||||
|
@ -438,12 +440,12 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
internal void AddToBindingData(Dictionary<string, object> bindingData)
|
||||
{
|
||||
// User data takes precedence, so if 'sys' already exists, add via the internal name.
|
||||
// User data takes precedence, so if 'sys' already exists, add via the internal name.
|
||||
string sysName = bindingData.ContainsKey(SystemBindingData.Name) ? SystemBindingData.InternalKeyName : SystemBindingData.Name;
|
||||
bindingData[sysName] = this;
|
||||
}
|
||||
|
||||
// Given per-instance binding data, extract just the system binding data object from it.
|
||||
// Given per-instance binding data, extract just the system binding data object from it.
|
||||
private static SystemBindingData GetFromData(IReadOnlyDictionary<string, object> bindingData)
|
||||
{
|
||||
object val;
|
||||
|
@ -459,10 +461,10 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
}
|
||||
}
|
||||
|
||||
// Helpers for providing default behavior for an IAttributeInvokeDescriptor that
|
||||
// convert between a TAttribute and a string representation (invoke string).
|
||||
// Properties with [AutoResolve] are the interesting ones to serialize and deserialize.
|
||||
// Assume any property without a [AutoResolve] attribute is read-only and so doesn't need to be included in the invoke string.
|
||||
// Helpers for providing default behavior for an IAttributeInvokeDescriptor that
|
||||
// convert between a TAttribute and a string representation (invoke string).
|
||||
// Properties with [AutoResolve] are the interesting ones to serialize and deserialize.
|
||||
// Assume any property without a [AutoResolve] attribute is read-only and so doesn't need to be included in the invoke string.
|
||||
private static class DefaultAttributeInvokerDescriptor
|
||||
{
|
||||
public static TAttribute FromInvokeString(AttributeCloner<TAttribute> cloner, string invokeString)
|
||||
|
@ -473,8 +475,8 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
}
|
||||
|
||||
// Instantiating new attributes can be tricky since sometimes the arg is to the ctor and sometimes
|
||||
// its a property setter. AttributeCloner already solves this, so use it here to do the actual attribute instantiation.
|
||||
// This has an instantiation problem similar to what Attribute Cloner has
|
||||
// its a property setter. AttributeCloner already solves this, so use it here to do the actual attribute instantiation.
|
||||
// This has an instantiation problem similar to what Attribute Cloner has
|
||||
if (invokeString[0] == '{')
|
||||
{
|
||||
var propertyValues = JsonConvert.DeserializeObject<IDictionary<string, string>>(invokeString);
|
||||
|
@ -516,9 +518,9 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resolution policy for { } in binding templates.
|
||||
/// The default policy is just a direct substitution for the binding data.
|
||||
/// Derived policies can enforce formatting / escaping when they do injection.
|
||||
/// Resolution policy for { } in binding templates.
|
||||
/// The default policy is just a direct substitution for the binding data.
|
||||
/// Derived policies can enforce formatting / escaping when they do injection.
|
||||
/// </summary>
|
||||
private class DefaultResolutionPolicy : IResolutionPolicy
|
||||
{
|
||||
|
@ -529,4 +531,5 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
}
|
||||
}
|
||||
}
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.WebJobs.Host.Bindings;
|
||||
using Microsoft.Azure.WebJobs.Host.Protocols;
|
||||
|
@ -11,7 +10,7 @@ using Microsoft.Extensions.Configuration;
|
|||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
// Helper class for implementing IBinding with the attribute resolver pattern.
|
||||
// Helper class for implementing IBinding with the attribute resolver pattern.
|
||||
internal abstract class BindingBase<TAttribute> : IBinding
|
||||
where TAttribute : Attribute
|
||||
{
|
||||
|
@ -51,7 +50,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public Task<IValueProvider> BindAsync(object value, ValueBindingContext context)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public ParameterDescriptor ToParameterDescriptor()
|
||||
|
@ -59,5 +58,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Azure.WebJobs.Host.Bindings;
|
||||
using Microsoft.Azure.WebJobs.Host.Protocols;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return Task.FromResult<IValueProvider>(new SecurityTokenValidationValueProvider(null, ""));
|
||||
}
|
||||
|
||||
return Task.FromResult<IValueProvider>(new SecurityTokenValidationValueProvider(securityTokenValidator.ValidateToken(request), ""));
|
||||
return Task.FromResult<IValueProvider>(new SecurityTokenValidationValueProvider(securityTokenValidator.ValidateToken(request), ""));
|
||||
}
|
||||
|
||||
public Task<IValueProvider> BindAsync(BindingContext context)
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
// todo: fix invoke string in another PR
|
||||
public SecurityTokenValidationValueProvider(SecurityTokenResult result, string invokeString)
|
||||
{
|
||||
this.result= result;
|
||||
this.result = result;
|
||||
this.invokeString = invokeString;
|
||||
}
|
||||
|
||||
|
@ -31,4 +31,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public Type Type => typeof(SecurityTokenResult);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,4 +47,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return info;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
|
@ -83,4 +81,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -51,10 +51,10 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
var serviceHubContext = await GetHubContextAsync();
|
||||
var negotiateResponse = await serviceHubContext.NegotiateAsync(new NegotiationOptions()
|
||||
{
|
||||
UserId = userId,
|
||||
Claims = BuildJwtClaims(claims, AzureSignalRUserPrefix).ToList(),
|
||||
HttpContext = httpContext
|
||||
{
|
||||
UserId = userId,
|
||||
Claims = BuildJwtClaims(claims, AzureSignalRUserPrefix).ToList(),
|
||||
HttpContext = httpContext
|
||||
});
|
||||
return new SignalRConnectionInfo
|
||||
{
|
||||
|
|
|
@ -8,13 +8,21 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
internal interface IAzureSignalRSender
|
||||
{
|
||||
Task SendToAll(SignalRData data);
|
||||
|
||||
Task SendToConnection(string connectionId, SignalRData data);
|
||||
|
||||
Task SendToUser(string userId, SignalRData data);
|
||||
|
||||
Task SendToGroup(string group, SignalRData data);
|
||||
|
||||
Task AddUserToGroup(SignalRGroupAction action);
|
||||
|
||||
Task RemoveUserFromGroup(SignalRGroupAction action);
|
||||
|
||||
Task RemoveUserFromAllGroups(SignalRGroupAction action);
|
||||
|
||||
Task AddConnectionToGroup(SignalRGroupAction action);
|
||||
|
||||
Task RemoveConnectionFromGroup(SignalRGroupAction action);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.Azure.SignalR;
|
||||
using Microsoft.Azure.SignalR;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
|
|
|
@ -65,4 +65,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return configuration.GetReloadToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public ValueTask<IServiceHubContext> GetAsync(string hubName)
|
||||
{
|
||||
var pair = store.GetOrAdd(hubName,
|
||||
var pair = store.GetOrAdd(hubName,
|
||||
(new Lazy<Task<IServiceHubContext>>(
|
||||
() => ServiceManager.CreateHubContextAsync(hubName)), default));
|
||||
return GetAsyncCore(hubName, pair);
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
|
@ -43,13 +43,13 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
throw new NotSupportedException($"{nameof(ISecurityTokenValidator)} already injected.");
|
||||
}
|
||||
|
||||
|
||||
builder.Services
|
||||
.AddSingleton<ISecurityTokenValidator>(s =>
|
||||
new DefaultSecurityTokenValidator(configureTokenValidationParameters));
|
||||
|
||||
builder.Services.
|
||||
TryAddSingleton<ISignalRConnectionInfoConfigurer>(s =>
|
||||
TryAddSingleton<ISignalRConnectionInfoConfigurer>(s =>
|
||||
internalSignalRConnectionInfoConfigurer);
|
||||
|
||||
return builder;
|
||||
|
|
|
@ -2,13 +2,12 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
// Then all resolve jobs are put in resolvers, we can also remove the SignalROption after we apply resolve jobs inside bindings.
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for SignalR Service integration
|
||||
/// </summary>
|
||||
|
|
|
@ -14,4 +14,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
internal static IServiceManagerStore ServiceManagerStore { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -35,4 +35,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
public const string Connected = "connected";
|
||||
public const string Disconnected = "disconnected";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -8,4 +8,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
public static readonly string EmptyConnectionStringErrorMessageFormat =
|
||||
$"The SignalR Service connection string or endpoints are not set.";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,4 +9,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,4 +15,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
{
|
||||
internal class SignalRTriggerParametersNotMatchException : SignalRTriggerException
|
||||
{
|
||||
public SignalRTriggerParametersNotMatchException(int excepted, int actual) : base(
|
||||
|
@ -10,4 +10,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,4 +4,4 @@
|
|||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("SignalRServiceExtension.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f33a29044fa9d740c9b3213a93e57c84b472c84e0b8a0e1ae48e67a9f8f6de9d5f7f3d52ac23e48ac51801f1dc950abe901da34d2a9e3baadb141a17c77ef3c565dd5ee5054b91cf63bb3c6ab83f72ab3aafe93d0fc3c2348b764fafb0b1c0733de51459aeab46580384bf9d74c4e28164b7cde247f891ba07891c9d872ad2bb")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
|
@ -1,8 +1,8 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using Microsoft.Azure.WebJobs.Description;
|
||||
using System;
|
||||
using Microsoft.Azure.WebJobs.Description;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
|
@ -11,4 +11,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
public class SecurityTokenValidationAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,8 +2,6 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.Azure.WebJobs.Description;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
|
@ -25,4 +23,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public string[] ClaimTypeList { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
|
||||
using Microsoft.Azure.WebJobs.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
[assembly: WebJobsStartup(typeof(SignalRWebJobsStartup))]
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
public class SignalRWebJobsStartup : IWebJobsStartup
|
||||
|
|
|
@ -1,64 +1,67 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
public class InvocationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The arguments of invocation message.
|
||||
/// </summary>
|
||||
public object[] Arguments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The error message of close connection event.
|
||||
/// Only close connection message can have this property, and it can be empty if connections close with no error.
|
||||
/// </summary>
|
||||
public string Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The category of the message.
|
||||
/// </summary>
|
||||
public string Category { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The event of the message.
|
||||
/// </summary>
|
||||
public string Event { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The hub which message belongs to.
|
||||
/// </summary>
|
||||
public string Hub { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The connection-id of the client which send the message.
|
||||
/// </summary>
|
||||
public string ConnectionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user identity of the client which send the message.
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The headers of request.
|
||||
/// Headers with duplicated key will be joined by comma.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The query of the request when client connect to the service.
|
||||
/// Queries with duplicated key will be joined by comma.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Query { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The claims of the client.
|
||||
/// If you multiple claims have the same key, only the first one will be reserved.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Claims { get; set; }
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
public class InvocationContext
|
||||
{
|
||||
/// <summary>
|
||||
/// The arguments of invocation message.
|
||||
/// </summary>
|
||||
public object[] Arguments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The error message of close connection event.
|
||||
/// Only close connection message can have this property, and it can be empty if connections close with no error.
|
||||
/// </summary>
|
||||
public string Error { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The category of the message.
|
||||
/// </summary>
|
||||
public string Category { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The event of the message.
|
||||
/// </summary>
|
||||
public string Event { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The hub which message belongs to.
|
||||
/// </summary>
|
||||
public string Hub { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The connection-id of the client which send the message.
|
||||
/// </summary>
|
||||
public string ConnectionId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user identity of the client which send the message.
|
||||
/// </summary>
|
||||
public string UserId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The headers of request.
|
||||
/// Headers with duplicated key will be joined by comma.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The query of the request when client connect to the service.
|
||||
/// Queries with duplicated key will be joined by comma.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Query { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The claims of the client.
|
||||
/// If you multiple claims have the same key, only the first one will be reserved.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Claims { get; set; }
|
||||
}
|
||||
}
|
|
@ -12,4 +12,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public AccessKey[] AccessKeys { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +1,15 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal class SignalRConnectMethodExecutor : SignalRMethodExecutor
|
||||
{
|
||||
public SignalRConnectMethodExecutor(IRequestResolver resolver, ExecutionContext executionContext): base(resolver, executionContext)
|
||||
public SignalRConnectMethodExecutor(IRequestResolver resolver, ExecutionContext executionContext) : base(resolver, executionContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,4 +29,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return new HttpResponseMessage(HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,22 +1,17 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Azure.SignalR.Serverless.Protocols;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal class SignalRDisconnectMethodExecutor: SignalRMethodExecutor
|
||||
internal class SignalRDisconnectMethodExecutor : SignalRMethodExecutor
|
||||
{
|
||||
public SignalRDisconnectMethodExecutor(IRequestResolver resolver, ExecutionContext executionContext): base(resolver, executionContext)
|
||||
public SignalRDisconnectMethodExecutor(IRequestResolver resolver, ExecutionContext executionContext) : base(resolver, executionContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -34,4 +29,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return new HttpResponseMessage(HttpStatusCode.OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,12 +2,8 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.AspNetCore.SignalR.Protocol;
|
||||
|
@ -15,9 +11,9 @@ using InvocationMessage = Microsoft.Azure.SignalR.Serverless.Protocols.Invocatio
|
|||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal class SignalRInvocationMethodExecutor: SignalRMethodExecutor
|
||||
internal class SignalRInvocationMethodExecutor : SignalRMethodExecutor
|
||||
{
|
||||
public SignalRInvocationMethodExecutor(IRequestResolver resolver, ExecutionContext executionContext): base(resolver, executionContext)
|
||||
public SignalRInvocationMethodExecutor(IRequestResolver resolver, ExecutionContext executionContext) : base(resolver, executionContext)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -48,7 +44,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
if (!functionResult.Succeeded)
|
||||
{
|
||||
var errorMessage = functionResult.Exception?.InnerException?.Message ??
|
||||
functionResult.Exception?.Message ??
|
||||
functionResult.Exception?.Message ??
|
||||
"Method execution failed.";
|
||||
completionMessage = CompletionMessage.WithError(message.InvocationId, errorMessage);
|
||||
response = new HttpResponseMessage(HttpStatusCode.OK);
|
||||
|
@ -81,4 +77,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Host.Executors;
|
||||
|
@ -58,4 +58,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@
|
|||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.WebJobs.Host.Executors;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
|
@ -14,4 +13,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
Task<HttpResponseMessage> ExecuteAsync(HttpRequestMessage req, CancellationToken token = default);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,4 +33,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return (await StaticServiceHubContextStore.Get().GetAsync(invocationContext.Hub)).UserGroups;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.WebJobs.Host.Listeners;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal class NullListener: IListener
|
||||
internal class NullListener : IListener
|
||||
{
|
||||
public NullListener()
|
||||
{
|
||||
|
@ -32,4 +31,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,7 +36,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
return contentType == Constants.JsonContentType || contentType == Constants.MessagePackContentType;
|
||||
}
|
||||
|
||||
// The algorithm is defined in spec: Hex_encoded(HMAC_SHA256(access-key, connection-id))
|
||||
// The algorithm is defined in spec: Hex_encoded(HMAC_SHA256(access-key, connection-id))
|
||||
public bool ValidateSignature(HttpRequestMessage request, AccessKey[] accessKeys)
|
||||
{
|
||||
if (!_validateSignature)
|
||||
|
|
|
@ -7,7 +7,6 @@ using System.IdentityModel.Tokens.Jwt;
|
|||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.Azure.SignalR.Management;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.WebJobs.Host;
|
||||
|
@ -31,5 +30,6 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
/// </summary>
|
||||
public abstract Task FilterAsync(InvocationContext invocationContext, CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
}
|
||||
}
|
|
@ -13,4 +13,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
public class SignalRIgnoreAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,4 +15,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
public class SignalRParameterAttribute : Attribute
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
}
|
||||
|
||||
public SignalRTriggerAttribute(string hubName, string category, string @event): this(hubName, category, @event, Array.Empty<string>())
|
||||
public SignalRTriggerAttribute(string hubName, string category, string @event) : this(hubName, category, @event, Array.Empty<string>())
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,248 +1,251 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Azure.SignalR;
|
||||
using Microsoft.Azure.WebJobs.Host.Bindings;
|
||||
using Microsoft.Azure.WebJobs.Host.Listeners;
|
||||
using Microsoft.Azure.WebJobs.Host.Protocols;
|
||||
using Microsoft.Azure.WebJobs.Host.Bindings;
|
||||
using Microsoft.Azure.WebJobs.Host.Listeners;
|
||||
using Microsoft.Azure.WebJobs.Host.Protocols;
|
||||
using Microsoft.Azure.WebJobs.Host.Triggers;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal class SignalRTriggerBinding : ITriggerBinding
|
||||
{
|
||||
private const string ReturnParameterKey = "$return";
|
||||
|
||||
private readonly ParameterInfo _parameterInfo;
|
||||
private readonly SignalRTriggerAttribute _attribute;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal class SignalRTriggerBinding : ITriggerBinding
|
||||
{
|
||||
private const string ReturnParameterKey = "$return";
|
||||
|
||||
private readonly ParameterInfo _parameterInfo;
|
||||
private readonly SignalRTriggerAttribute _attribute;
|
||||
private readonly ISignalRTriggerDispatcher _dispatcher;
|
||||
private readonly AccessKey[] _accessKeys;
|
||||
|
||||
public SignalRTriggerBinding(ParameterInfo parameterInfo, SignalRTriggerAttribute attribute, ISignalRTriggerDispatcher dispatcher, AccessKey[] accessKeys)
|
||||
{
|
||||
_parameterInfo = parameterInfo ?? throw new ArgumentNullException(nameof(parameterInfo));
|
||||
_attribute = attribute ?? throw new ArgumentNullException(nameof(attribute));
|
||||
private readonly AccessKey[] _accessKeys;
|
||||
|
||||
public SignalRTriggerBinding(ParameterInfo parameterInfo, SignalRTriggerAttribute attribute, ISignalRTriggerDispatcher dispatcher, AccessKey[] accessKeys)
|
||||
{
|
||||
_parameterInfo = parameterInfo ?? throw new ArgumentNullException(nameof(parameterInfo));
|
||||
_attribute = attribute ?? throw new ArgumentNullException(nameof(attribute));
|
||||
_dispatcher = dispatcher ?? throw new ArgumentNullException(nameof(dispatcher));
|
||||
_accessKeys = accessKeys ?? throw new ArgumentNullException(nameof(accessKeys));
|
||||
BindingDataContract = CreateBindingContract(_attribute, _parameterInfo);
|
||||
}
|
||||
|
||||
public Task<ITriggerData> BindAsync(object value, ValueBindingContext context)
|
||||
{
|
||||
var bindingData = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (value is SignalRTriggerEvent triggerEvent)
|
||||
{
|
||||
var bindingContext = triggerEvent.Context;
|
||||
|
||||
// If ParameterNames are set, bind them in order.
|
||||
// To reduce undefined situation, number of arguments should keep consist with that of ParameterNames
|
||||
if (_attribute.ParameterNames != null && _attribute.ParameterNames.Length != 0)
|
||||
{
|
||||
if (bindingContext.Arguments == null ||
|
||||
bindingContext.Arguments.Length != _attribute.ParameterNames.Length)
|
||||
{
|
||||
throw new SignalRTriggerParametersNotMatchException(_attribute.ParameterNames.Length, bindingContext.Arguments?.Length ?? 0);
|
||||
}
|
||||
|
||||
AddParameterNamesBindingData(bindingData, _attribute.ParameterNames, bindingContext.Arguments);
|
||||
}
|
||||
|
||||
return Task.FromResult<ITriggerData>(new TriggerData(new SignalRTriggerValueProvider(_parameterInfo, bindingContext), bindingData)
|
||||
{
|
||||
ReturnValueProvider = triggerEvent.TaskCompletionSource == null ? null : new TriggerReturnValueProvider(triggerEvent.TaskCompletionSource),
|
||||
});
|
||||
}
|
||||
|
||||
return Task.FromResult<ITriggerData>(null);
|
||||
}
|
||||
|
||||
public Task<IListener> CreateListenerAsync(ListenerFactoryContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
// It's not a real listener, and it doesn't need a start or close.
|
||||
_dispatcher.Map((_attribute.HubName, _attribute.Category, _attribute.Event),
|
||||
new ExecutionContext { Executor = context.Executor, AccessKeys = _accessKeys });
|
||||
|
||||
return Task.FromResult<IListener>(new NullListener());
|
||||
}
|
||||
|
||||
public ParameterDescriptor ToParameterDescriptor()
|
||||
{
|
||||
return new ParameterDescriptor
|
||||
{
|
||||
Name = _parameterInfo.Name,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of object in BindAsync
|
||||
/// </summary>
|
||||
public Type TriggerValueType => typeof(SignalRTriggerEvent);
|
||||
|
||||
// TODO: Use dynamic contract to deal with parameterName
|
||||
public IReadOnlyDictionary<string, Type> BindingDataContract { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Defined what other bindings can use and return value.
|
||||
/// </summary>
|
||||
private IReadOnlyDictionary<string, Type> CreateBindingContract(SignalRTriggerAttribute attribute, ParameterInfo parameter)
|
||||
{
|
||||
var contract = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ ReturnParameterKey, typeof(object).MakeByRefType() },
|
||||
};
|
||||
|
||||
// Add names in ParameterNames to binding contract, that user can bind to Functions' parameter directly
|
||||
if (attribute.ParameterNames != null)
|
||||
{
|
||||
var parameters = ((MethodInfo)parameter.Member).GetParameters().ToDictionary(p => p.Name, p => p.ParameterType, StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var parameterName in attribute.ParameterNames)
|
||||
{
|
||||
if (parameters.ContainsKey(parameterName))
|
||||
{
|
||||
contract.Add(parameterName, parameters[parameterName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
contract.Add(parameterName, typeof(object));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
private void AddParameterNamesBindingData(Dictionary<string, object> bindingData, string[] parameterNames, object[] arguments)
|
||||
{
|
||||
var length = parameterNames.Length;
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
if (BindingDataContract.TryGetValue(parameterNames[i], out var type))
|
||||
{
|
||||
bindingData.Add(parameterNames[i], ConvertValueIfNecessary(arguments[i], type));
|
||||
}
|
||||
else
|
||||
{
|
||||
bindingData.Add(parameterNames[i], arguments[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object ConvertValueIfNecessary(object value, Type targetType)
|
||||
{
|
||||
if (value != null && !targetType.IsAssignableFrom(value.GetType()))
|
||||
{
|
||||
var underlyingTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;
|
||||
|
||||
var jObject = value as JObject;
|
||||
if (jObject != null)
|
||||
{
|
||||
value = jObject.ToObject(targetType);
|
||||
}
|
||||
else if (underlyingTargetType == typeof(Guid) && value.GetType() == typeof(string))
|
||||
{
|
||||
// Guids need to be converted by their own logic
|
||||
// Intentionally throw here on error to standardize behavior
|
||||
value = Guid.Parse((string)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the type is nullable, we only need to convert to the
|
||||
// correct underlying type
|
||||
value = Convert.ChangeType(value, underlyingTargetType);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO: Add more supported type
|
||||
/// <summary>
|
||||
/// A provider that responsible for providing value in various type to be bond to function method parameter.
|
||||
/// </summary>
|
||||
private class SignalRTriggerValueProvider : IValueBinder
|
||||
{
|
||||
private readonly InvocationContext _value;
|
||||
private readonly ParameterInfo _parameter;
|
||||
|
||||
public SignalRTriggerValueProvider(ParameterInfo parameter, InvocationContext value)
|
||||
{
|
||||
_parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
|
||||
_value = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
public Task<object> GetValueAsync()
|
||||
{
|
||||
if (_parameter.ParameterType == typeof(InvocationContext))
|
||||
{
|
||||
return Task.FromResult<object>(_value);
|
||||
}
|
||||
else if (_parameter.ParameterType == typeof(object) ||
|
||||
_parameter.ParameterType == typeof(JObject))
|
||||
{
|
||||
return Task.FromResult<object>(JObject.FromObject(_value));
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
public string ToInvokeString()
|
||||
{
|
||||
return _value.ToString();
|
||||
}
|
||||
|
||||
public Type Type => _parameter.GetType();
|
||||
|
||||
// No use here
|
||||
public Task SetValueAsync(object value, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A provider to handle return value.
|
||||
/// </summary>
|
||||
private class TriggerReturnValueProvider : IValueBinder
|
||||
{
|
||||
private readonly TaskCompletionSource<object> _tcs;
|
||||
|
||||
public TriggerReturnValueProvider(TaskCompletionSource<object> tcs)
|
||||
{
|
||||
_tcs = tcs;
|
||||
}
|
||||
|
||||
public Task<object> GetValueAsync()
|
||||
{
|
||||
// Useless for return value provider
|
||||
return null;
|
||||
}
|
||||
|
||||
public string ToInvokeString()
|
||||
{
|
||||
// Useless for return value provider
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public Type Type => typeof(object).MakeByRefType();
|
||||
|
||||
public Task SetValueAsync(object value, CancellationToken cancellationToken)
|
||||
{
|
||||
_tcs.TrySetResult(value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
BindingDataContract = CreateBindingContract(_attribute, _parameterInfo);
|
||||
}
|
||||
|
||||
public Task<ITriggerData> BindAsync(object value, ValueBindingContext context)
|
||||
{
|
||||
var bindingData = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (value is SignalRTriggerEvent triggerEvent)
|
||||
{
|
||||
var bindingContext = triggerEvent.Context;
|
||||
|
||||
// If ParameterNames are set, bind them in order.
|
||||
// To reduce undefined situation, number of arguments should keep consist with that of ParameterNames
|
||||
if (_attribute.ParameterNames != null && _attribute.ParameterNames.Length != 0)
|
||||
{
|
||||
if (bindingContext.Arguments == null ||
|
||||
bindingContext.Arguments.Length != _attribute.ParameterNames.Length)
|
||||
{
|
||||
throw new SignalRTriggerParametersNotMatchException(_attribute.ParameterNames.Length, bindingContext.Arguments?.Length ?? 0);
|
||||
}
|
||||
|
||||
AddParameterNamesBindingData(bindingData, _attribute.ParameterNames, bindingContext.Arguments);
|
||||
}
|
||||
|
||||
return Task.FromResult<ITriggerData>(new TriggerData(new SignalRTriggerValueProvider(_parameterInfo, bindingContext), bindingData)
|
||||
{
|
||||
ReturnValueProvider = triggerEvent.TaskCompletionSource == null ? null : new TriggerReturnValueProvider(triggerEvent.TaskCompletionSource),
|
||||
});
|
||||
}
|
||||
|
||||
return Task.FromResult<ITriggerData>(null);
|
||||
}
|
||||
|
||||
public Task<IListener> CreateListenerAsync(ListenerFactoryContext context)
|
||||
{
|
||||
if (context == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(context));
|
||||
}
|
||||
|
||||
// It's not a real listener, and it doesn't need a start or close.
|
||||
_dispatcher.Map((_attribute.HubName, _attribute.Category, _attribute.Event),
|
||||
new ExecutionContext { Executor = context.Executor, AccessKeys = _accessKeys });
|
||||
|
||||
return Task.FromResult<IListener>(new NullListener());
|
||||
}
|
||||
|
||||
public ParameterDescriptor ToParameterDescriptor()
|
||||
{
|
||||
return new ParameterDescriptor
|
||||
{
|
||||
Name = _parameterInfo.Name,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of object in BindAsync
|
||||
/// </summary>
|
||||
public Type TriggerValueType => typeof(SignalRTriggerEvent);
|
||||
|
||||
// TODO: Use dynamic contract to deal with parameterName
|
||||
public IReadOnlyDictionary<string, Type> BindingDataContract { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Defined what other bindings can use and return value.
|
||||
/// </summary>
|
||||
private IReadOnlyDictionary<string, Type> CreateBindingContract(SignalRTriggerAttribute attribute, ParameterInfo parameter)
|
||||
{
|
||||
var contract = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ ReturnParameterKey, typeof(object).MakeByRefType() },
|
||||
};
|
||||
|
||||
// Add names in ParameterNames to binding contract, that user can bind to Functions' parameter directly
|
||||
if (attribute.ParameterNames != null)
|
||||
{
|
||||
var parameters = ((MethodInfo)parameter.Member).GetParameters().ToDictionary(p => p.Name, p => p.ParameterType, StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var parameterName in attribute.ParameterNames)
|
||||
{
|
||||
if (parameters.ContainsKey(parameterName))
|
||||
{
|
||||
contract.Add(parameterName, parameters[parameterName]);
|
||||
}
|
||||
else
|
||||
{
|
||||
contract.Add(parameterName, typeof(object));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return contract;
|
||||
}
|
||||
|
||||
private void AddParameterNamesBindingData(Dictionary<string, object> bindingData, string[] parameterNames, object[] arguments)
|
||||
{
|
||||
var length = parameterNames.Length;
|
||||
for (var i = 0; i < length; i++)
|
||||
{
|
||||
if (BindingDataContract.TryGetValue(parameterNames[i], out var type))
|
||||
{
|
||||
bindingData.Add(parameterNames[i], ConvertValueIfNecessary(arguments[i], type));
|
||||
}
|
||||
else
|
||||
{
|
||||
bindingData.Add(parameterNames[i], arguments[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private object ConvertValueIfNecessary(object value, Type targetType)
|
||||
{
|
||||
if (value != null && !targetType.IsAssignableFrom(value.GetType()))
|
||||
{
|
||||
var underlyingTargetType = Nullable.GetUnderlyingType(targetType) ?? targetType;
|
||||
|
||||
var jObject = value as JObject;
|
||||
if (jObject != null)
|
||||
{
|
||||
value = jObject.ToObject(targetType);
|
||||
}
|
||||
else if (underlyingTargetType == typeof(Guid) && value.GetType() == typeof(string))
|
||||
{
|
||||
// Guids need to be converted by their own logic
|
||||
// Intentionally throw here on error to standardize behavior
|
||||
value = Guid.Parse((string)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the type is nullable, we only need to convert to the
|
||||
// correct underlying type
|
||||
value = Convert.ChangeType(value, underlyingTargetType);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// TODO: Add more supported type
|
||||
/// <summary>
|
||||
/// A provider that responsible for providing value in various type to be bond to function method parameter.
|
||||
/// </summary>
|
||||
private class SignalRTriggerValueProvider : IValueBinder
|
||||
{
|
||||
private readonly InvocationContext _value;
|
||||
private readonly ParameterInfo _parameter;
|
||||
|
||||
public SignalRTriggerValueProvider(ParameterInfo parameter, InvocationContext value)
|
||||
{
|
||||
_parameter = parameter ?? throw new ArgumentNullException(nameof(parameter));
|
||||
_value = value ?? throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
public Task<object> GetValueAsync()
|
||||
{
|
||||
if (_parameter.ParameterType == typeof(InvocationContext))
|
||||
{
|
||||
return Task.FromResult<object>(_value);
|
||||
}
|
||||
else if (_parameter.ParameterType == typeof(object) ||
|
||||
_parameter.ParameterType == typeof(JObject))
|
||||
{
|
||||
return Task.FromResult<object>(JObject.FromObject(_value));
|
||||
}
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
}
|
||||
|
||||
public string ToInvokeString()
|
||||
{
|
||||
return _value.ToString();
|
||||
}
|
||||
|
||||
public Type Type => _parameter.GetType();
|
||||
|
||||
// No use here
|
||||
public Task SetValueAsync(object value, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A provider to handle return value.
|
||||
/// </summary>
|
||||
private class TriggerReturnValueProvider : IValueBinder
|
||||
{
|
||||
private readonly TaskCompletionSource<object> _tcs;
|
||||
|
||||
public TriggerReturnValueProvider(TaskCompletionSource<object> tcs)
|
||||
{
|
||||
_tcs = tcs;
|
||||
}
|
||||
|
||||
public Task<object> GetValueAsync()
|
||||
{
|
||||
// Useless for return value provider
|
||||
return null;
|
||||
}
|
||||
|
||||
public string ToInvokeString()
|
||||
{
|
||||
// Useless for return value provider
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
public Type Type => typeof(object).MakeByRefType();
|
||||
|
||||
public Task SetValueAsync(object value, CancellationToken cancellationToken)
|
||||
{
|
||||
_tcs.TrySetResult(value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
|
@ -16,6 +15,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
private readonly Dictionary<(string hub, string category, string @event), SignalRMethodExecutor> _executors =
|
||||
new Dictionary<(string, string, string), SignalRMethodExecutor>(TupleStringIgnoreCasesComparer.Instance);
|
||||
|
||||
private readonly IRequestResolver _resolver;
|
||||
|
||||
public SignalRTriggerDispatcher(IRequestResolver resolver = null)
|
||||
|
@ -27,7 +27,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
if (!_executors.ContainsKey(key))
|
||||
{
|
||||
if (string.Equals(key.category,Category.Connections, StringComparison.OrdinalIgnoreCase))
|
||||
if (string.Equals(key.category, Category.Connections, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (string.Equals(key.@event, Event.Connected, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
|
@ -65,7 +65,7 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
{
|
||||
return new HttpResponseMessage(HttpStatusCode.BadRequest);
|
||||
}
|
||||
|
||||
|
||||
if (_executors.TryGetValue(key, out var executor))
|
||||
{
|
||||
try
|
||||
|
@ -103,4 +103,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
!string.IsNullOrEmpty(key.@event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,4 +17,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
/// </summary>
|
||||
public TaskCompletionSource<object> TaskCompletionSource { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,4 +17,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public override IHubProtocol Protocol { get; } = new JsonHubProtocol();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,4 +17,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public override IHubProtocol Protocol { get; } = new MessagePackHubProtocol();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,4 +29,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
|
||||
public abstract IHubProtocol Protocol { get; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,65 +1,62 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal static class SignalRTriggerUtils
|
||||
{
|
||||
private const string CommaSeparator = ",";
|
||||
private static readonly char[] HeaderSeparator = { ',' };
|
||||
private static readonly string[] ClaimsSeparator = { ": " };
|
||||
|
||||
|
||||
public static IDictionary<string, string> GetQueryDictionary(string queryString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(queryString))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
// The query string looks like "?key1=value1&key2=value2"
|
||||
var queries = QueryHelpers.ParseQuery(queryString);
|
||||
return queries.ToDictionary(x => x.Key, x => x.Value.ToString());
|
||||
}
|
||||
|
||||
public static IDictionary<string, string> GetClaimDictionary(string claims)
|
||||
{
|
||||
if (string.IsNullOrEmpty(claims))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
// The claim string looks like "a: v, b: v"
|
||||
return claims.Split(HeaderSeparator, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(p => p.Split(ClaimsSeparator, StringSplitOptions.RemoveEmptyEntries)).Where(l => l.Length == 2)
|
||||
.GroupBy(s => s[0].Trim(), (k, g) => new KeyValuePair<string, string>(k, g.Select(gk => gk[1].Trim()).FirstOrDefault()))
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<string> GetSignatureList(string signatures)
|
||||
{
|
||||
if (string.IsNullOrEmpty(signatures))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return signatures.Split(HeaderSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public static IDictionary<string, string> GetHeaderDictionary(HttpRequestHeaders headers)
|
||||
{
|
||||
return headers.ToDictionary(x => x.Key, x => string.Join(CommaSeparator, x.Value.ToArray()), StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal static class SignalRTriggerUtils
|
||||
{
|
||||
private const string CommaSeparator = ",";
|
||||
private static readonly char[] HeaderSeparator = { ',' };
|
||||
private static readonly string[] ClaimsSeparator = { ": " };
|
||||
|
||||
public static IDictionary<string, string> GetQueryDictionary(string queryString)
|
||||
{
|
||||
if (string.IsNullOrEmpty(queryString))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
// The query string looks like "?key1=value1&key2=value2"
|
||||
var queries = QueryHelpers.ParseQuery(queryString);
|
||||
return queries.ToDictionary(x => x.Key, x => x.Value.ToString());
|
||||
}
|
||||
|
||||
public static IDictionary<string, string> GetClaimDictionary(string claims)
|
||||
{
|
||||
if (string.IsNullOrEmpty(claims))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
// The claim string looks like "a: v, b: v"
|
||||
return claims.Split(HeaderSeparator, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Select(p => p.Split(ClaimsSeparator, StringSplitOptions.RemoveEmptyEntries)).Where(l => l.Length == 2)
|
||||
.GroupBy(s => s[0].Trim(), (k, g) => new KeyValuePair<string, string>(k, g.Select(gk => gk[1].Trim()).FirstOrDefault()))
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
}
|
||||
|
||||
public static IReadOnlyList<string> GetSignatureList(string signatures)
|
||||
{
|
||||
if (string.IsNullOrEmpty(signatures))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return signatures.Split(HeaderSeparator, StringSplitOptions.RemoveEmptyEntries);
|
||||
}
|
||||
|
||||
public static IDictionary<string, string> GetHeaderDictionary(HttpRequestHeaders headers)
|
||||
{
|
||||
return headers.ToDictionary(x => x.Key, x => string.Join(CommaSeparator, x.Value.ToArray()), StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,13 +2,11 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
||||
{
|
||||
internal class TupleStringIgnoreCasesComparer: IEqualityComparer<(string, string, string)>
|
||||
internal class TupleStringIgnoreCasesComparer : IEqualityComparer<(string, string, string)>
|
||||
{
|
||||
public static readonly TupleStringIgnoreCasesComparer Instance = new TupleStringIgnoreCasesComparer();
|
||||
|
||||
|
@ -26,4 +24,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService
|
|||
StringComparer.InvariantCultureIgnoreCase.GetHashCode(obj.Item3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
using System;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
@ -13,7 +16,7 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols.Tests
|
|||
{
|
||||
public static IEnumerable<object[]> GetParameters()
|
||||
{
|
||||
var protocols = new string[] {"json", "messagepack"};
|
||||
var protocols = new string[] { "json", "messagepack" };
|
||||
foreach (var protocol in protocols)
|
||||
{
|
||||
yield return new object[] { protocol, null, Guid.NewGuid().ToString(), new object[0] };
|
||||
|
@ -46,7 +49,6 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols.Tests
|
|||
new object[] {new object[] { null, Guid.NewGuid().ToString() }}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -67,7 +69,7 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols.Tests
|
|||
}
|
||||
var serverlessProtocol = protocolName == "json" ? (IServerlessProtocol)new JsonServerlessProtocol() : new MessagePackServerlessProtocol();
|
||||
Assert.True(serverlessProtocol.TryParseMessage(ref payload, out var parsedMessage));
|
||||
var invocationMessage = (InvocationMessage) parsedMessage;
|
||||
var invocationMessage = (InvocationMessage)parsedMessage;
|
||||
Assert.Equal(1, invocationMessage.Type);
|
||||
Assert.Equal(invocationId, invocationMessage.InvocationId);
|
||||
Assert.Equal(target, invocationMessage.Target);
|
||||
|
@ -91,11 +93,11 @@ namespace Microsoft.Azure.SignalR.Serverless.Protocols.Tests
|
|||
[InlineData(null)]
|
||||
public void CloseConnectionMessageParseTest(string error)
|
||||
{
|
||||
var openConnectionPayload = new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new CloseConnectionMessage() { Type = 11, Error = error})));
|
||||
var openConnectionPayload = new ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new CloseConnectionMessage() { Type = 11, Error = error })));
|
||||
var serverlessProtocol = new JsonServerlessProtocol();
|
||||
Assert.True(serverlessProtocol.TryParseMessage(ref openConnectionPayload, out var message));
|
||||
Assert.Equal(error, ((CloseConnectionMessage)message).Error);
|
||||
Assert.Equal(typeof(CloseConnectionMessage), message.GetType());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,8 @@
|
|||
using System;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService.Tests.Common
|
||||
{
|
||||
|
@ -82,4 +83,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService.Tests.Common
|
|||
return lengthPrefixBuffer.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace Microsoft.Azure.WebJobs.Extensions.SignalRService.Tests.Common
|
||||
{
|
||||
|
@ -29,4 +29,4 @@ namespace Microsoft.Azure.WebJobs.Extensions.SignalRService.Tests.Common
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ namespace Microsoft.Azure.Webjobs.Extensions.SignalRService.E2ETests
|
|||
return HttpClient.PostAsync($"{url}/api/{SendPath}", content);
|
||||
}
|
||||
|
||||
public static Task Group(string url,SignalRGroupAction action)
|
||||
public static Task Group(string url, SignalRGroupAction action)
|
||||
{
|
||||
const string GroupPath = "group";
|
||||
var content = JsonContent.Create(action);
|
||||
|
|
|
@ -21,6 +21,7 @@ namespace Microsoft.Azure.Webjobs.Extensions.SignalRService.E2ETests
|
|||
{
|
||||
private const string Section = "SimpleChat";
|
||||
public static readonly SimpleChatClient Client = new();
|
||||
|
||||
public class BaseUrls : IEnumerable<object[]>
|
||||
{
|
||||
public static readonly IEnumerable<object[]> Data = from section in UrlConfiguration.GetSection(Section).GetChildren()
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
|
@ -31,7 +30,6 @@ namespace SignalRServiceExtension.Tests
|
|||
"",
|
||||
SecurityTokenStatus.Empty
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
[Theory]
|
||||
|
@ -59,4 +57,4 @@ namespace SignalRServiceExtension.Tests
|
|||
Assert.Equal(expectedStatus, securityTokenResult.Status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace SignalRServiceExtension.Tests
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -30,28 +32,27 @@ namespace SignalRServiceExtension.Tests.Trigger
|
|||
.Returns<TriggeredFunctionData, CancellationToken>((data, token) =>
|
||||
{
|
||||
_triggeredFunctionDataTcs.TrySetResult(data);
|
||||
((SignalRTriggerEvent) data.TriggerValue).TaskCompletionSource?.TrySetResult(string.Empty);
|
||||
((SignalRTriggerEvent)data.TriggerValue).TaskCompletionSource?.TrySetResult(string.Empty);
|
||||
return Task.FromResult(new FunctionResult(true));
|
||||
});
|
||||
_triggeredFunctionExecutor = executorMoc.Object;
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task SignalRConnectMethodExecutorTest()
|
||||
{
|
||||
var resolver = new SignalRRequestResolver(false);
|
||||
var methodExecutor = new SignalRConnectMethodExecutor(resolver, new ExecutionContext {Executor = _triggeredFunctionExecutor });
|
||||
var methodExecutor = new SignalRConnectMethodExecutor(resolver, new ExecutionContext { Executor = _triggeredFunctionExecutor });
|
||||
var hub = Guid.NewGuid().ToString();
|
||||
var category = Guid.NewGuid().ToString();
|
||||
var @event = Guid.NewGuid().ToString();
|
||||
var connectionId = Guid.NewGuid().ToString();
|
||||
var content = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new OpenConnectionMessage {Type = 10}));
|
||||
var content = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new OpenConnectionMessage { Type = 10 }));
|
||||
var request = TestHelpers.CreateHttpRequestMessage(hub, category, @event, connectionId, contentType: Constants.JsonContentType, content: content);
|
||||
await methodExecutor.ExecuteAsync(request);
|
||||
|
||||
var result = await _triggeredFunctionDataTcs.Task;
|
||||
var triggerData = (SignalRTriggerEvent) result.TriggerValue;
|
||||
var triggerData = (SignalRTriggerEvent)result.TriggerValue;
|
||||
Assert.Null(triggerData.TaskCompletionSource);
|
||||
Assert.Equal(hub, triggerData.Context.Hub);
|
||||
Assert.Equal(category, triggerData.Context.Category);
|
||||
|
@ -96,7 +97,7 @@ namespace SignalRServiceExtension.Tests.Trigger
|
|||
var category = Guid.NewGuid().ToString();
|
||||
var @event = Guid.NewGuid().ToString();
|
||||
var connectionId = Guid.NewGuid().ToString();
|
||||
var arguments = new object[] {Guid.NewGuid().ToString(), Guid.NewGuid().ToString()};
|
||||
var arguments = new object[] { Guid.NewGuid().ToString(), Guid.NewGuid().ToString() };
|
||||
|
||||
var message = new Microsoft.AspNetCore.SignalR.Protocol.InvocationMessage(Guid.NewGuid().ToString(), @event, arguments);
|
||||
IHubProtocol protocol = protocolName == "json" ? (IHubProtocol)new JsonHubProtocol() : new MessagePackHubProtocol();
|
||||
|
@ -126,4 +127,4 @@ namespace SignalRServiceExtension.Tests.Trigger
|
|||
Assert.Equal(arguments, triggerData.Context.Arguments);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Microsoft.Azure.WebJobs;
|
||||
|
@ -25,7 +27,7 @@ namespace SignalRServiceExtension.Tests
|
|||
Assert.Equal(nameof(TestServerlessHub), resolvedAttribute.HubName);
|
||||
Assert.Equal(Category.Messages, resolvedAttribute.Category);
|
||||
Assert.Equal(nameof(TestServerlessHub.TestFunction), resolvedAttribute.Event);
|
||||
Assert.Equal(new string[] {"arg0", "arg1"}, resolvedAttribute.ParameterNames);
|
||||
Assert.Equal(new string[] { "arg0", "arg1" }, resolvedAttribute.ParameterNames);
|
||||
|
||||
// With SignalRIgoreAttribute
|
||||
parameter = typeof(TestServerlessHub).GetMethod(nameof(TestServerlessHub.TestFunctionWithIgnore), BindingFlags.Instance | BindingFlags.NonPublic).GetParameters()[0];
|
||||
|
@ -91,7 +93,7 @@ namespace SignalRServiceExtension.Tests
|
|||
public void ResolveAttributeParameterConflictTest()
|
||||
{
|
||||
var bindingProvider = CreateBindingProvider();
|
||||
var attribute = new SignalRTriggerAttribute(string.Empty, string.Empty, String.Empty, new string[] {"arg0"});
|
||||
var attribute = new SignalRTriggerAttribute(string.Empty, string.Empty, String.Empty, new string[] { "arg0" });
|
||||
var parameter = typeof(TestServerlessHub).GetMethod(nameof(TestServerlessHub.TestFunction), BindingFlags.Instance | BindingFlags.NonPublic).GetParameters()[0];
|
||||
Assert.ThrowsAny<Exception>(() => bindingProvider.GetParameterResolvedAttribute(attribute, parameter));
|
||||
}
|
||||
|
@ -108,7 +110,7 @@ namespace SignalRServiceExtension.Tests
|
|||
private SignalRTriggerBindingProvider CreateBindingProvider(Exception exception = null)
|
||||
{
|
||||
var configuration = new ConfigurationBuilder().AddInMemoryCollection().Build();
|
||||
configuration[Constants.AzureSignalRConnectionStringName]= "Endpoint=http://localhost;AccessKey=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;Version=1.0;";
|
||||
configuration[Constants.AzureSignalRConnectionStringName] = "Endpoint=http://localhost;AccessKey=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;Version=1.0;";
|
||||
configuration["Serverless_ExpressionBindings_HubName"] = "test_hub";
|
||||
configuration["Serverless_ExpressionBindings_HubCategory"] = "connections";
|
||||
configuration["Serverless_ExpressionBindings_HubEvent"] = "connected";
|
||||
|
@ -118,37 +120,37 @@ namespace SignalRServiceExtension.Tests
|
|||
|
||||
public class TestServerlessHub : ServerlessHub
|
||||
{
|
||||
internal void TestFunction([SignalRTrigger]InvocationContext context, string arg0, int arg1)
|
||||
internal void TestFunction([SignalRTrigger] InvocationContext context, string arg0, int arg1)
|
||||
{
|
||||
}
|
||||
|
||||
internal void TestFunctionWithIgnore([SignalRTrigger]InvocationContext context, string arg0, int arg1, [SignalRIgnore]int arg2)
|
||||
internal void TestFunctionWithIgnore([SignalRTrigger] InvocationContext context, string arg0, int arg1, [SignalRIgnore] int arg2)
|
||||
{
|
||||
}
|
||||
|
||||
internal void TestFunctionWithSpecificType([SignalRTrigger]InvocationContext context, string arg0, int arg1, ILogger logger, CancellationToken token)
|
||||
internal void TestFunctionWithSpecificType([SignalRTrigger] InvocationContext context, string arg0, int arg1, ILogger logger, CancellationToken token)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class TestNonServerlessHub
|
||||
{
|
||||
internal void TestFunction([SignalRTrigger]InvocationContext context,
|
||||
[SignalRParameter]string arg0,
|
||||
[SignalRParameter]int arg1)
|
||||
internal void TestFunction([SignalRTrigger] InvocationContext context,
|
||||
[SignalRParameter] string arg0,
|
||||
[SignalRParameter] int arg1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public class TestConnectedServerlessHub : ServerlessHub
|
||||
{
|
||||
internal void OnConnected([SignalRTrigger]InvocationContext context, string arg0, int arg1)
|
||||
internal void OnConnected([SignalRTrigger] InvocationContext context, string arg0, int arg1)
|
||||
{
|
||||
}
|
||||
|
||||
internal void OnDisconnected([SignalRTrigger]InvocationContext context, string arg0, int arg1)
|
||||
internal void OnDisconnected([SignalRTrigger] InvocationContext context, string arg0, int arg1)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
using System;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
|
@ -41,11 +44,11 @@ namespace SignalRServiceExtension.Tests
|
|||
var executor = executorMoc.Object;
|
||||
if (throwException)
|
||||
{
|
||||
Assert.ThrowsAny<Exception>(() => dispatcher.Map(key, new ExecutionContext {Executor = executor, AccessKeys = null}));
|
||||
Assert.ThrowsAny<Exception>(() => dispatcher.Map(key, new ExecutionContext { Executor = executor, AccessKeys = null }));
|
||||
return;
|
||||
}
|
||||
|
||||
dispatcher.Map(key, new ExecutionContext {Executor = executor, AccessKeys = null});
|
||||
dispatcher.Map(key, new ExecutionContext { Executor = executor, AccessKeys = null });
|
||||
var request = TestHelpers.CreateHttpRequestMessage(key.hub, key.category, key.@event, Guid.NewGuid().ToString());
|
||||
await dispatcher.ExecuteAsync(request);
|
||||
executorMoc.Verify(e => e.TryExecuteAsync(It.IsAny<TriggeredFunctionData>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
|
@ -73,7 +76,7 @@ namespace SignalRServiceExtension.Tests
|
|||
.Returns(Task.FromResult(new FunctionResult(true)));
|
||||
var executor = executorMoc.Object;
|
||||
dispatcher.Map(key, new ExecutionContext { Executor = executor, AccessKeys = null });
|
||||
|
||||
|
||||
// Test content type
|
||||
resolver.ValidateContentTypeResult = false;
|
||||
var request = TestHelpers.CreateHttpRequestMessage(key.hub, key.category, key.@event, Guid.NewGuid().ToString());
|
||||
|
@ -120,4 +123,4 @@ namespace SignalRServiceExtension.Tests
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using Microsoft.Azure.SignalR;
|
||||
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
|
||||
using SignalRServiceExtension.Tests.Utils;
|
||||
|
@ -39,7 +41,6 @@ namespace SignalRServiceExtension.Tests.Trigger
|
|||
yield return new object[] { req, accessKeys, false };
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(SignatureTestData))]
|
||||
internal void SignatureTest(HttpRequestMessage request, AccessKey[] accessKeys, bool validate)
|
||||
|
@ -48,4 +49,4 @@ namespace SignalRServiceExtension.Tests.Trigger
|
|||
Assert.Equal(validate, resolver.ValidateSignature(request, accessKeys));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,13 +20,14 @@ namespace SignalRServiceExtension.Tests
|
|||
{
|
||||
private const string ConnectionString = "Endpoint=http://localhost;AccessKey=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789;Version=1.0;";
|
||||
private static readonly AccessKey[] AccessKeys = new AccessKey[] { new ServiceEndpoint(ConnectionString).AccessKey };
|
||||
|
||||
[Fact]
|
||||
public async Task BindAsyncTest()
|
||||
{
|
||||
var binding = CreateBinding(nameof(TestFunction), new string[0]);
|
||||
var tcs = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var context = new InvocationContext();
|
||||
var triggerContext = new SignalRTriggerEvent {Context = context, TaskCompletionSource = tcs};
|
||||
var triggerContext = new SignalRTriggerEvent { Context = context, TaskCompletionSource = tcs };
|
||||
var result = await binding.BindAsync(triggerContext, null);
|
||||
Assert.Equal(context, await result.ValueProvider.GetValueAsync());
|
||||
}
|
||||
|
@ -52,7 +53,7 @@ namespace SignalRServiceExtension.Tests
|
|||
public async Task BindingDataTestWithLessParameterNames()
|
||||
{
|
||||
var binding = CreateBinding(nameof(TestFunctionWithTwoStringArgument), "arg0");
|
||||
var context = new InvocationContext{Arguments = new object[] {Guid.NewGuid().ToString()}};
|
||||
var context = new InvocationContext { Arguments = new object[] { Guid.NewGuid().ToString() } };
|
||||
var triggerContext = new SignalRTriggerEvent { Context = context };
|
||||
var result = await binding.BindAsync(triggerContext, null);
|
||||
var bindingData = result.BindingData;
|
||||
|
@ -116,4 +117,4 @@ namespace SignalRServiceExtension.Tests
|
|||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
using System.Collections.Generic;
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
|
||||
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
|
||||
using Newtonsoft.Json;
|
||||
|
@ -13,17 +15,17 @@ namespace SignalRServiceExtension.Tests
|
|||
{
|
||||
public static IEnumerable<object[]> QueryStringTestData()
|
||||
{
|
||||
yield return new object[] {"?k=v", new Dictionary<string, string> {["k"] = "v"}};
|
||||
yield return new object[] { "?k=v", new Dictionary<string, string> { ["k"] = "v" } };
|
||||
yield return new object[] { "?k1=v1&k2=v2", new Dictionary<string, string> { ["k1"] = "v1", ["k2"] = "v2" } };
|
||||
yield return new object[] { "?k1=v1&k1=v2", new Dictionary<string, string> { ["k1"] = "v1,v2" }};
|
||||
yield return new object[] { "?k1=v1&k1=v2&k2=v3", new Dictionary<string, string> { ["k1"] = "v1,v2", ["k2"] = "v3"} };
|
||||
yield return new object[] { "?k1=v1&k1=v2", new Dictionary<string, string> { ["k1"] = "v1,v2" } };
|
||||
yield return new object[] { "?k1=v1&k1=v2&k2=v3", new Dictionary<string, string> { ["k1"] = "v1,v2", ["k2"] = "v3" } };
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> HeaderTestData()
|
||||
{
|
||||
var request1 = new HttpRequestMessage();
|
||||
request1.Headers.Add("k", "v");
|
||||
yield return new object[] {request1.Headers, new Dictionary<string, string> {["k"] = "v"}};
|
||||
yield return new object[] { request1.Headers, new Dictionary<string, string> { ["k"] = "v" } };
|
||||
|
||||
var request2 = new HttpRequestMessage();
|
||||
request2.Headers.Add("k1", "v1");
|
||||
|
@ -46,7 +48,7 @@ namespace SignalRServiceExtension.Tests
|
|||
{
|
||||
yield return new object[] { "k: v", new Dictionary<string, string> { ["k"] = "v" } };
|
||||
yield return new object[] { "k1: v1, k2: v2", new Dictionary<string, string> { ["k1"] = "v1", ["k2"] = "v2" } };
|
||||
yield return new object[] { "k1: v1, k1: v2", new Dictionary<string, string> { ["k1"] = "v1" }};
|
||||
yield return new object[] { "k1: v1, k1: v2", new Dictionary<string, string> { ["k1"] = "v1" } };
|
||||
yield return new object[] { "k1: v1, k1: v2, k2: v3", new Dictionary<string, string> { ["k1"] = "v1", ["k2"] = "v3" } };
|
||||
}
|
||||
|
||||
|
@ -74,4 +76,4 @@ namespace SignalRServiceExtension.Tests
|
|||
Assert.Equal(JsonConvert.SerializeObject(expectedResult), JsonConvert.SerializeObject(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,8 +34,9 @@ namespace SignalRServiceExtension.Tests.Utils.Loggings
|
|||
private class NoopDisposable : IDisposable
|
||||
{
|
||||
public static NoopDisposable Instance = new NoopDisposable();
|
||||
|
||||
public void Dispose()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,4 +21,4 @@ namespace SignalRServiceExtension.Tests.Utils.Loggings
|
|||
public void Dispose()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,4 +28,4 @@ namespace SignalRServiceExtension.Tests.Utils
|
|||
BindToInput<string>(attr => attr.ToBeAutoResolve);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -60,7 +60,7 @@ namespace SignalRServiceExtension.Tests.Utils
|
|||
return host.Services.GetService<IJobHost>() as JobHost;
|
||||
}
|
||||
|
||||
public static HttpRequestMessage CreateHttpRequestMessage(string hub, string category, string @event, string connectionId,
|
||||
public static HttpRequestMessage CreateHttpRequestMessage(string hub, string category, string @event, string connectionId,
|
||||
string contentType = Constants.JsonContentType, byte[] content = null, string[] signatures = null)
|
||||
{
|
||||
var context = new DefaultHttpContext();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
@ -13,7 +12,7 @@ using ExecutionContext = Microsoft.Azure.WebJobs.Extensions.SignalRService.Execu
|
|||
|
||||
namespace SignalRServiceExtension.Tests.Utils
|
||||
{
|
||||
class TestTriggerDispatcher : ISignalRTriggerDispatcher
|
||||
internal class TestTriggerDispatcher : ISignalRTriggerDispatcher
|
||||
{
|
||||
public Dictionary<(string, string, string), ExecutionContext> Executors { get; } =
|
||||
new Dictionary<(string, string, string), ExecutionContext>();
|
||||
|
@ -28,4 +27,4 @@ namespace SignalRServiceExtension.Tests.Utils
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче