Skip to content

Commit e5667a9

Browse files
authored
[Templates] Update the react template to use the CLI proxy (#31652)
Updates the react template to use the http-proxy-middleware for handling the requests instead of the asp.net core proxy in the same way it's done for the Angular template.
1 parent 77e5784 commit e5667a9

File tree

15 files changed

+16346
-53
lines changed

15 files changed

+16346
-53
lines changed

src/Middleware/Spa/SpaProxy/src/SpaProxyLaunchManager.cs

+3-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ private async Task<bool> ProbeSpaDevelopmentServerUrl(HttpClient httpClient, Can
6363
var running = response.IsSuccessStatusCode;
6464
return running;
6565
}
66-
catch (Exception exception) when (exception is HttpRequestException || exception is TaskCanceledException)
66+
catch (Exception exception) when (exception is HttpRequestException ||
67+
exception is TaskCanceledException ||
68+
exception is OperationCanceledException)
6769
{
6870
_logger.LogDebug(exception, "Failed to connect to the SPA Development proxy.");
6971
return false;

src/ProjectTemplates/Web.Spa.ProjectTemplates/Angular-CSharp.csproj.in

-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
<SpaProxyServerUrl Condition="'$(RequiresHttps)' != 'True'">http://localhost:5002</SpaProxyServerUrl>
99
<SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
1010
<NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
11-
1211
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.WebApplication1</RootNamespace>
1312
</PropertyGroup>
1413

src/ProjectTemplates/Web.Spa.ProjectTemplates/React-CSharp.csproj.in

+6-2
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,19 @@
88
<SpaRoot>ClientApp\</SpaRoot>
99
<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
1010
<NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
11+
<SpaProxyServerUrl Condition="'$(RequiresHttps)' == 'True'">https://localhost:5002</SpaProxyServerUrl>
12+
<SpaProxyServerUrl Condition="'$(RequiresHttps)' != 'True'">http://localhost:5002</SpaProxyServerUrl>
13+
<SpaProxyLaunchCommand>npm start</SpaProxyLaunchCommand>
14+
<NoDefaultLaunchSettingsFile Condition="'$(ExcludeLaunchSettings)' == 'True'">True</NoDefaultLaunchSettingsFile>
1115
<RootNamespace Condition="'$(name)' != '$(name{-VALUE-FORMS-}safe_namespace)'">Company.WebApplication1</RootNamespace>
1216
</PropertyGroup>
1317

1418
<ItemGroup>
15-
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="${MicrosoftAspNetCoreSpaServicesExtensionsVersion}" />
1619
<PackageReference Include="Microsoft.AspNetCore.ApiAuthorization.IdentityServer" Version="${MicrosoftAspNetCoreApiAuthorizationIdentityServerVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
1720
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="${MicrosoftAspNetCoreDiagnosticsEntityFrameworkCoreVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
1821
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="${MicrosoftAspNetCoreIdentityEntityFrameworkCoreVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
1922
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="${MicrosoftAspNetCoreIdentityUIVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
23+
<PackageReference Include="Microsoft.AspNetCore.SpaProxy" Version="${MicrosoftAspNetCoreSpaProxyVersion}" />
2024
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="${MicrosoftEntityFrameworkCoreRelationalVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' " />
2125
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="${MicrosoftEntityFrameworkCoreSqlServerVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' AND '$(UseLocalDB)' == 'True'" />
2226
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="${MicrosoftEntityFrameworkCoreSqliteVersion}" Condition=" '$(IndividualLocalAuth)' == 'True' AND '$(UseLocalDB)' != 'True'" />
@@ -54,7 +58,7 @@
5458
<ItemGroup>
5559
<DistFiles Include="$(SpaRoot)build\**" />
5660
<ResolvedFileToPublish Include="@(DistFiles->'%(FullPath)')" Exclude="@(ResolvedFileToPublish)">
57-
<RelativePath>%(DistFiles.Identity)</RelativePath>
61+
<RelativePath>wwwroot\%(RecursiveDir)%(FileName)%(Extension)</RelativePath>
5862
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
5963
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
6064
</ResolvedFileToPublish>

src/ProjectTemplates/Web.Spa.ProjectTemplates/content/Angular-CSharp/Startup.cs

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public void ConfigureServices(IServiceCollection services)
5454
services.AddAuthentication()
5555
.AddIdentityServerJwt();
5656
#endif
57+
5758
services.AddControllersWithViews();
5859
#if (IndividualLocalAuth)
5960
services.AddRazorPages();

src/ProjectTemplates/Web.Spa.ProjectTemplates/content/React-CSharp/.template.config/template.json

+7
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@
3939
"Controllers/OidcConfigurationController.cs"
4040
]
4141
},
42+
{
43+
"condition": "(!RequiresHttps)",
44+
"exclude": [
45+
"ClientApp/aspnetcore-https.js",
46+
"ClientApp/aspnetcore-react.js"
47+
]
48+
},
4249
{
4350
"condition": "(!IndividualLocalAuth || UseLocalDB)",
4451
"exclude": [
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
PORT=5002
2+
//#if(RequiresHttps)
3+
HTTPS=true
4+
//#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// This script sets up HTTPS for the application using the ASP.NET Core HTTPS certificate
2+
const fs = require('fs');
3+
const spawn = require('child_process').spawn;
4+
const path = require('path');
5+
6+
const baseFolder =
7+
process.env.APPDATA !== undefined && process.env.APPDATA !== ''
8+
? `${process.env.APPDATA}/ASP.NET/https`
9+
: `${process.env.HOME}/.aspnet/https`;
10+
11+
const certificateArg = process.argv.map(arg => arg.match(/--name=(?<value>.+)/i)).filter(Boolean)[0];
12+
const certificateName = certificateArg ? certificateArg.groups.value : process.env.npm_package_name;
13+
14+
if (!certificateName) {
15+
console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<<app>> explicitly.')
16+
process.exit(-1);
17+
}
18+
19+
const certFilePath = path.join(baseFolder, `${certificateName}.pem`);
20+
const keyFilePath = path.join(baseFolder, `${certificateName}.key`);
21+
22+
if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) {
23+
spawn('dotnet', [
24+
'dev-certs',
25+
'https',
26+
'--export-path',
27+
certFilePath,
28+
'--format',
29+
'Pem',
30+
'--no-password',
31+
], { stdio: 'inherit', })
32+
.on('exit', (code) => process.exit(code));
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// This script configures the .env.development.local file with additional environment variables to configure HTTPS using the ASP.NET Core
2+
// development certificate in the webpack development proxy.
3+
4+
const fs = require('fs');
5+
const path = require('path');
6+
7+
const baseFolder =
8+
process.env.APPDATA !== undefined && process.env.APPDATA !== ''
9+
? `${process.env.APPDATA}/ASP.NET/https`
10+
: `${process.env.HOME}/.aspnet/https`;
11+
12+
const certificateArg = process.argv.map(arg => arg.match(/--name=(?<value>.+)/i)).filter(Boolean)[0];
13+
const certificateName = certificateArg ? certificateArg.groups.value : process.env.npm_package_name;
14+
15+
if (!certificateName) {
16+
console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<<app>> explicitly.')
17+
process.exit(-1);
18+
}
19+
20+
const certFilePath = path.join(baseFolder, `${certificateName}.pem`);
21+
const keyFilePath = path.join(baseFolder, `${certificateName}.key`);
22+
23+
if (!fs.existsSync('.env.development.local')) {
24+
fs.writeFileSync(
25+
'.env.development.local',
26+
`SSL_CRT_FILE=${certFilePath}
27+
SSL_KEY_FILE=${keyFilePath}`
28+
);
29+
} else {
30+
let lines = fs.readFileSync('.env.development.local')
31+
.toString()
32+
.split('\n');
33+
34+
let hasCert, hasCertKey = false;
35+
for (const line of lines) {
36+
if (/SSL_CRT_FILE=.*/i.test(line)) {
37+
hasCert = true;
38+
}
39+
if (/SSL_KEY_FILE=.*/i.test(line)) {
40+
hasCertKey = true;
41+
}
42+
}
43+
if (!hasCert) {
44+
fs.appendFileSync(
45+
'.env.development.local',
46+
`\nSSL_CRT_FILE=${certFilePath}`
47+
);
48+
}
49+
if (!hasCertKey) {
50+
fs.appendFileSync(
51+
'.env.development.local',
52+
`\nSSL_KEY_FILE=${keyFilePath}`
53+
);
54+
}
55+
}

0 commit comments

Comments
 (0)