Set X-Requested-With on all requests (#1848)
This commit is contained in:
parent
80f87e7730
commit
32b4d5cc6c
|
|
@ -428,6 +428,10 @@ namespace Microsoft.AspNetCore.Http.Connections.Client
|
|||
}
|
||||
}
|
||||
|
||||
httpClient.DefaultRequestHeaders.Remove("X-Requested-With");
|
||||
// Tell auth middleware to 401 instead of redirecting
|
||||
httpClient.DefaultRequestHeaders.Add("X-Requested-With", "XMLHttpRequest");
|
||||
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,6 +82,8 @@ namespace Microsoft.AspNetCore.Http.Connections.Client.Internal
|
|||
_closeTimeout = httpOptions.CloseTimeout;
|
||||
}
|
||||
|
||||
_webSocket.Options.SetRequestHeader("X-Requested-With", "XMLHttpRequest");
|
||||
|
||||
_logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger<WebSocketsTransport>();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ using Microsoft.AspNetCore.Connections;
|
|||
using Microsoft.AspNetCore.Http.Connections;
|
||||
using Microsoft.AspNetCore.Http.Connections.Client;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
|
@ -64,7 +63,7 @@ namespace Microsoft.AspNetCore.SignalR.Client
|
|||
o.Url = url;
|
||||
o.Transport = transportType;
|
||||
});
|
||||
|
||||
|
||||
if (configureHttpConnection != null)
|
||||
{
|
||||
hubConnectionBuilder.Services.Configure(configureHttpConnection);
|
||||
|
|
|
|||
|
|
@ -66,6 +66,46 @@ namespace Microsoft.AspNetCore.SignalR.Client.Tests
|
|||
Assert.True(requestsExecuted);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(HttpTransportType.LongPolling)]
|
||||
[InlineData(HttpTransportType.ServerSentEvents)]
|
||||
public async Task HttpConnectionSetsRequestedWithOnAllRequests(HttpTransportType transportType)
|
||||
{
|
||||
var testHttpHandler = new TestHttpMessageHandler(autoNegotiate: false);
|
||||
var requestsExecuted = false;
|
||||
|
||||
testHttpHandler.OnRequest((request, next, token) =>
|
||||
{
|
||||
return Task.FromResult(ResponseUtils.CreateResponse(HttpStatusCode.NoContent));
|
||||
});
|
||||
|
||||
testHttpHandler.OnNegotiate((_, cancellationToken) =>
|
||||
{
|
||||
return ResponseUtils.CreateResponse(HttpStatusCode.OK, ResponseUtils.CreateNegotiationContent());
|
||||
});
|
||||
|
||||
testHttpHandler.OnRequest(async (request, next, token) =>
|
||||
{
|
||||
var requestedWithHeader = request.Headers.GetValues("X-Requested-With");
|
||||
var requestedWithValue = Assert.Single(requestedWithHeader);
|
||||
Assert.Equal("XMLHttpRequest", requestedWithValue);
|
||||
|
||||
requestsExecuted = true;
|
||||
|
||||
return await next();
|
||||
});
|
||||
|
||||
await WithConnectionAsync(
|
||||
CreateConnection(testHttpHandler, transportType: transportType),
|
||||
async (connection) =>
|
||||
{
|
||||
await connection.StartAsync(TransferFormat.Text).OrTimeout();
|
||||
await connection.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("Hello World"));
|
||||
});
|
||||
// Fail safe in case the code is modified and some requests don't execute as a result
|
||||
Assert.True(requestsExecuted);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CanReceiveData()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Connections;
|
||||
|
||||
namespace Microsoft.AspNetCore.SignalR.Tests
|
||||
{
|
||||
[Authorize]
|
||||
public class AuthConnectionHandler : ConnectionHandler
|
||||
{
|
||||
public override async Task OnConnectedAsync(ConnectionContext connection)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var result = await connection.Transport.Input.ReadAsync();
|
||||
var buffer = result.Buffer;
|
||||
|
||||
if (!buffer.IsEmpty)
|
||||
{
|
||||
await connection.Transport.Output.WriteAsync(buffer.ToArray());
|
||||
}
|
||||
else if (result.IsCompleted)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
connection.Transport.Input.AdvanceTo(buffer.End);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -302,6 +302,69 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[WebSocketsSupportedCondition]
|
||||
public async Task UnauthorizedWebSocketsConnectionDoesNotConnect()
|
||||
{
|
||||
using (StartLog(out var loggerFactory, LogLevel.Trace))
|
||||
{
|
||||
var logger = loggerFactory.CreateLogger<EndToEndTests>();
|
||||
|
||||
var url = _serverFixture.Url + "/auth";
|
||||
var connection = new HttpConnection(new Uri(url), HttpTransportType.WebSockets, loggerFactory);
|
||||
|
||||
try
|
||||
{
|
||||
logger.LogInformation("Starting connection to {url}", url);
|
||||
await connection.StartAsync(TransferFormat.Binary).OrTimeout();
|
||||
Assert.True(false);
|
||||
}
|
||||
catch (WebSocketException) { }
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogInformation(ex, "Test threw exception");
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
logger.LogInformation("Disposing Connection");
|
||||
await connection.DisposeAsync().OrTimeout();
|
||||
logger.LogInformation("Disposed Connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(HttpTransportType.LongPolling)]
|
||||
[InlineData(HttpTransportType.ServerSentEvents)]
|
||||
public async Task UnauthorizedConnectionDoesNotConnect(HttpTransportType transportType)
|
||||
{
|
||||
using (StartLog(out var loggerFactory, LogLevel.Trace, testName: $"{nameof(UnauthorizedConnectionDoesNotConnect)}_{transportType}"))
|
||||
{
|
||||
var logger = loggerFactory.CreateLogger<EndToEndTests>();
|
||||
|
||||
var url = _serverFixture.Url + "/auth";
|
||||
var connection = new HttpConnection(new Uri(url), transportType, loggerFactory);
|
||||
|
||||
try
|
||||
{
|
||||
logger.LogInformation("Starting connection to {url}", url);
|
||||
await connection.StartAsync(TransferFormat.Binary).OrTimeout();
|
||||
Assert.True(false);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Assert.Equal("Response status code does not indicate success: 401 (Unauthorized).", ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
logger.LogInformation("Disposing Connection");
|
||||
await connection.DisposeAsync().OrTimeout();
|
||||
logger.LogInformation("Disposed Connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[WebSocketsSupportedCondition]
|
||||
public async Task ServerClosesConnectionWithErrorIfHubCannotBeCreated_WebSocket()
|
||||
|
|
|
|||
|
|
@ -34,6 +34,8 @@
|
|||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="$(MicrosoftAspNetCoreHttpAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Server.IntegrationTesting" Version="$(MicrosoftAspNetCoreServerIntegrationTestingPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="$(MicrosoftAspNetCoreAuthorizationPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="$(MicrosoftAspNetCoreAuthenticationCookiesPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="$(MicrosoftExtensionsDependencyInjectionAbstractionsPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftExtensionsDependencyInjectionPackageVersion)" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="$(MicrosoftExtensionsLoggingConsolePackageVersion)" />
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
|
@ -16,6 +18,12 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
{
|
||||
options.EnableDetailedErrors = true;
|
||||
});
|
||||
|
||||
services.AddAuthentication(options =>
|
||||
{
|
||||
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
|
||||
}).AddCookie();
|
||||
}
|
||||
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
|
|
@ -25,6 +33,7 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
routes.MapConnectionHandler<EchoConnectionHandler>("/echo");
|
||||
routes.MapConnectionHandler<WriteThenCloseConnectionHandler>("/echoAndClose");
|
||||
routes.MapConnectionHandler<HttpHeaderConnectionHandler>("/httpheader");
|
||||
routes.MapConnectionHandler<AuthConnectionHandler>("/auth");
|
||||
});
|
||||
|
||||
app.UseSignalR(routes =>
|
||||
|
|
|
|||
|
|
@ -107,6 +107,30 @@ namespace Microsoft.AspNetCore.SignalR.Tests
|
|||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[WebSocketsSupportedCondition]
|
||||
public async Task WebSocketsTransportSendsXRequestedWithHeader()
|
||||
{
|
||||
using (StartLog(out var loggerFactory))
|
||||
{
|
||||
var pair = DuplexPipe.CreateConnectionPair(PipeOptions.Default, PipeOptions.Default);
|
||||
var webSocketsTransport = new WebSocketsTransport(httpOptions: null, loggerFactory: loggerFactory);
|
||||
await webSocketsTransport.StartAsync(new Uri(_serverFixture.WebSocketsUrl + "/httpheader"), pair.Application,
|
||||
TransferFormat.Binary, connection: Mock.Of<IConnection>()).OrTimeout();
|
||||
|
||||
await pair.Transport.Output.WriteAsync(Encoding.UTF8.GetBytes("X-Requested-With"));
|
||||
|
||||
// The HTTP header endpoint closes the connection immediately after sending response which should stop the transport
|
||||
await webSocketsTransport.Running.OrTimeout();
|
||||
|
||||
Assert.True(pair.Transport.Input.TryRead(out var result));
|
||||
|
||||
string headerValue = Encoding.UTF8.GetString(result.Buffer.ToArray());
|
||||
|
||||
Assert.Equal("XMLHttpRequest", headerValue);
|
||||
}
|
||||
}
|
||||
|
||||
[ConditionalFact]
|
||||
[WebSocketsSupportedCondition]
|
||||
public async Task WebSocketsTransportStopsWhenConnectionChannelClosed()
|
||||
|
|
|
|||
Loading…
Reference in New Issue