private Task ProcessNegotiationRequest()

in src/Microsoft.Azure.SignalR.AspNet/Middleware/NegotiateMiddleware.cs [163:264]


    private Task ProcessNegotiationRequest(IOwinContext owinContext, HostContext context)
    {
        var claims = BuildClaims(owinContext, context.Request);

        var dispatcher = new HubDispatcher(_configuration);
        try
        {
            dispatcher.Initialize(_configuration.Resolver);
            if (!dispatcher.Authorize(context.Request))
            {
                string error = null;
                if (context.Request.User != null && context.Request.User.Identity.IsAuthenticated)
                {
                    // If the user is authenticated and authorize failed then 403
                    error = "Forbidden";
                    context.Response.StatusCode = 403;
                }
                else
                {
                    // If failed to authorize the request then return 401
                    error = "Unauthorized";
                    context.Response.StatusCode = 401;
                }
                Log.NegotiateFailed(_logger, error);
                return context.Response.End(error);
            }
        }
        catch (Exception e)
        {
            Log.NegotiateFailed(_logger, e.Message);
            context.Response.StatusCode = 500;
            return context.Response.End("");
        }

        IServiceEndpointProvider provider;
        try
        {
            // Take the service endpoints for the app
            provider = _endpointManager.GetEndpointProvider(_router.GetNegotiateEndpoint(owinContext, _endpointManager.GetEndpoints(_appName)));

            // When status code changes, we consider the inner router changed the response, then we stop here
            if (context.Response.StatusCode != 200)
            {
                // Inner handler already write to context.Response, no need to continue with error case
                return Task.CompletedTask;
            }

            // Consider it as internal server error when we don't successfully get negotiate response
            if (provider == null)
            {
                var message = "Unable to get the negotiate endpoint";
                Log.NegotiateFailed(_logger, message);
                context.Response.StatusCode = 500;
                return context.Response.End(message);
            }
        }
        catch (AzureSignalRNotConnectedException e)
        {
            Log.NegotiateFailed(_logger, e.Message);
            context.Response.StatusCode = 500;
            return context.Response.End(e.Message);
        }

        // Redirect to Service
        var clientProtocol = context.Request.QueryString["clientProtocol"];
        string originalPath = null;
        string queryString = null;

        // add OriginalPath and QueryString when the clients protocol is higher than 2.0, earlier ASP.NET SignalR clients does not support redirect URL with query parameters
        if (!string.IsNullOrEmpty(clientProtocol) && Version.TryParse(clientProtocol, out var version) && version >= ClientSupportQueryStringVersion)
        {
            var clientRequestId = _connectionRequestIdProvider.GetRequestId("");
            if (clientRequestId != null)
            {
                // remove system preserved query strings
                queryString = "?" +
                    string.Join("&",
                        context.Request.QueryString.Where(s => !PreservedQueryParameters.Contains(s.Key)).Concat(
                                new[]
                                {
                                    new KeyValuePair<string, string>(
                                        Constants.QueryParameter.ConnectionRequestId,
                                        clientRequestId)
                                })
                            .Select(s => $"{Uri.EscapeDataString(s.Key)}={Uri.EscapeDataString(s.Value)}"));
            }

            originalPath = GetOriginalPath(context.Request.LocalPath);
        }

        var url = provider.GetClientEndpoint(null, originalPath, queryString);
        try
        {
            return GenerateClientAccessTokenAsync(provider, context, url, claims);
        }
        catch (AzureSignalRAccessTokenNotAuthorizedException e)
        {
            Log.NegotiateFailed(_logger, e.Message);
            context.Response.StatusCode = 500;
            return context.Response.End("");
        }
    }