diff --git a/services/recommendation-service/dotnet/Program.cs b/services/recommendation-service/dotnet/Program.cs index e2d0b891..c744342e 100644 --- a/services/recommendation-service/dotnet/Program.cs +++ b/services/recommendation-service/dotnet/Program.cs @@ -21,11 +21,16 @@ // Add Semantic Kernel services builder.Services.AddSkServices(); -// Explicitly configure Kestrel to only use HTTP -builder.WebHost.ConfigureKestrel(serverOptions => +// Configure CORS to allow specific origins from KernelSettings +builder.Services.AddCors(options => { - // Remove the HTTPS endpoint if it's there - serverOptions.ListenAnyIP(80); // Listen on port 80 for HTTP + options.AddPolicy(name: "MiyagiAllowSpecificOrigins", + policy => + { + policy.WithOrigins(kernelSettings.CorsAllowedOrigins) + .AllowAnyHeader() + .AllowAnyMethod(); + }); }); var app = builder.Build(); @@ -34,9 +39,11 @@ app.UseSwagger(); app.UseSwaggerUI(); -app.UseCors(); +app.UseCors("MiyagiAllowSpecificOrigins"); // app.UseHttpsRedirection(); // Issue with Next.js to use https redirection +app.UseRouting(); + app.Map("/", () => Results.Redirect("/swagger")); // app.UseAuthorization(); diff --git a/services/recommendation-service/dotnet/config/KernelSettings.cs b/services/recommendation-service/dotnet/config/KernelSettings.cs index 83fefec0..fef92c28 100644 --- a/services/recommendation-service/dotnet/config/KernelSettings.cs +++ b/services/recommendation-service/dotnet/config/KernelSettings.cs @@ -50,6 +50,9 @@ internal class KernelSettings [JsonPropertyName("cosmosDbConnectionString")] public string CosmosDbConnectionString { get; set; } = string.Empty; + [JsonPropertyName("corsAllowedOrigins")] + public string[] CorsAllowedOrigins { get; set; } = Array.Empty(); + /// /// Load the kernel settings from settings.json if the file exists and if not attempt to use user secrets. diff --git a/ui/typescript/.env b/ui/typescript/.env index 8782e0e3..48c97dba 100644 --- a/ui/typescript/.env +++ b/ui/typescript/.env @@ -1,3 +1,3 @@ NEXT_PUBLIC_GA_MEASUREMENT_ID=G-DC9QMEZBZL -RECCOMMENDATION_SERVICE_URL=http://localhost:5224 +NEXT_PUBLIC_RECCOMMENDATION_SERVICE_URL=http://localhost:5224 NEXT_PUBLIC_COPILOT_CHAT_BASE_URL=https://copilotdemo.app \ No newline at end of file diff --git a/ui/typescript/.env.local.example b/ui/typescript/.env.local.example index 5bdae45c..9da38b3d 100644 --- a/ui/typescript/.env.local.example +++ b/ui/typescript/.env.local.example @@ -1,5 +1,5 @@ NEXT_PUBLIC_GA_MEASUREMENT_ID= -RECCOMMENDATION_SERVICE_URL= +NEXT_PUBLIC_RECCOMMENDATION_SERVICE_URL= NEXT_PUBLIC_CHAT_ID= COPILOT_CHAT_BASE_URL= NEXT_PUBLIC_COPILOT_CHAT_BASE_URL= diff --git a/ui/typescript/app/chat-session/route.ts b/ui/typescript/app/chat-session/route.ts index 9dd9a03f..65100be9 100644 --- a/ui/typescript/app/chat-session/route.ts +++ b/ui/typescript/app/chat-session/route.ts @@ -3,10 +3,10 @@ import { NextResponse } from 'next/server'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const userId = searchParams.get('userId'); - const RECCOMMENDATION_SERVICE_URL = `${process.env.NEXT_PUBLIC_COPILOT_CHAT_BASE_URL}/chats` + const chatsUrl = `${process.env.NEXT_PUBLIC_COPILOT_CHAT_BASE_URL}/chats` console.log("Request body: "); console.dir(userId) - const res = await fetch(RECCOMMENDATION_SERVICE_URL, { + const res = await fetch(chatsUrl, { method: 'POST', headers: { 'Content-type': `application/json` diff --git a/ui/typescript/app/chatSession/getAllChats/route.ts b/ui/typescript/app/chatSession/getAllChats/route.ts index 9dd9a03f..65100be9 100644 --- a/ui/typescript/app/chatSession/getAllChats/route.ts +++ b/ui/typescript/app/chatSession/getAllChats/route.ts @@ -3,10 +3,10 @@ import { NextResponse } from 'next/server'; export async function GET(request: Request) { const { searchParams } = new URL(request.url); const userId = searchParams.get('userId'); - const RECCOMMENDATION_SERVICE_URL = `${process.env.NEXT_PUBLIC_COPILOT_CHAT_BASE_URL}/chats` + const chatsUrl = `${process.env.NEXT_PUBLIC_COPILOT_CHAT_BASE_URL}/chats` console.log("Request body: "); console.dir(userId) - const res = await fetch(RECCOMMENDATION_SERVICE_URL, { + const res = await fetch(chatsUrl, { method: 'POST', headers: { 'Content-type': `application/json` diff --git a/ui/typescript/app/personalize/route.ts b/ui/typescript/app/personalize/route.ts index c6627c74..05652fcf 100644 --- a/ui/typescript/app/personalize/route.ts +++ b/ui/typescript/app/personalize/route.ts @@ -2,11 +2,11 @@ import { NextResponse } from 'next/server'; export async function POST(request: Request) { console.dir(request); - const RECCOMMENDATION_SERVICE_URL = `${process.env.RECCOMMENDATION_SERVICE_URL}/personalize` + const personalizeUrl = `${process.env.NEXT_PUBLIC_RECCOMMENDATION_SERVICE_URL}/personalize` const { body } = request console.log("Request body: "); console.dir(body) - const res = await fetch(RECCOMMENDATION_SERVICE_URL, { + const res = await fetch(personalizeUrl, { method: 'POST', headers: { 'Content-type': `application/json` }, duplex: 'half', diff --git a/ui/typescript/src/components/personalize/personalize-drawer.tsx b/ui/typescript/src/components/personalize/personalize-drawer.tsx index 341b0edb..76be032c 100644 --- a/ui/typescript/src/components/personalize/personalize-drawer.tsx +++ b/ui/typescript/src/components/personalize/personalize-drawer.tsx @@ -76,18 +76,33 @@ export default function PersonalizeDrawer() { stocks, }; - const response = await personalizeMutation.mutateAsync(requestData); - console.log('Successfully got personalization'); + const response = await fetch(`${process.env.NEXT_PUBLIC_RECCOMMENDATION_SERVICE_URL}/personalize`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(requestData), + }); + console.dir(response); + + if (!response.ok) { + console.error('HTTP error: ', response); + toast.error('Failed to fetch personalization. Try again later.'); + } + + const responseData = await response.json(); + console.log('Successfully got personalization'); + console.dir(responseData); toast.success('Personalization successful'); // Extract the relevant data from the response - const updatedAssetData = response.assets.portfolio.map((item, index) => ({ + const updatedAssetData = responseData.assets.portfolio.map((item, index) => ({ ...assetsInfo[index], gptRecommendation: item.gptRecommendation, })); - const updatedInvestmentData = response.investments.portfolio.map((item, index) => ({ + const updatedInvestmentData = responseData.investments.portfolio.map((item, index) => ({ ...investmentsInfo[index], gptRecommendation: item.gptRecommendation, })); @@ -107,6 +122,7 @@ export default function PersonalizeDrawer() { } }; + return (