Skip to content

Commit a7409ea

Browse files
PankajBhojwaniDHowett
authored andcommitted
Update Azure Cloud Shell for their new URI format (#16247)
The Azure cloud shell team made some API changes that required us to format our requests a little differently. This PR makes those changes (more info in the comments in the code) Closes #16098 (cherry picked from commit 5a9f352) Service-Card-Id: 90985893 Service-Version: 1.19
1 parent 28a1ecb commit a7409ea

File tree

3 files changed

+54
-5
lines changed

3 files changed

+54
-5
lines changed

.github/actions/spelling/allow/allow.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
aci
12
admins
23
allcolors
34
Apc
@@ -8,6 +9,7 @@ breadcrumbs
89
bsd
910
calt
1011
ccmp
12+
ccon
1113
changelog
1214
clickable
1315
clig
@@ -91,6 +93,7 @@ reserialize
9193
reserializes
9294
rlig
9395
runtimes
96+
servicebus
9497
shcha
9598
slnt
9699
Sos
@@ -116,6 +119,7 @@ vsdevcmd
116119
walkthrough
117120
walkthroughs
118121
We'd
122+
westus
119123
wildcards
120124
XBox
121125
YBox

src/cascadia/TerminalConnection/AzureConnection.cpp

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
398398

399399
switch (bufferType)
400400
{
401+
case WINHTTP_WEB_SOCKET_BINARY_MESSAGE_BUFFER_TYPE:
401402
case WINHTTP_WEB_SOCKET_UTF8_FRAGMENT_BUFFER_TYPE:
402403
case WINHTTP_WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE:
403404
{
@@ -797,7 +798,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
797798
// - an optional HTTP method (defaults to POST if content is present, GET otherwise)
798799
// Return value:
799800
// - the response from the server as a json value
800-
WDJ::JsonObject AzureConnection::_SendRequestReturningJson(std::wstring_view uri, const WWH::IHttpContent& content, WWH::HttpMethod method)
801+
WDJ::JsonObject AzureConnection::_SendRequestReturningJson(std::wstring_view uri, const WWH::IHttpContent& content, WWH::HttpMethod method, const Windows::Foundation::Uri referer)
801802
{
802803
if (!method)
803804
{
@@ -810,6 +811,11 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
810811
auto headers{ request.Headers() };
811812
headers.Accept().TryParseAdd(L"application/json");
812813

814+
if (referer)
815+
{
816+
headers.Referer(referer);
817+
}
818+
813819
const auto response{ _httpClient.SendRequestAsync(request).get() };
814820
const auto string{ response.Content().ReadAsStringAsync().get() };
815821
const auto jsonResult{ WDJ::JsonObject::Parse(string) };
@@ -974,17 +980,56 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
974980
auto uri{ fmt::format(L"{}terminals?cols={}&rows={}&version=2019-01-01&shell={}", _cloudShellUri, _initialCols, _initialRows, shellType) };
975981

976982
WWH::HttpStringContent content{
977-
L"",
983+
L"{}",
978984
WSS::UnicodeEncoding::Utf8,
979985
// LOAD-BEARING. the API returns "'content-type' should be 'application/json' or 'multipart/form-data'"
980986
L"application/json"
981987
};
982988

983-
const auto terminalResponse = _SendRequestReturningJson(uri, content);
989+
const auto terminalResponse = _SendRequestReturningJson(uri, content, WWH::HttpMethod::Post(), Windows::Foundation::Uri(_cloudShellUri));
984990
_terminalID = terminalResponse.GetNamedString(L"id");
985991

992+
// we have to do some post-handling to get the proper socket endpoint
993+
// the logic here is based on the way the cloud shell team itself does it
994+
winrt::hstring finalSocketUri;
995+
const std::wstring_view wCloudShellUri{ _cloudShellUri };
996+
997+
if (wCloudShellUri.find(L"servicebus") == std::wstring::npos)
998+
{
999+
// wCloudShellUri does not contain the word "servicebus", we can just use it to make the final URI
1000+
1001+
// remove the "https" from the cloud shell URI
1002+
const auto uriWithoutProtocol = wCloudShellUri.substr(5);
1003+
1004+
finalSocketUri = fmt::format(FMT_COMPILE(L"wss{}terminals/{}"), uriWithoutProtocol, _terminalID);
1005+
}
1006+
else
1007+
{
1008+
// if wCloudShellUri contains the word "servicebus", that means the returned socketUri is of the form
1009+
// wss://ccon-prod-westus-aci-03.servicebus.windows.net/cc-AAAA-AAAAAAAA//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
1010+
// we need to change it to:
1011+
// wss://ccon-prod-westus-aci-03.servicebus.windows.net/$hc/cc-AAAA-AAAAAAAA/terminals/aaaaaaaaaaaaaaaaaaaaaa
1012+
1013+
const auto socketUri = terminalResponse.GetNamedString(L"socketUri");
1014+
const std::wstring_view wSocketUri{ socketUri };
1015+
1016+
// get the substring up until the ".net"
1017+
const auto dotNetStart = wSocketUri.find(L".net");
1018+
THROW_HR_IF(E_UNEXPECTED, dotNetStart == std::wstring::npos);
1019+
const auto dotNetEnd = dotNetStart + 4;
1020+
const auto wSocketUriBody = wSocketUri.substr(0, dotNetEnd);
1021+
1022+
// get the portion between the ".net" and the "//" (this is the cc-AAAA-AAAAAAAA part)
1023+
const auto lastDoubleSlashPos = wSocketUri.find_last_of(L"//");
1024+
THROW_HR_IF(E_UNEXPECTED, lastDoubleSlashPos == std::wstring::npos);
1025+
const auto wSocketUriMiddle = wSocketUri.substr(dotNetEnd, lastDoubleSlashPos - (dotNetEnd));
1026+
1027+
// piece together the final uri, adding in the "$hc" and "terminals" where needed
1028+
finalSocketUri = fmt::format(FMT_COMPILE(L"{}/$hc{}terminals/{}"), wSocketUriBody, wSocketUriMiddle, _terminalID);
1029+
}
1030+
9861031
// Return the uri
987-
return terminalResponse.GetNamedString(L"socketUri");
1032+
return winrt::hstring{ finalSocketUri };
9881033
}
9891034

9901035
// Method description:

src/cascadia/TerminalConnection/AzureConnection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
6868

6969
void _WriteStringWithNewline(const std::wstring_view str);
7070
void _WriteCaughtExceptionRecord();
71-
winrt::Windows::Data::Json::JsonObject _SendRequestReturningJson(std::wstring_view uri, const winrt::Windows::Web::Http::IHttpContent& content = nullptr, winrt::Windows::Web::Http::HttpMethod method = nullptr);
71+
winrt::Windows::Data::Json::JsonObject _SendRequestReturningJson(std::wstring_view uri, const winrt::Windows::Web::Http::IHttpContent& content = nullptr, winrt::Windows::Web::Http::HttpMethod method = nullptr, const winrt::Windows::Foundation::Uri referer = nullptr);
7272
void _setAccessToken(std::wstring_view accessToken);
7373
winrt::Windows::Data::Json::JsonObject _GetDeviceCode();
7474
winrt::Windows::Data::Json::JsonObject _WaitForUser(const winrt::hstring& deviceCode, int pollInterval, int expiresIn);

0 commit comments

Comments
 (0)