2.7 KiB
2.7 KiB
Спецификация 01: GarminClient — SSO и API Garmin Connect
Источники: tech-req разд. 5 (FitFetcher — «по контракту семьи
библиотек garminconnect»), Ф-8.1, vision (SSO-последовательность).
Прототип: против живого Garmin не автоматизируется; тесты —
фейковый HttpMessageHandler с теми же маршрутами.
1. Сигнатуры
public class GarminClient
{
public GarminClient(string login, string password,
string baseUrl, HttpMessageHandler? handler = null);
public void Login(CancellationToken ct = default); // SSO → Bearer
public List<GarminActivity> ListActivities(int limit, CancellationToken ct = default);
public byte[] DownloadFit(long activityId, CancellationToken ct = default);
}
public sealed record GarminActivity(
long ActivityId, DateTime StartTimeLocal, string ActivityType);
2. Маршруты (по контракту garminconnect; {base} = Garmin.BaseUrl)
| Шаг | Запрос | Что берём |
|---|---|---|
| 1 | GET {base}/sso/embed |
cookies (SSO) |
| 2 | GET {base}/sso/signin |
csrf из html (name="_csrf") |
| 3 | POST {base}/sso/signin (form: username, password, embed, csrf) |
ticket из редиректа (?ticket=…); неуспех → GarminAuthException |
| 4 | GET {base}/modern/?ticket=… |
cookies современного домена |
| 5 | POST {base}/sso/api/2.0/oauth/exchange/service/user/2.0 (OAuth1-подпись тестовыми consumer key/secret) |
Bearer access_token |
| 6 | GET {base}/activitylist-service/activities/search/activities?limit=N&start=0 |
JSON список: activityId, startTimeLocal, activityType.typeKey |
| 7 | GET {base}/download-service/files/activity/{id} |
байты .fit |
Все запросы после шага 5 — заголовок Authorization: Bearer ….
Таймаут HttpClient — 30 с. 🛡 пароль и токены в логи не попадают
(исключения — без credential-текста).
3. Тестовый handler
FakeGarminHandler : HttpMessageHandler — маршруты разд. 2 на
{base}; список и байты .fit задаёт тест (FitParser.WriteTestFile);
режим FailLogin — шаг 3 возвращает 401.
4. Ошибки
GarminAuthException— шаги 1–5 (логин/MFA/блокировка); текст содержит шаг и код ответа, не содержит пароль;HttpRequestException/TaskCanceledException— сеть/таймаут (сеть сбоит в тестах подменой handler).