Getting 400 error when running basic auth test on apphost

Viewed 70

I have an apphost

    public class LocalTestAppHost : AppSelfHostBase
    {
        public LocalTestAppHost() : base(nameof(LocalTestAppHost), typeof(MyServices).Assembly, typeof(LocalTestAppHost).Assembly) { }


        public override void Configure(Container container)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(Directory.GetCurrentDirectory())
                // .AddJsonFile("appSettings.json")
                .AddEnvironmentVariables()
                .AddUserSecrets(typeof(IntegrationTest).Assembly);
            
            var configuration = builder.Build();
            
            AppSettings = new NetCoreAppSettings(configuration);

            container.AddSingleton<IAppSettings>(AppSettings);

            SetConfig(new HostConfig
            {
                AddRedirectParamsToQueryString = true,
                DebugMode = true
            });
            
            Plugins.Add(new CorsFeature(allowOriginWhitelist: new[] { IntegrationTestBase.BaseUriLocalDev },
                allowedMethods: "GET, PATCH, POST, PUT, DELETE, OPTIONS",
                allowCredentials: true,
                allowedHeaders: "Content-Type, Allow, Authorization"));
            
            JsConfig.DateHandler = DateHandler.ISO8601;
            
            var connectionString = AppSettings.GetString("DefaultConnection");

            OrmLiteConfig.StripUpperInLike = false;

            container.AddSingleton<IDbConnectionFactory>(new OrmLiteConnectionFactory(connectionString, PostgreSqlDialect.Provider));
            
            container.AddSingleton<IAuthRepository>(c =>
                new OrmLiteAuthRepository<UserAuthCustom, UserAuthDetails>(c.Resolve<IDbConnectionFactory>())
                {
                    UseDistinctRoleTables = true
                });
            
            Plugins.Add(new AuthFeature(() => new CustomUserSession(),
                new IAuthProvider[] {
                    new CredentialsAuthProvider(AppSettings)
                    {
                        
                    },     /* Sign In with Username / Password credentials */
                }));
            
            Plugins.Add(new AdminUsersFeature());
            
            
        }
    }

And I am trying to run simple test where I log in (using existing connection to my local db)

    public class ReportTests : IntegrationTestBase
    {
        private string _adminUser;
        private string _adminPass;
        public ReportTests()
        {
            Licensing.RegisterLicense(Licence);
            this.AppHost = new LocalTestAppHost()
                .Init()
                .Start(BaseUriLocalDev); 
            
            Settings = AppHost.Resolve<IAppSettings>();
            Db = AppHost.Resolve<IDbConnectionFactory>().OpenDbConnection();

            _adminUser = Settings.GetString("adminUser");
            _adminPass = Settings.GetString("adminPass");
        }

        [Test]
        public void TestStats()
        {
            var users = Db.Select<UserAuthCustom>();
            var client = new JsonServiceClient(BaseUriLocalDev);

            var authReq = new Authenticate()
            {
                UserName = _adminUser,
                Password = _adminPass,
                provider = CredentialsAuthProvider.Name
            };

            var resp = client.Post(authReq);
        }

But it throws this exception:

System.Net.WebException: Received an invalid status line: '400'.
 ---> System.Net.Http.HttpRequestException: Received an invalid status line: '400'.
   at System.Net.Http.HttpConnection.ParseStatusLine(Span`1 line, HttpResponseMessage response)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnection.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.DecompressionHandler.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
   at System.Net.Http.HttpMessageHandlerStage.Send(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.SocketsHttpHandler.Send(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClientHandler.Send(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpMessageInvoker.Send(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.SendAsyncCore(HttpRequestMessage request, HttpCompletionOption completionOption, Boolean async, Boolean emitTelemetryStartStop, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.Send(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
   at System.Net.HttpWebRequest.SendRequest(Boolean async)
   at System.Net.HttpWebRequest.GetResponse()
   --- End of inner exception stack trace ---
   at System.Net.HttpWebRequest.GetResponse()
   at ServiceStack.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 1416
   at ServiceStack.ServiceClientBase.Post[TResponse](IReturn`1 requestDto) in C:\BuildAgent\work\3481147c480f4a2f\src\ServiceStack.Client\ServiceClientBase.cs:line 1581
   at LeadInput.Tests.IntegrationTests.ReportTests.TestStats() in D:\Clients\LeadInput\LeadInput.Tests\IntegrationTests\ReportTests.cs:line 43

I am struggling to figure why it is not working and why it is not receiving a valid response from the apphost.

As the apphost only runs for scope of test I am finding it hard to debug. It seems like everything is correct but I am getting invalid response.

Stepping through code it is client.GetResponse(); that throws the exception, I guess it is getting unexpected format but I cannot see a way to get raw response in debugger.

Any ideas where I am going wrong?

EDIT

It happens also on hello world endpoint so I guess the AppHost is not running. I have tried changing the port but doesn't help. I upgraded to 5.13.3 recently, not sure if that's relevant.

EDIT

With debugger active this is logged:

DEBUG: CreateRequestAsync/requestParams: WARN: Could not Set-Cookie 'ss-id': Could not load type 'Microsoft.Extensions.Primitives.InplaceStringBuilder' from assembly 'Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'., Exception: Could not load type 'Microsoft.Extensions.Primitives.InplaceStringBuilder' from assembly 'Microsoft.Extensions.Primitives, Version=6.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.

1 Answers

You can try enabling debug logging in your AppHost to see if logs any info:

LogManager.LogFactory = new ConsoleLogFactory(debugEnabled:true); 

Don't forget your Integration test needs to dispose the AppHost after it's run or other integration tests will fail:

[OneTimeTearDown]
public void OneTimeTearDown() => AppHost.Dispose();

One way to view the response is run your AppHost for a long time then you can view the output by inspecting the HTTP Request externally, e.g. via Chrome's WebInspector or curl:

[Test]
public void Run_for_30secs()
{
    Thread.Sleep(30000);
}

It sounds like the AppHost isn't properly running, so I'd comment/disable features until you can isolate the problem.

Note: CORS isn't relevant in an integration test, it's only relevant when called from a Web browser making cross-domain requests.

Related