Skip to content

Commit 1a70a1e

Browse files
committed
Extract helper method; add tests.
1 parent 5255547 commit 1a70a1e

File tree

3 files changed

+67
-29
lines changed

3 files changed

+67
-29
lines changed

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -477,37 +477,21 @@ public async Task ConnectAsync(ConnectionSettings cs, int startTickCount, ILoadB
477477
{
478478
Log.Info("Session{0} is already redirected; ignoring it.", m_logArguments);
479479
}
480-
else
480+
else if (Utility.TryParseRedirectionHeader(ok.StatusInfo, out var host, out var port, out var user))
481481
{
482-
var hostIndex = 18;
483-
var colonIndex = ok.StatusInfo.IndexOf(':', hostIndex);
484-
if (colonIndex != -1)
485-
{
486-
var host = ok.StatusInfo.Substring(hostIndex, colonIndex - hostIndex);
487-
var portIndex = colonIndex + 1;
488-
var userIndex = ok.StatusInfo.IndexOf("/user=", StringComparison.Ordinal);
489-
if (userIndex != -1)
490-
{
491-
if (int.TryParse(ok.StatusInfo.Substring(portIndex, userIndex - portIndex), out var port))
492-
{
493-
var ampersandIndex = ok.StatusInfo.IndexOf('&', userIndex);
494-
var userId = ampersandIndex == -1 ? ok.StatusInfo.Substring(userIndex + 6) : ok.StatusInfo.Substring(userIndex + 6, ampersandIndex - userIndex - 6);
495-
Log.Info("Session{0} found server redirection Host={1}; Port={2}; User={3}", m_logArguments[0], host, port, userId);
482+
Log.Info("Session{0} found server redirection Host={1}; Port={2}; User={3}", m_logArguments[0], host, port, user);
496483

497-
if (host != cs.HostNames![0] || port != cs.Port || userId != cs.UserID)
498-
{
499-
Log.Info("Session{0} closing existing connection", m_logArguments);
500-
await SendAsync(QuitPayload.Instance, ioBehavior, cancellationToken).ConfigureAwait(false);
501-
Log.Info("Session{0} opening new connection to Host={1}; Port={2}; User={3}", m_logArguments[0], host, port, userId);
502-
cs = cs.CloneWith(host, port, userId, isRedirected: true);
503-
goto serverRedirection;
504-
}
505-
else
506-
{
507-
Log.Info("Session{0} is already connected to this server; ignoring redirection", m_logArguments);
508-
}
509-
}
510-
}
484+
if (host != cs.HostNames![0] || port != cs.Port || user != cs.UserID)
485+
{
486+
Log.Info("Session{0} closing existing connection", m_logArguments);
487+
await SendAsync(QuitPayload.Instance, ioBehavior, cancellationToken).ConfigureAwait(false);
488+
Log.Info("Session{0} opening new connection to Host={1}; Port={2}; User={3}", m_logArguments[0], host, port, user);
489+
cs = cs.CloneWith(host, port, user, isRedirected: true);
490+
goto serverRedirection;
491+
}
492+
else
493+
{
494+
Log.Info("Session{0} is already connected to this server; ignoring redirection", m_logArguments);
511495
}
512496
}
513497
}

src/MySqlConnector/Utilities/Utility.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,34 @@ public static void Resize<T>([NotNull] ref ResizableArray<T>? resizableArray, in
318318
resizableArray.DoResize(newLength);
319319
}
320320

321+
public static bool TryParseRedirectionHeader(string header, out string host, out int port, out string user)
322+
{
323+
host = "";
324+
port = 0;
325+
user = "";
326+
327+
if (!header.StartsWith("Location: mysql://", StringComparison.Ordinal))
328+
return false;
329+
330+
var hostIndex = 18;
331+
var colonIndex = header.IndexOf(':', hostIndex);
332+
if (colonIndex == -1)
333+
return false;
334+
335+
host = header.Substring(hostIndex, colonIndex - hostIndex);
336+
var portIndex = colonIndex + 1;
337+
var userIndex = header.IndexOf("/user=", StringComparison.Ordinal);
338+
if (userIndex == -1)
339+
return false;
340+
341+
if (!int.TryParse(header.Substring(portIndex, userIndex - portIndex), out port) || port <= 0)
342+
return false;
343+
344+
var ampersandIndex = header.IndexOf('&', userIndex);
345+
user = ampersandIndex == -1 ? header.Substring(userIndex + 6) : header.Substring(userIndex + 6, ampersandIndex - userIndex - 6);
346+
return true;
347+
}
348+
321349
public static TimeSpan ParseTimeSpan(ReadOnlySpan<byte> value)
322350
{
323351
var originalValue = value;

tests/MySqlConnector.Tests/UtilityTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,32 @@ namespace MySqlConnector.Tests
88
{
99
public class UtilityTests
1010
{
11+
[Theory]
12+
[InlineData("Location: mysql://host.example.com:1234/user=user@host", "host.example.com", 1234, "user@host")]
13+
[InlineData("Location: mysql://host.example.com:1234/user=user@host&ttl=60", "host.example.com", 1234, "user@host")]
14+
public void ParseRedirectionHeader(string input, string expectedHost, int expectedPort, string expectedUser)
15+
{
16+
Assert.True(Utility.TryParseRedirectionHeader(input, out var host, out var port, out var user));
17+
Assert.Equal(expectedHost, host);
18+
Assert.Equal(expectedPort, port);
19+
Assert.Equal(expectedUser, user);
20+
}
21+
22+
[Theory]
23+
[InlineData("")]
24+
[InlineData("Location: mysql")]
25+
[InlineData("Location: mysql://host.example.com")]
26+
[InlineData("Location: mysql://host.example.com:123")]
27+
[InlineData("Location: mysql://host.example.com:123/")]
28+
[InlineData("Location: mysql://host.example.com:/user=")]
29+
[InlineData("Location: mysql://host.example.com:/user=user@host")]
30+
[InlineData("Location: mysql://host.example.com:-1/user=user@host")]
31+
[InlineData("Location: mysql://host.example.com:0/user=user@host")]
32+
public void ParseRedirectionHeaderFails(string input)
33+
{
34+
Assert.False(Utility.TryParseRedirectionHeader(input, out _, out _, out _));
35+
}
36+
1137
[Theory]
1238
[InlineData("00:00:00", "00:00:00")]
1339
[InlineData("00:00:01", "00:00:01")]

0 commit comments

Comments
 (0)