Deploying Azure SignalR

Update the upstream URL pattern so that it contains the SignalR extension key:

The SignalR extension key can be found under App Keys:

Appendix:

using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs.Extensions.SignalRService;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;

using static AzureSignalR.LocationReporting.Language;

namespace AzureSignalR.Functions
{
    public class LocationHub : ServerlessHub
    {
        const string NewMessageTarget    = "newMessage";
        const string NewConnectionTarget = "newConnection";

        [FunctionName("negotiate")]
        public SignalRConnectionInfo Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req)
        {
            return Negotiate(null, null, new System.TimeSpan(1,0,0));
        }

        [FunctionName(nameof(OnConnected))]
        public async Task OnConnected([SignalRTrigger] InvocationContext invocationContext, ILogger logger)
        {
            invocationContext.Headers.TryGetValue("Authorization", out var auth);
            await Clients.All.SendAsync(NewConnectionTarget, new NewConnection(invocationContext.ConnectionId, auth));
            logger.LogInformation($"{invocationContext.ConnectionId} has connected");
        }

        [FunctionAuthorize]
        [FunctionName(nameof(LocationUpdate))]
        public async Task LocationUpdate([SignalRTrigger] InvocationContext invocationContext, SubjectLocation update, ILogger logger)
        {
            await Clients.All.SendAsync(NewMessageTarget, new NewMessage(invocationContext, update));
            logger.LogInformation($"{invocationContext.ConnectionId} broadcast {update}");
        }

        [FunctionName(nameof(SendToGroup))]
        public async Task SendToGroup([SignalRTrigger] InvocationContext invocationContext, string groupName, SubjectLocation msg)
        {
            await Clients.Group(groupName).SendAsync(NewMessageTarget, new NewMessage(invocationContext, msg));
        }

        [FunctionName(nameof(SendToUser))]
        public async Task SendToUser([SignalRTrigger] InvocationContext invocationContext, string userName, SubjectLocation update)
        {
            await Clients.User(userName).SendAsync(NewMessageTarget, new NewMessage(invocationContext, update));
        }

        [FunctionName(nameof(SendToConnection))]
        public async Task SendToConnection([SignalRTrigger] InvocationContext invocationContext, string connectionId, SubjectLocation update)
        {
            await Clients.Client(connectionId).SendAsync(NewMessageTarget, new NewMessage(invocationContext, update));
        }

        [FunctionName(nameof(JoinGroup))]
        public async Task JoinGroup([SignalRTrigger] InvocationContext invocationContext, string groupName)
        {
            await Groups.AddToGroupAsync(invocationContext.ConnectionId, groupName);
        }

        [FunctionName(nameof(LeaveGroup))]
        public async Task LeaveGroup([SignalRTrigger] InvocationContext invocationContext, string connectionId, string groupName)
        {
            await Groups.RemoveFromGroupAsync(connectionId, groupName);
        }

        [FunctionName(nameof(JoinUserToGroup))]
        public async Task JoinUserToGroup([SignalRTrigger] InvocationContext invocationContext, string userName, string groupName)
        {
            await UserGroups.AddToGroupAsync(userName, groupName);
        }

        [FunctionName(nameof(LeaveUserFromGroup))]
        public async Task LeaveUserFromGroup([SignalRTrigger] InvocationContext invocationContext, string userName, string groupName)
        {
            await UserGroups.RemoveFromGroupAsync(userName, groupName);
        }

        [FunctionName(nameof(OnDisconnected))]
        public void OnDisconnected([SignalRTrigger] InvocationContext invocationContext)
        {
        }

        class NewConnection
        {
            public string ConnectionId { get; }

            public string Authentication { get; }

            public NewConnection(string connectionId, string authentication)
            {
                ConnectionId   = connectionId;
                Authentication = authentication;
            }
        }

        class NewMessage
        {
            public string ConnectionId    { get; }
            public string Sender          { get; }
            public SubjectLocation Update { get; }

            public NewMessage(InvocationContext invocationContext, SubjectLocation update)
            {
                Sender       = string.IsNullOrEmpty(invocationContext.UserId) ? string.Empty : invocationContext.UserId;
                ConnectionId = invocationContext.ConnectionId;
                Update       = update;
            }
        }
    }
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s