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
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ server {
}

location /api/ {
proxy_pass ${services__weatherapi__https__0};
proxy_pass ${WEATHERAPI_HTTPS};
proxy_http_version 1.1;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
module.exports = {
"/api": {
target:
process.env["services__weatherapi__https__0"] ||
process.env["services__weatherapi__http__0"],
process.env["WEATHERAPI_HTTPS"] || process.env["WEATHERAPI_HTTP"],
secure: process.env["NODE_ENV"] !== "development",
pathRewrite: {
"^/api": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ server {
}

location /api/ {
proxy_pass ${services__weatherapi__https__0};
proxy_pass ${WEATHERAPI_HTTPS};
proxy_http_version 1.1;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ module.exports = (env) => {
{
context: ["/api"],
target:
process.env.services__weatherapi__https__0 ||
process.env.services__weatherapi__http__0,
process.env.WEATHERAPI_HTTPS || process.env.WEATHERAPI_HTTP,
pathRewrite: { "^/api": "" },
secure: false,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ server {
}

location /api/ {
proxy_pass ${services__weatherapi__https__0};
proxy_pass ${WEATHERAPI_HTTPS};
proxy_http_version 1.1;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ export default defineConfig(({ mode }) => {
port: parseInt(env.VITE_PORT),
proxy: {
'/api': {
target: process.env.services__weatherapi__https__0 ||
process.env.services__weatherapi__http__0,
target: process.env.WEATHERAPI_HTTPS || process.env.WEATHERAPI_HTTP,
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
secure: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ server {
}

location /api/ {
proxy_pass ${services__weatherapi__https__0};
proxy_pass ${WEATHERAPI_HTTPS};
proxy_http_version 1.1;
proxy_ssl_server_name on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default defineConfig({
port: parseInt(process.env.PORT ?? "5173"),
proxy: {
'/api': {
target: process.env.services__weatherapi__https__0 || process.env.services__weatherapi__http__0,
target: process.env.WEATHERAPI_HTTPS || process.env.WEATHERAPI_HTTP,
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, ''),
secure: false
Expand Down
2 changes: 2 additions & 0 deletions playground/AspireWithJavaScript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ The app consists of four services:

### Experiencing the app

Before starting the app host run `npm install` in each javascript folder.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there not calls to .WithNpmPackageInstallation in the AppHost?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, didn't know about it then Damian told me. Should I add it in this PR? @IEvangelist note that the Vite sample doesn't work at all, issues with authenticating on npm, not sure if the extension method will take care of this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, dont' add it to this PR.


Once the app is running, the .NET Aspire dashboard will launch in your browser:

![.NET Aspire dashboard](./images/aspire-dashboard.png)
Expand Down
2 changes: 1 addition & 1 deletion playground/AspireWithNode/NodeFrontend/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const config = {
certFile: process.env['HTTPS_CERT_FILE'] ?? '',
certKeyFile: process.env['HTTPS_CERT_KEY_FILE'] ?? '',
cacheUrl: process.env['CACHE_URI'] ?? '',
apiServer: process.env['services__weatherapi__https__0'] ?? process.env['services__weatherapi__http__0']
apiServer: process.env['WEATHERAPI_HTTPS'] ?? process.env['WEATHERAPI_HTTP']
};
console.log(`config: ${JSON.stringify(config)}`);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ public static EndpointReference GetEndpoint(this IResourceBuilder<DevTunnelResou
ArgumentNullException.ThrowIfNull(targetEndpointReference);

var portResource = tunnelBuilder.Resource.Ports
.FirstOrDefault(p => p.TargetEndpoint.Resource == targetEndpointReference.Resource
.FirstOrDefault(p => p.TargetEndpoint.Resource == targetEndpointReference.Resource
&& StringComparers.EndpointAnnotationName.Equals(p.TargetEndpoint.EndpointName, targetEndpointReference.EndpointName));

if (portResource is null)
Expand All @@ -394,8 +394,9 @@ private static EndpointReference CreateEndpointReferenceWithError(DevTunnelResou
}

/// <summary>
/// Injects service discovery information as environment variables from the dev tunnel resource into the destination resource, using the tunneled resource's name as the service name.
/// Each endpoint defined on the target resource will be injected using the format "services__{sourceResourceName}__{endpointName}__{endpointIndex}={uriString}".
/// Injects service discovery and endpoint information as environment variables from the dev tunnel resource into the destination resource, using the tunneled resource's name as the service name.
/// Each endpoint defined on the target resource will be injected using the format defined by the <see cref="ReferenceEnvironmentInjectionAnnotation"/> on the destination resource, i.e.
/// either "services__{sourceResourceName}__{endpointName}__{endpointIndex}={uriString}" for .NET service discovery, or "{RESOURCE_ENDPOINT}={uri}" for endpoint injection.
/// </summary>
/// <remarks>
/// Referencing a dev tunnel will delay the start of the resource until the referenced dev tunnel's endpoint is allocated.
Expand All @@ -422,12 +423,25 @@ public static IResourceBuilder<TResource> WithReference<TResource>(this IResourc
.WithReferenceRelationship(tunnelResource)
.WithEnvironment(context =>
{
// Determine what to inject based on the annotation on the destination resource
var injectionAnnotation = context.Resource.TryGetLastAnnotation<ReferenceEnvironmentInjectionAnnotation>(out var annotation) ? annotation : null;
var flags = injectionAnnotation?.Flags ?? ReferenceEnvironmentInjectionFlags.All;

// Add environment variables for each tunnel port that references an endpoint on the target resource
foreach (var port in tunnelResource.Resource.Ports.Where(p => p.TargetEndpoint.Resource == targetResource.Resource))
{
var serviceName = targetResource.Resource.Name;
var endpointName = port.TargetEndpoint.EndpointName;
context.EnvironmentVariables[$"services__{serviceName}__{endpointName}__0"] = port.TunnelEndpoint;

if (flags.HasFlag(ReferenceEnvironmentInjectionFlags.ServiceDiscovery))
{
context.EnvironmentVariables[$"services__{serviceName}__{endpointName}__0"] = port.TunnelEndpoint;
}

if (flags.HasFlag(ReferenceEnvironmentInjectionFlags.Endpoints))
{
context.EnvironmentVariables[$"{serviceName.ToUpperInvariant()}_{endpointName.ToUpperInvariant()}"] = port.TunnelEndpoint;
}
}
});

Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.Qdrant/QdrantBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ public static IResourceBuilder<TDestination> WithReference<TDestination>(this IR
var connectionStringName = resource.ConnectionStringEnvironmentVariable ?? $"ConnectionStrings__{connectionName}";

// Determine what to inject based on the annotation on the destination resource
var injectionAnnotation = builder.Resource.Annotations.OfType<ReferenceEnvironmentInjectionAnnotation>().LastOrDefault();
var injectionAnnotation = builder.Resource.TryGetLastAnnotation<ReferenceEnvironmentInjectionAnnotation>(out var annotation) ? annotation : null;
var flags = injectionAnnotation?.Flags ?? ReferenceEnvironmentInjectionFlags.All;

if (flags.HasFlag(ReferenceEnvironmentInjectionFlags.ConnectionString))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace Aspire.Hosting.ApplicationModel;

/// <summary>
/// Annotation that specifies which connection information should be injected into environment variables
/// Annotation that specifies which connection and endpoint information should be injected into environment variables
/// when a resource is referenced using <c>WithReference()</c>.
/// </summary>
public sealed class ReferenceEnvironmentInjectionAnnotation : IResourceAnnotation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
namespace Aspire.Hosting.ApplicationModel;

/// <summary>
/// Specifies which connection information should be injected into environment variables when <c>WithReference()</c> is invoked.
/// Specifies which connection or endpoint information should be injected into environment variables when <c>WithReference()</c> is invoked.
/// </summary>
[Flags]
public enum ReferenceEnvironmentInjectionFlags
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can follow up on naming.

Expand All @@ -25,7 +25,17 @@ public enum ReferenceEnvironmentInjectionFlags
ConnectionProperties = 1 << 1,

/// <summary>
/// Both connection string and connection properties will be injected as environment variables.
/// Each endpoint defined on the resource will be injected using the format "services__{resourceName}__{endpointName}__{endpointIndex}".
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

endpointIndex

What is the reason we have an index at the end? How are those scenarios going to work with the Endpoints format?

Copy link
Member

@davidfowl davidfowl Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need index because each endpoint gets a single env variable. The service discovery format has a one to many relationship with endpoints. You can have 5 endpoints named differently with an http scheme and use the resource name (e.g. http://foo to refer to it). That will load balance across those 5 addresses at runtime.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can have 5 endpoints named differently with an http scheme and use the resource name (e.g. http://foo/ to refer to it). That will load balance across those 5 addresses at runtime.

In that case is endpointName correct above? Or is it uri.scheme?

If you have 5 endpoints named differently, why isn't services__{resourceName}__{endpointName} enough?

Copy link
Member

@davidfowl davidfowl Oct 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The service discovery implementation relies on IConfiguration and that is how you represent arrays:

{
    "services": {
        "foo":  [
            "http://locahost:5006",
            "http://locahost:5002"
            "http://locahost:5004"  
        ]
   }
}

"services__foo__http__0" The system does some munging to support different configuration formats but they are all ugly to support this model.

cc @ReubenBond

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and that is how you represent arrays

But in this new format, we aren't going to support arrays?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't any ENV defined by aspire that is not __0. We only have it because it's an array, but always use a single value right now. So for the new ENV there is no reason to have it used at all.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. We don't need it here.

/// </summary>
All = ConnectionString | ConnectionProperties
ServiceDiscovery = 1 << 2,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ServiceDiscovery enough in this context? Is it really .NET ServiceDiscovery? Even using the Endpoints format is still "service discovery", right? Just not the Microsoft.Extensions.ServiceDiscovery format.


/// <summary>
/// Each endpoint defined on the resource will be injected using the format "{RESOURCENAME}_{ENDPOINTNAME}".
/// </summary>
Endpoints = 1 << 3,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure Endpoints is the right name here. Maybe SimplifiedEndpoints? or SimpleEndpoints?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow up API review, I think this whole enum is unclear.


/// <summary>
/// Connection string, connection properties and service endpoints will be injected as environment variables.
/// </summary>
All = ConnectionString | ConnectionProperties | ServiceDiscovery | Endpoints
}
Loading