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:
- LocalStack is running:
docker ps - The service URL is correct
- 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
- Credentials - Anonymous credentials for LocalStack
- Testing - Testing strategies with JustSaying
- LocalStack Documentation - LocalStack setup and configuration