QDG Knowledge Base Read-only viewer QWebHub
general

API.DataRouter

Version 1 · Document the API.DataRouter data-feed API: endpoints, services, middleware, config

API.DataRouter

The central data-feed REST API. It routes and serves racing data (race cards, results, trials, meetings, master data, lookups) from MySQL, and applies per-customer [[data-fingerprinting]] to outbound feeds. It is the only project in the solution with a Dockerfile and docker-compose.yml.

SDK: Microsoft.NET.Sdk.Web. Key packages: MySql.Data 9.1.0, Newtonsoft.Json 13.0.4, Swashbuckle.AspNetCore 6.4.0, Microsoft.AspNetCore.OpenApi 8.0.7. Project reference: DataFingerprinting.

Startup

Program.cs registers controllers, Swagger (currently always on), and AddFingerprinting(Configuration). It reads three connection strings — RasDb, QdsDb, QdsDbTemp — and registers the data services as singletons: RaceCardService, RaceResultService (injected IFingerprintService), LookupService, MasterDataService, MeetingService, TrialService. ApiKeyCustomerMiddleware runs before MapControllers().

Data access is raw ADO.NET over MySqlConnection with SQL strings — no ORM.

Endpoints

Controller Route(s)
RaceCardController GET /api/RaceCard/{meetingId}, GET /api/RaceCard/racecard10/{meetingId}
RaceResultController GET /api/RaceResult/{meetingId} — reads the resolved customer id from HttpContext.Items and passes it to the service for fingerprinting
TrialController GET /api/Trial?date=yyyy-MM-dd&courseId=…
MeetingController GET /api/Meeting?type={racecard|result|trial}&date=&token=&discipline=
MasterDataController POST /api/v1/masterdata/weather
LookupController POST /api/v1/lookup/read, POST /api/v1/lookup/write (write rejects array payloads; maps 200/201/400/404/409/413/500)
IdTranslatorController POST /api/IdTranslator/encode, POST /api/IdTranslator/decode

Services

  • LookupService — generic_lookup read/write.
  • MasterDataService — weather upsert across multiple QDS connections, with country / course resolution.
  • MeetingService — meeting lists by type / date / discipline.
  • RaceCardService — race cards (plus weather-by-race and stewards incidents).
  • RaceResultService — race results; injects IFingerprintService and fingerprints race_time_seconds, runner_time_seconds, and sectional times.
  • TrialService — barrier-trial data.

Utilities

  • IdTranslator — encodes/decodes record ids to/from ROT13-obfuscated GUIDs carrying table enum, record id, and version.
  • IdResolver — Resolve(encodedId, TableType).
  • Helpers, Common, JsonExtensions.

Middleware

ApiKeyCustomerMiddleware reads the X-Api-Key header, matches it to a configured customer's ApiKey, and stashes the customer id in HttpContext.Items. Non-blocking: an absent or unknown key simply means no fingerprinting — the request is still served. This header identifies a fingerprinting customer only; it does not authenticate or authorize the request.

Configuration

appsettings.json holds the three connection strings and the Fingerprinting section (Customers and Policies). docker-compose.yml runs the service as api-datarouter on 8080:8080 with ASPNETCORE_ENVIRONMENT=Production, overriding RasDb / QdsDb (→ qds_dev) via env vars. The Dockerfile is a multi-stage build on the .NET 8 aspnet/sdk images, exposing 8080.

Live MySQL credentials are currently committed in appsettings.json and docker-compose.yml. Treat them as secrets and move them to a secret store before deployment.

Naming note

The QDG.* namespaces (QDG.Services.LookupService, QDG.Controllers.LookupController, QDG.DTOs) physically live in this project, not in the separate QDG MVC project.

Updated by Claude on Aug. 4, 2026, 12:30 p.m. · Task: updatewiki create project documentation