Skip to main content

Service Endpoints

Service endpoints specify the URL where AWS services can be reached. By default, the AWS SDK connects to the real AWS services. Configure custom service endpoints for testing with LocalStack or other AWS-compatible services.

Default Behavior​

If you don't configure a service endpoint, the AWS SDK connects to the real AWS SNS and SQS services in the region you specified.

Configuration Methods​

WithServiceUrl(string url)​

Specify a custom service endpoint URL as a string.

config.Client(x =>
{
x.WithServiceUrl("http://localhost:4566");
});

WithServiceUri(Uri uri)​

Specify a custom service endpoint using a Uri object.

config.Client(x =>
{
x.WithServiceUri(new Uri("http://localhost:4566"));
});

LocalStack Configuration​

LocalStack provides a local AWS cloud stack for development and testing. Configure JustSaying to use LocalStack:

services.AddJustSaying(config =>
{
config.Client(x =>
{
x.WithServiceUri(new Uri("http://localhost:4566"))
.WithAnonymousCredentials();
});

config.Messaging(x =>
{
x.WithRegion("us-east-1"); // LocalStack default region
});

config.Publications(x =>
{
x.WithTopic<OrderPlacedEvent>();
});
});

Note: LocalStack uses port 4566 for all services by default.

Environment-Specific Configuration​

Use different configurations for different environments:

services.AddJustSaying(config =>
{
config.Client(x =>
{
if (hostEnvironment.IsDevelopment())
{
// LocalStack (local development)
x.WithServiceUri(new Uri("http://localhost:4566"))
.WithAnonymousCredentials();
}
else
{
// Production uses real AWS (no service URL configuration)
// IAM role provides credentials automatically
}
});

config.Messaging(x =>
{
x.WithRegion(configuration.GetValue<string>("AWS:Region"));
});
});

Configuration from Settings​

Store the LocalStack URL in configuration:

appsettings.Development.json:

{
"AWS": {
"ServiceUrl": "http://localhost:4566",
"Region": "us-east-1"
}
}

Startup configuration:

services.AddJustSaying(config =>
{
config.Client(x =>
{
var serviceUrl = configuration.GetValue<string>("AWS:ServiceUrl");
if (!string.IsNullOrEmpty(serviceUrl))
{
x.WithServiceUri(new Uri(serviceUrl))
.WithAnonymousCredentials();
}
});

config.Messaging(x =>
{
x.WithRegion(configuration.GetValue<string>("AWS:Region"));
});
});

Docker Compose Setup​

Run LocalStack using Docker Compose for local development:

docker-compose.yml:

version: '3.8'

services:
localstack:
image: localstack/localstack:latest
ports:
- "4566:4566"
environment:
- SERVICES=sns,sqs
- DEBUG=1
- DATA_DIR=/tmp/localstack/data
volumes:
- "./localstack-data:/tmp/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"

Start LocalStack:

docker-compose up -d

Your JustSaying application can now connect to LocalStack at http://localhost:4566.

Testing Considerations​

Integration Tests​

Configure tests to use LocalStack:

[Collection("LocalStack")]
public class MessagePublishingTests
{
private readonly IServiceProvider _serviceProvider;

public MessagePublishingTests()
{
var services = new ServiceCollection();

services.AddJustSaying(config =>
{
config.Client(x =>
{
x.WithServiceUri(new Uri("http://localhost:4566"))
.WithAnonymousCredentials();
});

config.Messaging(x => x.WithRegion("us-east-1"));
config.Publications(x => x.WithTopic<TestEvent>());
});

_serviceProvider = services.BuildServiceProvider();
}

[Fact]
public async Task Can_Publish_Message_To_LocalStack()
{
var publisher = _serviceProvider.GetRequiredService<IMessagePublisher>();
await publisher.PublishAsync(new TestEvent { Id = 123 });
// Assert
}
}

Testcontainers​

Use Testcontainers to automatically manage LocalStack containers in tests:

var localStackContainer = new ContainerBuilder()
.WithImage("localstack/localstack:latest")
.WithPortBinding(4566, 4566)
.WithEnvironment("SERVICES", "sns,sqs")
.Build();

await localStackContainer.StartAsync();

services.AddJustSaying(config =>
{
config.Client(x =>
{
x.WithServiceUri(new Uri("http://localhost:4566"))
.WithAnonymousCredentials();
});
});

Custom AWS-Compatible Services​

Service endpoints can be used with any AWS-compatible service that implements the SNS and SQS APIs:

  • LocalStack (local development)
  • ElasticMQ (SQS-compatible message queue)
  • Custom AWS service implementations

Configure the endpoint URL to point to your custom service.

Troubleshooting​

"Unable to connect to the remote server"​

Verify that:

  1. LocalStack is running: docker ps
  2. The service URL is correct
  3. The port is accessible from your application

Topics/Queues not persisting​

By default, LocalStack doesn't persist data. Mount a volume to persist data:

volumes:
- "./localstack-data:/tmp/localstack"

Region mismatch errors​

Ensure the region in .WithRegion(...) matches the LocalStack configuration. LocalStack uses us-east-1 by default.

See Also​