adas-core.module.ProxyDevices — Proxy Devices Module
A functional module of the ADAS Core platform.
Encapsulates all logic for proxying communication with external hardware devices over HTTP. This module acts as a configurable gateway layer that the Host registers at startup, translating internal requests into authenticated HTTP calls to remote endpoints.
Table of Contents
- Overview
- Responsibilities
- Project Structure
- Dependencies
- Device Proxy Architecture
- ProxyDeviceService Flow
- Design Rules
Overview
adas-core.module.ProxyDevices is a modular satellite project that provides a proxy gateway for interacting with external hardware devices over HTTP. It abstracts the complexity of device authentication, connection management, and response handling behind a uniform IProxyDevice contract.
Key characteristics:
- Modular Monolith Pattern — Self-contained module with its own device drivers, service orchestration, and configuration model. No other module depends on it directly.
- Plugin Architecture — New device types are added by creating a class that implements
IProxyDevice and naming it {Type}Device. The service discovers and instantiates them at runtime via reflection.
- Digest Authentication Support — The built-in
HttpDevice supports HTTP Digest authentication via NetworkCredential.
- Instance Caching —
ProxyDeviceService maintains an in-memory cache of initialized device instances to avoid repeated construction and initialization overhead.
- Dual Operation Modes — Each device supports both
Process() (full response) and Stream() (response-headers-read) operations.
- Configuration-Driven — All devices, their types, and parameters are defined in
ProxyDeviceSettings bound from appsettings.json.
Responsibilities
| Concern |
What this project does |
| Device Proxying |
Acts as an intermediary between the Host and external HTTP-based devices, shielding the rest of the system from protocol specifics. |
| Device Lifecycle |
Manages device initialization, caching, and disposal through the IProxyDevice contract. |
| HTTP Communication |
HttpDevice performs authenticated and unauthenticated HTTP GET requests with timeout handling. |
| Digest Authentication |
Supports HTTP Digest auth via username, password, and optional domain parameters. |
| Reflection-Based Factory |
ProxyDeviceService dynamically instantiates device classes by type name at runtime ({Type}Device). |
| Instance Caching |
Caches initialized IProxyDevice instances per deviceId to minimize repeated setup costs. |
| Streaming vs Processing |
Offers Process() for complete responses and Stream() for streaming (headers-first) scenarios. |
| Error Translation |
Converts HttpRequestException, TaskCanceledException, and missing-device errors into standardized HttpResponseMessage responses. |
| Configuration Model |
Defines ProxyDeviceSettings and ProxyDevice as strongly-typed configuration objects bound from the Host's configuration system. |
| Audit Logging |
Emits audit events for device access and proxy operations via AuditLogs. |
Project Structure
| File |
Role |
ProxyDeviceSettings.cs |
Configuration root. A List<ProxyDevice> bound from appsettings.json. Each entry defines Id, Type, Enabled, and Parameters. |
IProxyDevice.cs |
Interface contract. All proxy devices implement Initialize(Dictionary), Process(), and Stream(). |
HttpDevice.cs |
Concrete proxy for HTTP endpoints. Validates url, optional digest auth, performs GET requests, handles timeouts. |
IProxyDeviceService.cs |
Application-facing contract. Host controllers depend on this interface, not on module internals. |
ProxyDeviceService.cs |
Implementation. Reads settings, looks up devices by Id, lazily instantiates and caches drivers, delegates to Process() or Stream(). |
Dependencies
Downstream References
This project has no direct project references to other ADAS Core projects. It is a completely decoupled satellite module.
| Package |
Version |
Purpose |
Microsoft.Extensions.DependencyInjection |
10.0.8 |
DI registration helpers used during Host startup. |
Microsoft.Extensions.Hosting |
10.0.8 |
Hosting abstractions for optional background proxy services. |
Upstream References (projects that depend on this)
| Project |
Reason |
adas-core (Host) |
Registers IProxyDeviceService and ProxyDeviceSettings at startup. Host controllers invoke Process() and Stream() through the service interface. |
NuGet Packages
| Package |
Version |
Purpose |
Microsoft.Extensions.DependencyInjection |
10.0.8 |
Service-collection registration helpers. |
Microsoft.Extensions.Hosting |
10.0.8 |
Hosting abstractions for background services. |
Serilog |
4.3.1 |
Structured logging for timeout and HTTP error events. |
AuditLogs |
1.0.59 |
Audit trail emission for device access and proxy operations. |
SharpCompress |
0.49.0 |
Available for potential compression pipelines in future device types. |
Snappier |
1.3.1 |
Fast compression library for future streaming optimization. |
Device Proxy Architecture
IProxyDevice Contract
| Member |
Purpose |
Initialize(parameters) |
One-time setup. Validates required keys (url), extracts optional keys (name, username, password, domain), and marks the device as ready. |
Process() |
Performs a full HTTP GET request and returns the complete HttpResponseMessage. |
Stream() |
Performs an HTTP GET with HttpCompletionOption.ResponseHeadersRead, enabling callers to stream the body without buffering. |
HttpDevice — Built-in HTTP Proxy
- URI Validation — Requires a non-empty, absolute
url in parameters. Throws ArgumentNullException if missing or invalid.
- Single Initialization Guard — Throws
InvalidOperationException if Initialize() is called twice.
- Optional Digest Auth — When
username is provided, sets HttpClientHandler.Credentials with NetworkCredential(username, password, domain).
- Timeout Translation — Catches
TaskCanceledException (timeout) and re-throws as TimeoutException with a descriptive message.
- Diagnostics — Overrides
ToString() to emit [HttpDevice] (name uri username password domain) for logging.
Adding a New Device Type
- Create a class in
Devices/ that implements IProxyDevice.
- Name it
{Type}Device (e.g., TcpDevice, UdpDevice).
- Register the type string in
appsettings.json under ProxyDeviceSettings.
ProxyDeviceService will resolve it automatically via reflection at first use.
ProxyDeviceService Flow
Device Resolution & Caching
Key Behaviors
- Thread-Safe Cache — The
_cache dictionary is guarded by a lock during read/write to prevent race conditions.
- Lazy Instantiation — Devices are created only on first access, not at startup.
- Graceful Degradation — If a device is not found, disabled, or throws
HttpRequestException, the service returns an HttpResponseMessage with an appropriate status code rather than crashing.
- No Dispose Lifecycle — Cached instances are reused for the lifetime of the service. The Host manages the service scope (typically Singleton).
Design Rules
- True Module Independence — This project must not reference any other ADAS Core project. It communicates with the Host exclusively through its own public interfaces and the .NET configuration/options system.
- Configuration-Driven Discovery — Device types, endpoints, and credentials must come exclusively from
ProxyDeviceSettings bound to appsettings.json. No hardcoded URLs or auth secrets.
- Reflection Factory — New device types are added by convention (
{Type}Device implementing IProxyDevice). No central switch statement needs modification (Open/Closed).
- Cache Safety — The device instance cache is protected by a
lock during writes. Reads inside the lock are safe because initialization is atomic.
- Fail Securely — Missing or disabled devices return
404 Not Found. HTTP failures are translated into HttpResponseMessage with the original status code. Timeouts become TimeoutException.
- No Business Logic — This module handles transport only. Any transformation, validation, or business-rule enforcement belongs in
Application or the Host.
- Lazy Initialization — Devices are instantiated on first request, not at Host startup. This prevents delaying startup when a remote device is unreachable.
- Digest Auth Only —
HttpDevice supports HTTP Digest authentication. Basic auth, bearer tokens, or mTLS must be implemented in a separate IProxyDevice implementation if needed.
- Audit Every Access — Every
Process() and Stream() call emits an audit event via AuditLogs tagging the device ID and outcome.
- Singleton Service —
ProxyDeviceService is registered as a Singleton because it holds cached device instances and settings that are immutable after startup.
Back to adas-core Root README