Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions infra/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -914,13 +914,11 @@ module webServerFarm 'br/public:avm/res/web/serverfarm:0.7.0' = {

// ========== Web App ========== //
var webSiteResourceName = 'app-${solutionSuffix}'
// Backend URL: Use ACI IP (private or public) or FQDN depending on networking mode
var aciPrivateIpFallback = '10.0.4.4'
var aciPublicFqdnFallback = '${containerInstanceName}.${solutionLocation}.azurecontainer.io'
// For private networking use IP, for public use FQDN
// Backend URL: Use actual ACI IP/FQDN from deployment outputs
// This also creates an implicit dependency ensuring ACI deploys before the web app
var aciBackendUrl = enablePrivateNetworking
? 'http://${aciPrivateIpFallback}:8000'
: 'http://${aciPublicFqdnFallback}:8000'
? 'http://${containerInstance.outputs.ipAddress}:8000'
: 'http://${containerInstance.outputs.fqdn}:8000'
module webSite 'modules/web-sites.bicep' = {
name: take('module.web-sites.${webSiteResourceName}', 64)
params: {
Expand Down
16 changes: 7 additions & 9 deletions infra/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"_generator": {
"name": "bicep",
"version": "0.42.1.51946",
"templateHash": "12441959736083561218"
"templateHash": "9315041614692254935"
},
"name": "Intelligent Content Generation Accelerator",
"description": "Solution Accelerator for multimodal marketing content generation using Microsoft Agent Framework.\n"
Expand Down Expand Up @@ -383,9 +383,6 @@
"cosmosDBProductsContainer": "products",
"webServerFarmResourceName": "[format('asp-{0}', variables('solutionSuffix'))]",
"webSiteResourceName": "[format('app-{0}', variables('solutionSuffix'))]",
"aciPrivateIpFallback": "10.0.4.4",
"aciPublicFqdnFallback": "[format('{0}.{1}.azurecontainer.io', variables('containerInstanceName'), variables('solutionLocation'))]",
"aciBackendUrl": "[if(parameters('enablePrivateNetworking'), format('http://{0}:8000', variables('aciPrivateIpFallback')), format('http://{0}:8000', variables('aciPublicFqdnFallback')))]",
"containerInstanceName": "[format('aci-{0}', variables('solutionSuffix'))]"
},
"resources": {
Expand Down Expand Up @@ -24915,8 +24912,8 @@
},
"dependsOn": [
"aiFoundryAiServices",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').cognitiveServices)]",
"[format('avmPrivateDnsZones[{0}]', variables('dnsZoneIndex').openAI)]",
"virtualNetwork"
]
},
Expand Down Expand Up @@ -42336,7 +42333,7 @@
},
"virtualNetworkSubnetId": "[if(parameters('enablePrivateNetworking'), createObject('value', reference('virtualNetwork').outputs.webSubnetResourceId.value), createObject('value', null()))]",
"configs": {
"value": "[concat(createArray(createObject('name', 'appsettings', 'properties', createObject('DOCKER_REGISTRY_SERVER_URL', format('https://{0}.azurecr.io', variables('acrResourceName')), 'BACKEND_URL', variables('aciBackendUrl'), 'AZURE_CLIENT_ID', reference('userAssignedIdentity').outputs.clientId.value), 'applicationInsightResourceId', if(parameters('enableMonitoring'), reference('applicationInsights').outputs.resourceId.value, null()))), if(parameters('enableMonitoring'), createArray(createObject('name', 'logs', 'properties', createObject())), createArray()))]"
"value": "[concat(createArray(createObject('name', 'appsettings', 'properties', createObject('DOCKER_REGISTRY_SERVER_URL', format('https://{0}.azurecr.io', variables('acrResourceName')), 'BACKEND_URL', if(parameters('enablePrivateNetworking'), format('http://{0}:8000', reference('containerInstance').outputs.ipAddress.value), format('http://{0}:8000', reference('containerInstance').outputs.fqdn.value)), 'AZURE_CLIENT_ID', reference('userAssignedIdentity').outputs.clientId.value), 'applicationInsightResourceId', if(parameters('enableMonitoring'), reference('applicationInsights').outputs.resourceId.value, null()))), if(parameters('enableMonitoring'), createArray(createObject('name', 'logs', 'properties', createObject())), createArray()))]"
},
"enableMonitoring": {
"value": "[parameters('enableMonitoring')]"
Expand All @@ -42363,7 +42360,7 @@
"_generator": {
"name": "bicep",
"version": "0.42.1.51946",
"templateHash": "18300393946144087310"
"templateHash": "10464081739325272474"
}
},
"definitions": {
Expand Down Expand Up @@ -43402,7 +43399,7 @@
"_generator": {
"name": "bicep",
"version": "0.42.1.51946",
"templateHash": "1934732677721164061"
"templateHash": "904290865426801162"
},
"name": "Site App Settings",
"description": "This module deploys a Site App Setting."
Expand Down Expand Up @@ -43515,7 +43512,7 @@
"type": "Microsoft.Web/sites/config",
"apiVersion": "2025-03-01",
"name": "[format('{0}/{1}', parameters('appName'), parameters('name'))]",
"properties": "[union(parameters('properties'), parameters('currentAppSettings'), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(parameters('storageAccountResourceId'), '/')), listKeys('storageAccount', '2025-08-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), createObject('AzureWebJobsStorage__accountName', last(split(parameters('storageAccountResourceId'), '/')), 'AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob, 'AzureWebJobsStorage__queueServiceUri', reference('storageAccount').primaryEndpoints.queue, 'AzureWebJobsStorage__tableServiceUri', reference('storageAccount').primaryEndpoints.table), createObject())), if(not(empty(parameters('applicationInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('applicationInsights').ConnectionString), createObject()), variables('loggingProperties'))]",
"properties": "[union(parameters('currentAppSettings'), parameters('properties'), if(and(not(empty(parameters('storageAccountResourceId'))), not(parameters('storageAccountUseIdentityAuthentication'))), createObject('AzureWebJobsStorage', format('DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1};EndpointSuffix={2}', last(split(parameters('storageAccountResourceId'), '/')), listKeys('storageAccount', '2025-08-01').keys[0].value, environment().suffixes.storage)), if(and(not(empty(parameters('storageAccountResourceId'))), parameters('storageAccountUseIdentityAuthentication')), createObject('AzureWebJobsStorage__accountName', last(split(parameters('storageAccountResourceId'), '/')), 'AzureWebJobsStorage__blobServiceUri', reference('storageAccount').primaryEndpoints.blob, 'AzureWebJobsStorage__queueServiceUri', reference('storageAccount').primaryEndpoints.queue, 'AzureWebJobsStorage__tableServiceUri', reference('storageAccount').primaryEndpoints.table), createObject())), if(not(empty(parameters('applicationInsightResourceId'))), createObject('APPLICATIONINSIGHTS_CONNECTION_STRING', reference('applicationInsights').ConnectionString), createObject()), variables('loggingProperties'))]",
"dependsOn": [
"applicationInsights",
"storageAccount"
Expand Down Expand Up @@ -44286,6 +44283,7 @@
},
"dependsOn": [
"applicationInsights",
"containerInstance",
"logAnalyticsWorkspace",
"userAssignedIdentity",
"virtualNetwork",
Expand Down
14 changes: 7 additions & 7 deletions infra/main_custom.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -947,13 +947,13 @@ module webServerFarm 'br/public:avm/res/web/serverfarm:0.7.0' = {

// ========== Web App ========== //
var webSiteResourceName = 'app-${solutionSuffix}'
// Backend URL: Use ACI IP (private or public) or FQDN depending on networking mode
var aciPrivateIpFallback = '10.0.4.4'
var aciPublicFqdnFallback = '${containerInstanceName}.${solutionLocation}.azurecontainer.io'
// For private networking use IP, for public use FQDN
var aciBackendUrl = enablePrivateNetworking
? 'http://${aciPrivateIpFallback}:8000'
: 'http://${aciPublicFqdnFallback}:8000'
// Backend URL: Use actual ACI IP/FQDN from deployment outputs
// This also creates an implicit dependency ensuring ACI deploys before the web app
var aciBackendUrl = shouldDeployACI
? (enablePrivateNetworking
? 'http://${containerInstance!.properties.ipAddress.ip}:8000'
: 'http://${containerInstance!.properties.ipAddress.fqdn}:8000')
: ''
module webSite 'modules/web-sites.bicep' = {
name: take('module.web-sites.${webSiteResourceName}', 64)
params: {
Expand Down
2 changes: 1 addition & 1 deletion infra/modules/web-sites.config.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@ var loggingProperties = enableMonitoring && name == 'logs'
: {}

var expandedProperties = union(
properties,
currentAppSettings,
properties,
azureWebJobsValues,
appInsightsValues,
loggingProperties
Expand Down
16 changes: 11 additions & 5 deletions src/App/server/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ const http = require('http');
const app = express();
const PORT = process.env.PORT || 8080;

// Backend API URL (ACI private IP in VNet)
const BACKEND_URL = process.env.BACKEND_URL || 'http://10.0.4.5:8000';
// Backend API URL (injected via BACKEND_URL env var at deployment time)
if (!process.env.BACKEND_URL) {
console.error('ERROR: BACKEND_URL environment variable is not set. API proxy will not work.');
}
const BACKEND_URL = process.env.BACKEND_URL;
Comment thread
Ragini-Microsoft marked this conversation as resolved.

// Create HTTP agent with extended keep-alive timeout for long-running SSE connections
const httpAgent = new http.Agent({
Expand All @@ -18,7 +21,8 @@ const httpAgent = new http.Agent({
});

// Proxy API requests to backend
app.use('/api', createProxyMiddleware({
if (BACKEND_URL) {
app.use('/api', createProxyMiddleware({
target: BACKEND_URL,
changeOrigin: true,
pathRewrite: {
Expand Down Expand Up @@ -51,7 +55,7 @@ app.use('/api', createProxyMiddleware({
}
}
}));

}
// Serve static files from the build directory
app.use(express.static(path.join(__dirname, 'static')));

Expand All @@ -63,7 +67,9 @@ app.get('/{*path}', (req, res) => {
// Create server with extended timeouts for SSE
const server = app.listen(PORT, () => {
console.log(`Frontend server running on port ${PORT}`);
console.log(`Proxying API requests to ${BACKEND_URL}`);
if (BACKEND_URL) {
console.log(`Proxying API requests to ${BACKEND_URL}`);
}
});

// Extend server timeouts for long-running SSE connections
Expand Down
Loading