mirror of
https://github.com/sstent/go-garth.git
synced 2026-03-10 14:35:21 +00:00
porting - part 1 and 2 completed and working
This commit is contained in:
@@ -1,21 +0,0 @@
|
||||
# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json # Schema for CodeRabbit configurations
|
||||
language: "en-US"
|
||||
early_access: true
|
||||
reviews:
|
||||
request_changes_workflow: false
|
||||
high_level_summary: true
|
||||
poem: false
|
||||
review_status: true
|
||||
collapse_walkthrough: false
|
||||
auto_review:
|
||||
enabled: true
|
||||
drafts: false
|
||||
path_filters:
|
||||
- "!tests/**/cassettes/**"
|
||||
path_instructions:
|
||||
- path: "tests/**"
|
||||
instructions: |
|
||||
- test functions shouldn't have a return type hint
|
||||
- it's ok to use `assert` instead of `pytest.assume()`
|
||||
chat:
|
||||
auto_reply: true
|
||||
@@ -1,7 +0,0 @@
|
||||
FROM mcr.microsoft.com/devcontainers/anaconda:0-3
|
||||
|
||||
# Copy environment.yml (if found) to a temp location so we update the environment. Also
|
||||
# copy "noop.txt" so the COPY instruction does not fail if no environment.yml exists.
|
||||
COPY environment.yml* .devcontainer/noop.txt /tmp/conda-tmp/
|
||||
RUN if [ -f "/tmp/conda-tmp/environment.yml" ]; then umask 0002 && /opt/conda/bin/conda env update -n base -f /tmp/conda-tmp/environment.yml; fi \
|
||||
&& rm -rf /tmp/conda-tmp
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "Anaconda (Python 3)",
|
||||
"build": {
|
||||
"context": "..",
|
||||
"dockerfile": "Dockerfile"
|
||||
},
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
This file copied into the container along with environment.yml* from the parent
|
||||
folder. This file is included to prevents the Dockerfile COPY instruction from
|
||||
failing if no environment.yml is found.
|
||||
1
garth/.gitattributes
vendored
1
garth/.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
*.ipynb linguist-documentation=true
|
||||
17
garth/.github/dependabot.yml
vendored
17
garth/.github/dependabot.yml
vendored
@@ -1,17 +0,0 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "20:00"
|
||||
timezone: "America/Mexico_City"
|
||||
open-pull-requests-limit: 5
|
||||
|
||||
- package-ecosystem: pip
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "20:00"
|
||||
timezone: "America/Mexico_City"
|
||||
open-pull-requests-limit: 5
|
||||
87
garth/.github/workflows/ci.yml
vendored
87
garth/.github/workflows/ci.yml
vendored
@@ -1,87 +0,0 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
tags:
|
||||
- "**"
|
||||
pull_request: {}
|
||||
|
||||
env:
|
||||
COLUMNS: 150
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
checks: write
|
||||
statuses: write
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
name: lint ${{ matrix.python-version }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- uses: astral-sh/setup-uv@v6
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install --system -e .
|
||||
uv pip install --system --group linting
|
||||
|
||||
- uses: pre-commit/action@v3.0.1
|
||||
with:
|
||||
extra_args: --all-files --verbose
|
||||
env:
|
||||
SKIP: no-commit-to-branch
|
||||
|
||||
test:
|
||||
name: test ${{ matrix.python-version }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu, macos, windows]
|
||||
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
||||
|
||||
env:
|
||||
PYTHON: ${{ matrix.python-version }}
|
||||
OS: ${{ matrix.os }}
|
||||
|
||||
runs-on: ${{ matrix.os }}-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- uses: astral-sh/setup-uv@v6
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
uv pip install --system -e .
|
||||
uv pip install --system --group testing
|
||||
|
||||
- name: test
|
||||
run: make testcov
|
||||
env:
|
||||
CONTEXT: ${{ runner.os }}-py${{ matrix.python-version }}-with-deps
|
||||
|
||||
- name: upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage/coverage.xml
|
||||
flags: unittests
|
||||
name: codecov-umbrella
|
||||
fail_ci_if_error: true
|
||||
30
garth/.github/workflows/publish.yml
vendored
30
garth/.github/workflows/publish.yml
vendored
@@ -1,30 +0,0 @@
|
||||
name: Publish to PyPI
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: pypi
|
||||
url: https://pypi.org/p/garth
|
||||
permissions:
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.13"
|
||||
|
||||
- uses: astral-sh/setup-uv@v6
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
uv build
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
53
garth/.gitignore
vendored
53
garth/.gitignore
vendored
@@ -1,53 +0,0 @@
|
||||
# Virtual environments
|
||||
env/
|
||||
env3*/
|
||||
venv/
|
||||
.venv/
|
||||
.envrc
|
||||
.env
|
||||
__pypackages__/
|
||||
|
||||
# IDEs and editors
|
||||
.idea/
|
||||
|
||||
# Package distribution and build files
|
||||
*.egg-info/
|
||||
dist/
|
||||
/build/
|
||||
_build/
|
||||
|
||||
# Python bytecode and cache files
|
||||
*.py[cod]
|
||||
.cache/
|
||||
/.ghtopdep_cache/
|
||||
.hypothesis
|
||||
.mypy_cache/
|
||||
.pytest_cache/
|
||||
/.ruff_cache/
|
||||
|
||||
# Benchmark and test files
|
||||
/benchmarks/*.json
|
||||
/htmlcov/
|
||||
/codecov.sh
|
||||
/coverage.lcov
|
||||
.coverage
|
||||
test.py
|
||||
/coverage/
|
||||
|
||||
# Documentation files
|
||||
/docs/changelog.md
|
||||
/site/
|
||||
/site.zip
|
||||
|
||||
# Other files and folders
|
||||
.python-version
|
||||
.DS_Store
|
||||
.auto-format
|
||||
/sandbox/
|
||||
/worktrees/
|
||||
.pdm-python
|
||||
tmp/
|
||||
.pdm.toml
|
||||
|
||||
# exclude saved oauth tokens
|
||||
oauth*_token.json
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"MD033": {
|
||||
"allowed_elements": ["img", "a", "source", "picture"]
|
||||
},
|
||||
"MD046": false
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
exclude: '.*\.ipynb$'
|
||||
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
args: ['--unsafe']
|
||||
- id: check-toml
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.6
|
||||
hooks:
|
||||
- id: codespell
|
||||
additional_dependencies:
|
||||
- tomli
|
||||
exclude: 'cassettes/'
|
||||
|
||||
- repo: https://github.com/DavidAnson/markdownlint-cli2
|
||||
rev: v0.12.1
|
||||
hooks:
|
||||
- id: markdownlint-cli2
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: lint
|
||||
name: lint
|
||||
entry: make lint
|
||||
types: [python]
|
||||
language: system
|
||||
pass_filenames: false
|
||||
@@ -1,21 +0,0 @@
|
||||
# MIT License
|
||||
|
||||
Copyright (c) 2023 Matin Tamizi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,81 +0,0 @@
|
||||
# Based on Makefile for pydantic (github.com/pydantic/pydantic/blob/main/Makefile)
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
sources = src tests
|
||||
|
||||
.PHONY: .uv ## Check that uv is installed
|
||||
.uv:
|
||||
@uv --version || echo 'Please install uv: https://docs.astral.sh/uv/getting-started/installation/'
|
||||
|
||||
.PHONY: .pre-commit ## Check that pre-commit is installed
|
||||
.pre-commit:
|
||||
@pre-commit -V || echo 'Please install pre-commit: https://pre-commit.com/'
|
||||
|
||||
.PHONY: install ## Install the package, dependencies, and pre-commit for local development
|
||||
install: .uv .pre-commit
|
||||
uv pip install -e .
|
||||
uv pip install --group dev --group linting --group testing
|
||||
pre-commit install --install-hooks
|
||||
|
||||
.PHONY: sync ## Sync dependencies and lockfiles
|
||||
sync: .uv clean
|
||||
uv pip install -e . --force-reinstall
|
||||
uv sync
|
||||
|
||||
.PHONY: format ## Auto-format python source files
|
||||
format: .uv
|
||||
uv run ruff format $(sources)
|
||||
uv run ruff check --fix $(sources)
|
||||
|
||||
.PHONY: lint ## Lint python source files
|
||||
lint: .uv
|
||||
uv run ruff format --check $(sources)
|
||||
uv run ruff check $(sources)
|
||||
uv run mypy $(sources)
|
||||
|
||||
.PHONY: codespell ## Use Codespell to do spellchecking
|
||||
codespell: .pre-commit
|
||||
pre-commit run codespell --all-files
|
||||
|
||||
.PHONY: test ## Run all tests, skipping the type-checker integration tests
|
||||
test: .uv
|
||||
uv run coverage run -m pytest -v --durations=10
|
||||
|
||||
.PHONY: testcov ## Run tests and generate a coverage report, skipping the type-checker integration tests
|
||||
testcov: test
|
||||
@echo "building coverage html"
|
||||
@uv run coverage html
|
||||
@echo "building coverage xml"
|
||||
@uv run coverage xml -o coverage/coverage.xml
|
||||
|
||||
.PHONY: all ## Run the standard set of checks performed in CI
|
||||
all: lint codespell testcov
|
||||
|
||||
.PHONY: clean ## Clear local caches and build artifacts
|
||||
clean:
|
||||
find . -type d -name __pycache__ -exec rm -r {} +
|
||||
find . -type f -name '*.py[co]' -exec rm -f {} +
|
||||
find . -type f -name '*~' -exec rm -f {} +
|
||||
find . -type f -name '.*~' -exec rm -f {} +
|
||||
rm -rf .cache
|
||||
rm -rf .pytest_cache
|
||||
rm -rf .ruff_cache
|
||||
rm -rf htmlcov
|
||||
rm -rf *.egg-info
|
||||
rm -f .coverage
|
||||
rm -f .coverage.*
|
||||
rm -rf build
|
||||
rm -rf dist
|
||||
rm -rf site
|
||||
rm -rf docs/_build
|
||||
rm -rf docs/.changelog.md docs/.version.md docs/.tmp_schema_mappings.html
|
||||
rm -rf fastapi/test.db
|
||||
rm -rf coverage.xml
|
||||
rm -rf __pypackages__ uv.lock
|
||||
|
||||
.PHONY: help ## Display this message
|
||||
help:
|
||||
@grep -E \
|
||||
'^.PHONY: .*?## .*$$' $(MAKEFILE_LIST) | \
|
||||
sort | \
|
||||
awk 'BEGIN {FS = ".PHONY: |## "}; {printf "\033[36m%-19s\033[0m %s\n", $$2, $$3}'
|
||||
1108
garth/README.md
1108
garth/README.md
File diff suppressed because it is too large
Load Diff
179
garth/client/client.go
Normal file
179
garth/client/client.go
Normal file
@@ -0,0 +1,179 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/cookiejar"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"garmin-connect/garth/sso"
|
||||
"garmin-connect/garth/types"
|
||||
)
|
||||
|
||||
// Client represents the Garmin Connect API client
|
||||
type Client struct {
|
||||
Domain string
|
||||
HTTPClient *http.Client
|
||||
Username string
|
||||
AuthToken string
|
||||
OAuth1Token *types.OAuth1Token
|
||||
OAuth2Token *types.OAuth2Token
|
||||
}
|
||||
|
||||
// NewClient creates a new Garmin Connect client
|
||||
func NewClient(domain string) (*Client, error) {
|
||||
if domain == "" {
|
||||
domain = "garmin.com"
|
||||
}
|
||||
|
||||
jar, err := cookiejar.New(nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create cookie jar: %w", err)
|
||||
}
|
||||
|
||||
return &Client{
|
||||
Domain: domain,
|
||||
HTTPClient: &http.Client{
|
||||
Jar: jar,
|
||||
Timeout: 30 * time.Second,
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
if len(via) >= 10 {
|
||||
return fmt.Errorf("too many redirects")
|
||||
}
|
||||
return nil
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Login authenticates to Garmin Connect using SSO
|
||||
func (c *Client) Login(email, password string) error {
|
||||
ssoClient := sso.NewClient(c.Domain)
|
||||
oauth2Token, err := ssoClient.Login(email, password)
|
||||
if err != nil {
|
||||
return fmt.Errorf("SSO login failed: %w", err)
|
||||
}
|
||||
|
||||
c.OAuth2Token = oauth2Token
|
||||
c.AuthToken = fmt.Sprintf("%s %s", oauth2Token.TokenType, oauth2Token.AccessToken)
|
||||
|
||||
// Get user profile to set username
|
||||
if err := c.GetUserProfile(); err != nil {
|
||||
return fmt.Errorf("failed to get user profile after login: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetUserProfile retrieves the current user's profile
|
||||
func (c *Client) GetUserProfile() error {
|
||||
profileURL := fmt.Sprintf("https://connectapi.%s/userprofile-service/socialProfile", c.Domain)
|
||||
|
||||
req, err := http.NewRequest("GET", profileURL, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create profile request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", c.AuthToken)
|
||||
req.Header.Set("User-Agent", "com.garmin.android.apps.connectmobile")
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get user profile: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return fmt.Errorf("profile request failed with status %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var profile map[string]interface{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&profile); err != nil {
|
||||
return fmt.Errorf("failed to parse profile: %w", err)
|
||||
}
|
||||
|
||||
if username, ok := profile["userName"].(string); ok {
|
||||
c.Username = username
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("username not found in profile response")
|
||||
}
|
||||
|
||||
// GetActivities retrieves recent activities
|
||||
func (c *Client) GetActivities(limit int) ([]types.Activity, error) {
|
||||
if limit <= 0 {
|
||||
limit = 10
|
||||
}
|
||||
|
||||
activitiesURL := fmt.Sprintf("https://connectapi.%s/activitylist-service/activities/search/activities?limit=%d&start=0", c.Domain, limit)
|
||||
|
||||
req, err := http.NewRequest("GET", activitiesURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create activities request: %w", err)
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", c.AuthToken)
|
||||
req.Header.Set("User-Agent", "com.garmin.android.apps.connectmobile")
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get activities: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
return nil, fmt.Errorf("activities request failed with status %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var activities []types.Activity
|
||||
if err := json.NewDecoder(resp.Body).Decode(&activities); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse activities: %w", err)
|
||||
}
|
||||
|
||||
return activities, nil
|
||||
}
|
||||
|
||||
// SaveSession saves the current session to a file
|
||||
func (c *Client) SaveSession(filename string) error {
|
||||
session := types.SessionData{
|
||||
Domain: c.Domain,
|
||||
Username: c.Username,
|
||||
AuthToken: c.AuthToken,
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(session, "", " ")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal session: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filename, data, 0600); err != nil {
|
||||
return fmt.Errorf("failed to write session file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LoadSession loads a session from a file
|
||||
func (c *Client) LoadSession(filename string) error {
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read session file: %w", err)
|
||||
}
|
||||
|
||||
var session types.SessionData
|
||||
if err := json.Unmarshal(data, &session); err != nil {
|
||||
return fmt.Errorf("failed to unmarshal session: %w", err)
|
||||
}
|
||||
|
||||
c.Domain = session.Domain
|
||||
c.Username = session.Username
|
||||
c.AuthToken = session.AuthToken
|
||||
|
||||
return nil
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
32
garth/credentials/credentials.go
Normal file
32
garth/credentials/credentials.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package credentials
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/joho/godotenv"
|
||||
)
|
||||
|
||||
// LoadEnvCredentials loads credentials from .env file
|
||||
func LoadEnvCredentials() (email, password, domain string, err error) {
|
||||
// Load .env file
|
||||
if err := godotenv.Load(); err != nil {
|
||||
return "", "", "", fmt.Errorf("error loading .env file: %w", err)
|
||||
}
|
||||
|
||||
email = os.Getenv("GARMIN_EMAIL")
|
||||
password = os.Getenv("GARMIN_PASSWORD")
|
||||
domain = os.Getenv("GARMIN_DOMAIN")
|
||||
|
||||
if email == "" {
|
||||
return "", "", "", fmt.Errorf("GARMIN_EMAIL not found in .env file")
|
||||
}
|
||||
if password == "" {
|
||||
return "", "", "", fmt.Errorf("GARMIN_PASSWORD not found in .env file")
|
||||
}
|
||||
if domain == "" {
|
||||
domain = "garmin.com" // default value
|
||||
}
|
||||
|
||||
return email, password, domain, nil
|
||||
}
|
||||
69
garth/errors/errors.go
Normal file
69
garth/errors/errors.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package errors
|
||||
|
||||
import "fmt"
|
||||
|
||||
// AuthenticationError represents authentication failures
|
||||
type AuthenticationError struct {
|
||||
Message string
|
||||
Cause error
|
||||
}
|
||||
|
||||
func (e *AuthenticationError) Error() string {
|
||||
if e.Cause != nil {
|
||||
return fmt.Sprintf("authentication error: %s: %v", e.Message, e.Cause)
|
||||
}
|
||||
return fmt.Sprintf("authentication error: %s", e.Message)
|
||||
}
|
||||
|
||||
// OAuthError represents OAuth token-related errors
|
||||
type OAuthError struct {
|
||||
Message string
|
||||
Cause error
|
||||
}
|
||||
|
||||
func (e *OAuthError) Error() string {
|
||||
if e.Cause != nil {
|
||||
return fmt.Sprintf("OAuth error: %s: %v", e.Message, e.Cause)
|
||||
}
|
||||
return fmt.Sprintf("OAuth error: %s", e.Message)
|
||||
}
|
||||
|
||||
// APIError represents errors from API calls
|
||||
type APIError struct {
|
||||
StatusCode int
|
||||
Response string
|
||||
Cause error
|
||||
}
|
||||
|
||||
func (e *APIError) Error() string {
|
||||
if e.Cause != nil {
|
||||
return fmt.Sprintf("API error (status %d): %s: %v", e.StatusCode, e.Response, e.Cause)
|
||||
}
|
||||
return fmt.Sprintf("API error (status %d): %s", e.StatusCode, e.Response)
|
||||
}
|
||||
|
||||
// IOError represents file I/O errors
|
||||
type IOError struct {
|
||||
Message string
|
||||
Cause error
|
||||
}
|
||||
|
||||
func (e *IOError) Error() string {
|
||||
if e.Cause != nil {
|
||||
return fmt.Sprintf("I/O error: %s: %v", e.Message, e.Cause)
|
||||
}
|
||||
return fmt.Sprintf("I/O error: %s", e.Message)
|
||||
}
|
||||
|
||||
// ValidationError represents input validation failures
|
||||
type ValidationError struct {
|
||||
Message string
|
||||
Field string
|
||||
}
|
||||
|
||||
func (e *ValidationError) Error() string {
|
||||
if e.Field != "" {
|
||||
return fmt.Sprintf("validation error for %s: %s", e.Field, e.Message)
|
||||
}
|
||||
return fmt.Sprintf("validation error: %s", e.Message)
|
||||
}
|
||||
152
garth/oauth/oauth.go
Normal file
152
garth/oauth/oauth.go
Normal file
@@ -0,0 +1,152 @@
|
||||
package oauth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"garmin-connect/garth/types"
|
||||
"garmin-connect/garth/utils"
|
||||
)
|
||||
|
||||
// GetOAuth1Token retrieves an OAuth1 token using the provided ticket
|
||||
func GetOAuth1Token(domain, ticket string) (*types.OAuth1Token, error) {
|
||||
consumer, err := utils.LoadOAuthConsumer()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load OAuth consumer: %w", err)
|
||||
}
|
||||
|
||||
baseURL := fmt.Sprintf("https://connectapi.%s/oauth-service/oauth/", domain)
|
||||
loginURL := fmt.Sprintf("https://sso.%s/sso/embed", domain)
|
||||
tokenURL := fmt.Sprintf("%spreauthorized?ticket=%s&login-url=%s&accepts-mfa-tokens=true",
|
||||
baseURL, ticket, url.QueryEscape(loginURL))
|
||||
|
||||
// Parse URL to extract query parameters for signing
|
||||
parsedURL, err := url.Parse(tokenURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Extract query parameters
|
||||
queryParams := make(map[string]string)
|
||||
for key, values := range parsedURL.Query() {
|
||||
if len(values) > 0 {
|
||||
queryParams[key] = values[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Create OAuth1 signed request
|
||||
baseURLForSigning := parsedURL.Scheme + "://" + parsedURL.Host + parsedURL.Path
|
||||
authHeader := utils.CreateOAuth1AuthorizationHeader("GET", baseURLForSigning, queryParams,
|
||||
consumer.ConsumerKey, consumer.ConsumerSecret, "", "")
|
||||
|
||||
req, err := http.NewRequest("GET", tokenURL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("Authorization", authHeader)
|
||||
req.Header.Set("User-Agent", "com.garmin.android.apps.connectmobile")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bodyStr := string(body)
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("OAuth1 request failed with status %d: %s", resp.StatusCode, bodyStr)
|
||||
}
|
||||
|
||||
// Parse query string response - handle both & and ; separators
|
||||
bodyStr = strings.ReplaceAll(bodyStr, ";", "&")
|
||||
values, err := url.ParseQuery(bodyStr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse OAuth1 response: %w", err)
|
||||
}
|
||||
|
||||
oauthToken := values.Get("oauth_token")
|
||||
oauthTokenSecret := values.Get("oauth_token_secret")
|
||||
|
||||
if oauthToken == "" || oauthTokenSecret == "" {
|
||||
return nil, fmt.Errorf("missing oauth_token or oauth_token_secret in response")
|
||||
}
|
||||
|
||||
return &types.OAuth1Token{
|
||||
OAuthToken: oauthToken,
|
||||
OAuthTokenSecret: oauthTokenSecret,
|
||||
MFAToken: values.Get("mfa_token"),
|
||||
Domain: domain,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ExchangeToken exchanges an OAuth1 token for an OAuth2 token
|
||||
func ExchangeToken(oauth1Token *types.OAuth1Token) (*types.OAuth2Token, error) {
|
||||
consumer, err := utils.LoadOAuthConsumer()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to load OAuth consumer: %w", err)
|
||||
}
|
||||
|
||||
exchangeURL := fmt.Sprintf("https://connectapi.%s/oauth-service/oauth/exchange/user/2.0", oauth1Token.Domain)
|
||||
|
||||
// Prepare form data
|
||||
formData := url.Values{}
|
||||
if oauth1Token.MFAToken != "" {
|
||||
formData.Set("mfa_token", oauth1Token.MFAToken)
|
||||
}
|
||||
|
||||
// Convert form data to map for OAuth signing
|
||||
formParams := make(map[string]string)
|
||||
for key, values := range formData {
|
||||
if len(values) > 0 {
|
||||
formParams[key] = values[0]
|
||||
}
|
||||
}
|
||||
|
||||
// Create OAuth1 signed request
|
||||
authHeader := utils.CreateOAuth1AuthorizationHeader("POST", exchangeURL, formParams,
|
||||
consumer.ConsumerKey, consumer.ConsumerSecret, oauth1Token.OAuthToken, oauth1Token.OAuthTokenSecret)
|
||||
|
||||
req, err := http.NewRequest("POST", exchangeURL, strings.NewReader(formData.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req.Header.Set("Authorization", authHeader)
|
||||
req.Header.Set("User-Agent", "com.garmin.android.apps.connectmobile")
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
return nil, fmt.Errorf("OAuth2 exchange failed with status %d: %s", resp.StatusCode, string(body))
|
||||
}
|
||||
|
||||
var oauth2Token types.OAuth2Token
|
||||
if err := json.Unmarshal(body, &oauth2Token); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode OAuth2 token: %w", err)
|
||||
}
|
||||
|
||||
// Set creation time for expiration tracking
|
||||
oauth2Token.CreatedAt = time.Now()
|
||||
|
||||
return &oauth2Token, nil
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
[project]
|
||||
name = "garth"
|
||||
dynamic = ["version"]
|
||||
description = "Garmin SSO auth + Connect client"
|
||||
authors = [
|
||||
{name = "Matin Tamizi", email = "mtamizi@duck.com"},
|
||||
]
|
||||
dependencies = [
|
||||
"requests>=2.0.0,<3.0.0",
|
||||
"pydantic>=1.10.12,<3.0.0",
|
||||
"requests-oauthlib>=1.3.1,<3.0.0",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Operating System :: MacOS :: MacOS X",
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: POSIX :: Linux",
|
||||
"Operating System :: OS Independent",
|
||||
]
|
||||
keywords = ["garmin", "garmin api", "garmin connect", "garmin sso"]
|
||||
|
||||
[project.urls]
|
||||
"Homepage" = "https://github.com/matin/garth"
|
||||
"Repository" = "https://github.com/matin/garth"
|
||||
"Issues" = "https://github.com/matin/garth/issues"
|
||||
"Changelog" = "https://github.com/matin/garth/releases"
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.version]
|
||||
path = "src/garth/version.py"
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "--ignore=__pypackages__ --ignore-glob=*.yaml"
|
||||
|
||||
[tool.mypy]
|
||||
ignore_missing_imports = true
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 79
|
||||
indent-width = 4
|
||||
target-version = "py310"
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = ["E", "F", "I"]
|
||||
ignore = []
|
||||
|
||||
[tool.ruff.format]
|
||||
quote-style = "double"
|
||||
indent-style = "space"
|
||||
skip-magic-trailing-comma = false
|
||||
line-ending = "auto"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"ipython",
|
||||
"ipdb",
|
||||
"ipykernel",
|
||||
"pandas",
|
||||
"matplotlib",
|
||||
]
|
||||
linting = [
|
||||
"ruff",
|
||||
"mypy",
|
||||
"types-requests",
|
||||
]
|
||||
testing = [
|
||||
"coverage",
|
||||
"pytest",
|
||||
"pytest-vcr",
|
||||
]
|
||||
|
||||
[tool.ruff.lint.isort]
|
||||
known-first-party = ["garth"]
|
||||
combine-as-imports = true
|
||||
lines-after-imports = 2
|
||||
|
||||
[project.scripts]
|
||||
garth = "garth.cli:main"
|
||||
@@ -1,59 +0,0 @@
|
||||
from .data import (
|
||||
BodyBatteryData,
|
||||
DailyBodyBatteryStress,
|
||||
HRVData,
|
||||
SleepData,
|
||||
WeightData,
|
||||
)
|
||||
from .http import Client, client
|
||||
from .stats import (
|
||||
DailyHRV,
|
||||
DailyHydration,
|
||||
DailyIntensityMinutes,
|
||||
DailySleep,
|
||||
DailySteps,
|
||||
DailyStress,
|
||||
WeeklyIntensityMinutes,
|
||||
WeeklySteps,
|
||||
WeeklyStress,
|
||||
)
|
||||
from .users import UserProfile, UserSettings
|
||||
from .version import __version__
|
||||
|
||||
|
||||
__all__ = [
|
||||
"BodyBatteryData",
|
||||
"Client",
|
||||
"DailyBodyBatteryStress",
|
||||
"DailyHRV",
|
||||
"DailyHydration",
|
||||
"DailyIntensityMinutes",
|
||||
"DailySleep",
|
||||
"DailySteps",
|
||||
"DailyStress",
|
||||
"HRVData",
|
||||
"SleepData",
|
||||
"WeightData",
|
||||
"UserProfile",
|
||||
"UserSettings",
|
||||
"WeeklyIntensityMinutes",
|
||||
"WeeklySteps",
|
||||
"WeeklyStress",
|
||||
"__version__",
|
||||
"client",
|
||||
"configure",
|
||||
"connectapi",
|
||||
"download",
|
||||
"login",
|
||||
"resume",
|
||||
"save",
|
||||
"upload",
|
||||
]
|
||||
|
||||
configure = client.configure
|
||||
connectapi = client.connectapi
|
||||
download = client.download
|
||||
login = client.login
|
||||
resume = client.load
|
||||
save = client.dump
|
||||
upload = client.upload
|
||||
@@ -1,37 +0,0 @@
|
||||
import time
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class OAuth1Token:
|
||||
oauth_token: str
|
||||
oauth_token_secret: str
|
||||
mfa_token: str | None = None
|
||||
mfa_expiration_timestamp: datetime | None = None
|
||||
domain: str | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class OAuth2Token:
|
||||
scope: str
|
||||
jti: str
|
||||
token_type: str
|
||||
access_token: str
|
||||
refresh_token: str
|
||||
expires_in: int
|
||||
expires_at: int
|
||||
refresh_token_expires_in: int
|
||||
refresh_token_expires_at: int
|
||||
|
||||
@property
|
||||
def expired(self):
|
||||
return self.expires_at < time.time()
|
||||
|
||||
@property
|
||||
def refresh_expired(self):
|
||||
return self.refresh_token_expires_at < time.time()
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.token_type.title()} {self.access_token}"
|
||||
@@ -1,34 +0,0 @@
|
||||
import argparse
|
||||
import getpass
|
||||
|
||||
import garth
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(prog="garth")
|
||||
parser.add_argument(
|
||||
"--domain",
|
||||
"-d",
|
||||
default="garmin.com",
|
||||
help=(
|
||||
"Domain for Garmin Connect (default: garmin.com). "
|
||||
"Use garmin.cn for China."
|
||||
),
|
||||
)
|
||||
subparsers = parser.add_subparsers(dest="command")
|
||||
subparsers.add_parser(
|
||||
"login", help="Authenticate with Garmin Connect and print token"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
garth.configure(domain=args.domain)
|
||||
|
||||
match args.command:
|
||||
case "login":
|
||||
email = input("Email: ")
|
||||
password = getpass.getpass("Password: ")
|
||||
garth.login(email, password)
|
||||
token = garth.client.dumps()
|
||||
print(token)
|
||||
case _:
|
||||
parser.print_help()
|
||||
@@ -1,21 +0,0 @@
|
||||
__all__ = [
|
||||
"BodyBatteryData",
|
||||
"BodyBatteryEvent",
|
||||
"BodyBatteryReading",
|
||||
"DailyBodyBatteryStress",
|
||||
"HRVData",
|
||||
"SleepData",
|
||||
"StressReading",
|
||||
"WeightData",
|
||||
]
|
||||
|
||||
from .body_battery import (
|
||||
BodyBatteryData,
|
||||
BodyBatteryEvent,
|
||||
BodyBatteryReading,
|
||||
DailyBodyBatteryStress,
|
||||
StressReading,
|
||||
)
|
||||
from .hrv import HRVData
|
||||
from .sleep import SleepData
|
||||
from .weight import WeightData
|
||||
@@ -1,47 +0,0 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from datetime import date
|
||||
from itertools import chain
|
||||
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import date_range, format_end_date
|
||||
|
||||
|
||||
MAX_WORKERS = 10
|
||||
|
||||
|
||||
class Data(ABC):
|
||||
@classmethod
|
||||
@abstractmethod
|
||||
def get(
|
||||
cls, day: date | str, *, client: http.Client | None = None
|
||||
) -> Self | list[Self] | None: ...
|
||||
|
||||
@classmethod
|
||||
def list(
|
||||
cls,
|
||||
end: date | str | None = None,
|
||||
days: int = 1,
|
||||
*,
|
||||
client: http.Client | None = None,
|
||||
max_workers: int = MAX_WORKERS,
|
||||
) -> list[Self]:
|
||||
client = client or http.client
|
||||
end = format_end_date(end)
|
||||
|
||||
def fetch_date(date_):
|
||||
if day := cls.get(date_, client=client):
|
||||
return day
|
||||
|
||||
dates = date_range(end, days)
|
||||
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
||||
data = list(executor.map(fetch_date, dates))
|
||||
data = [day for day in data if day is not None]
|
||||
|
||||
return list(
|
||||
chain.from_iterable(
|
||||
day if isinstance(day, list) else [day] for day in data
|
||||
)
|
||||
)
|
||||
@@ -1,11 +0,0 @@
|
||||
__all__ = [
|
||||
"BodyBatteryData",
|
||||
"BodyBatteryEvent",
|
||||
"BodyBatteryReading",
|
||||
"DailyBodyBatteryStress",
|
||||
"StressReading",
|
||||
]
|
||||
|
||||
from .daily_stress import DailyBodyBatteryStress
|
||||
from .events import BodyBatteryData, BodyBatteryEvent
|
||||
from .readings import BodyBatteryReading, StressReading
|
||||
@@ -1,90 +0,0 @@
|
||||
from datetime import date, datetime
|
||||
from functools import cached_property
|
||||
from typing import Any
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from ... import http
|
||||
from ...utils import camel_to_snake_dict, format_end_date
|
||||
from .._base import Data
|
||||
from .readings import (
|
||||
BodyBatteryReading,
|
||||
StressReading,
|
||||
parse_body_battery_readings,
|
||||
parse_stress_readings,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailyBodyBatteryStress(Data):
|
||||
"""Complete daily Body Battery and stress data."""
|
||||
|
||||
user_profile_pk: int
|
||||
calendar_date: date
|
||||
start_timestamp_gmt: datetime
|
||||
end_timestamp_gmt: datetime
|
||||
start_timestamp_local: datetime
|
||||
end_timestamp_local: datetime
|
||||
max_stress_level: int
|
||||
avg_stress_level: int
|
||||
stress_chart_value_offset: int
|
||||
stress_chart_y_axis_origin: int
|
||||
stress_values_array: list[list[int]]
|
||||
body_battery_values_array: list[list[Any]]
|
||||
|
||||
@cached_property
|
||||
def body_battery_readings(self) -> list[BodyBatteryReading]:
|
||||
"""Convert body battery values array to structured readings."""
|
||||
return parse_body_battery_readings(self.body_battery_values_array)
|
||||
|
||||
@property
|
||||
def stress_readings(self) -> list[StressReading]:
|
||||
"""Convert stress values array to structured readings."""
|
||||
return parse_stress_readings(self.stress_values_array)
|
||||
|
||||
@property
|
||||
def current_body_battery(self) -> int | None:
|
||||
"""Get the latest Body Battery level."""
|
||||
readings = self.body_battery_readings
|
||||
return readings[-1].level if readings else None
|
||||
|
||||
@property
|
||||
def max_body_battery(self) -> int | None:
|
||||
"""Get the maximum Body Battery level for the day."""
|
||||
readings = self.body_battery_readings
|
||||
return max(reading.level for reading in readings) if readings else None
|
||||
|
||||
@property
|
||||
def min_body_battery(self) -> int | None:
|
||||
"""Get the minimum Body Battery level for the day."""
|
||||
readings = self.body_battery_readings
|
||||
return min(reading.level for reading in readings) if readings else None
|
||||
|
||||
@property
|
||||
def body_battery_change(self) -> int | None:
|
||||
"""Calculate the Body Battery change for the day."""
|
||||
readings = self.body_battery_readings
|
||||
if not readings or len(readings) < 2:
|
||||
return None
|
||||
return readings[-1].level - readings[0].level
|
||||
|
||||
@classmethod
|
||||
def get(
|
||||
cls,
|
||||
day: date | str | None = None,
|
||||
*,
|
||||
client: http.Client | None = None,
|
||||
) -> Self | None:
|
||||
"""Get complete Body Battery and stress data for a specific date."""
|
||||
client = client or http.client
|
||||
date_str = format_end_date(day)
|
||||
|
||||
path = f"/wellness-service/wellness/dailyStress/{date_str}"
|
||||
response = client.connectapi(path)
|
||||
|
||||
if not isinstance(response, dict):
|
||||
return None
|
||||
|
||||
snake_response = camel_to_snake_dict(response)
|
||||
return cls(**snake_response)
|
||||
@@ -1,227 +0,0 @@
|
||||
import logging
|
||||
from datetime import date, datetime
|
||||
from typing import Any
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from ... import http
|
||||
from ...utils import format_end_date
|
||||
from .._base import Data
|
||||
from .readings import BodyBatteryReading, parse_body_battery_readings
|
||||
|
||||
|
||||
MAX_WORKERS = 10
|
||||
|
||||
|
||||
@dataclass
|
||||
class BodyBatteryEvent:
|
||||
"""Body Battery event data."""
|
||||
|
||||
event_type: str
|
||||
event_start_time_gmt: datetime
|
||||
timezone_offset: int
|
||||
duration_in_milliseconds: int
|
||||
body_battery_impact: int
|
||||
feedback_type: str
|
||||
short_feedback: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class BodyBatteryData(Data):
|
||||
"""Legacy Body Battery events data (sleep events only)."""
|
||||
|
||||
event: BodyBatteryEvent | None = None
|
||||
activity_name: str | None = None
|
||||
activity_type: str | None = None
|
||||
activity_id: str | None = None
|
||||
average_stress: float | None = None
|
||||
stress_values_array: list[list[int]] | None = None
|
||||
body_battery_values_array: list[list[Any]] | None = None
|
||||
|
||||
@property
|
||||
def body_battery_readings(self) -> list[BodyBatteryReading]:
|
||||
"""Convert body battery values array to structured readings."""
|
||||
return parse_body_battery_readings(self.body_battery_values_array)
|
||||
|
||||
@property
|
||||
def current_level(self) -> int | None:
|
||||
"""Get the latest Body Battery level."""
|
||||
readings = self.body_battery_readings
|
||||
return readings[-1].level if readings else None
|
||||
|
||||
@property
|
||||
def max_level(self) -> int | None:
|
||||
"""Get the maximum Body Battery level for the day."""
|
||||
readings = self.body_battery_readings
|
||||
return max(reading.level for reading in readings) if readings else None
|
||||
|
||||
@property
|
||||
def min_level(self) -> int | None:
|
||||
"""Get the minimum Body Battery level for the day."""
|
||||
readings = self.body_battery_readings
|
||||
return min(reading.level for reading in readings) if readings else None
|
||||
|
||||
@classmethod
|
||||
def get(
|
||||
cls,
|
||||
date_str: str | date | None = None,
|
||||
*,
|
||||
client: http.Client | None = None,
|
||||
) -> list[Self]:
|
||||
"""Get Body Battery events for a specific date."""
|
||||
client = client or http.client
|
||||
date_str = format_end_date(date_str)
|
||||
|
||||
path = f"/wellness-service/wellness/bodyBattery/events/{date_str}"
|
||||
try:
|
||||
response = client.connectapi(path)
|
||||
except Exception as e:
|
||||
logging.warning(f"Failed to fetch Body Battery events: {e}")
|
||||
return []
|
||||
|
||||
if not isinstance(response, list):
|
||||
return []
|
||||
|
||||
events = []
|
||||
for item in response:
|
||||
try:
|
||||
# Parse event data with validation
|
||||
event_data = item.get("event")
|
||||
|
||||
# Validate event_data exists before accessing properties
|
||||
if event_data is None:
|
||||
logging.warning(f"Missing event data in item: {item}")
|
||||
event = None
|
||||
else:
|
||||
# Validate and parse datetime with explicit error handling
|
||||
event_start_time_str = event_data.get("eventStartTimeGmt")
|
||||
if not event_start_time_str:
|
||||
logging.error(
|
||||
f"Missing eventStartTimeGmt in event data: "
|
||||
f"{event_data}"
|
||||
)
|
||||
raise ValueError(
|
||||
"eventStartTimeGmt is required but missing"
|
||||
)
|
||||
|
||||
try:
|
||||
event_start_time_gmt = datetime.fromisoformat(
|
||||
event_start_time_str.replace("Z", "+00:00")
|
||||
)
|
||||
except (ValueError, AttributeError) as e:
|
||||
logging.error(
|
||||
f"Invalid datetime format "
|
||||
f"'{event_start_time_str}': {e}"
|
||||
)
|
||||
raise ValueError(
|
||||
f"Invalid eventStartTimeGmt format: "
|
||||
f"{event_start_time_str}"
|
||||
) from e
|
||||
|
||||
# Validate numeric fields
|
||||
timezone_offset = event_data.get("timezoneOffset", 0)
|
||||
if not isinstance(timezone_offset, (int, float)):
|
||||
logging.warning(
|
||||
f"Invalid timezone_offset type: "
|
||||
f"{type(timezone_offset)}, using 0"
|
||||
)
|
||||
timezone_offset = 0
|
||||
|
||||
duration_ms = event_data.get("durationInMilliseconds", 0)
|
||||
if not isinstance(duration_ms, (int, float)):
|
||||
logging.warning(
|
||||
f"Invalid durationInMilliseconds type: "
|
||||
f"{type(duration_ms)}, using 0"
|
||||
)
|
||||
duration_ms = 0
|
||||
|
||||
battery_impact = event_data.get("bodyBatteryImpact", 0)
|
||||
if not isinstance(battery_impact, (int, float)):
|
||||
logging.warning(
|
||||
f"Invalid bodyBatteryImpact type: "
|
||||
f"{type(battery_impact)}, using 0"
|
||||
)
|
||||
battery_impact = 0
|
||||
|
||||
event = BodyBatteryEvent(
|
||||
event_type=event_data.get("eventType", ""),
|
||||
event_start_time_gmt=event_start_time_gmt,
|
||||
timezone_offset=int(timezone_offset),
|
||||
duration_in_milliseconds=int(duration_ms),
|
||||
body_battery_impact=int(battery_impact),
|
||||
feedback_type=event_data.get("feedbackType", ""),
|
||||
short_feedback=event_data.get("shortFeedback", ""),
|
||||
)
|
||||
|
||||
# Validate data arrays
|
||||
stress_values = item.get("stressValuesArray")
|
||||
if stress_values is not None and not isinstance(
|
||||
stress_values, list
|
||||
):
|
||||
logging.warning(
|
||||
f"Invalid stressValuesArray type: "
|
||||
f"{type(stress_values)}, using None"
|
||||
)
|
||||
stress_values = None
|
||||
|
||||
battery_values = item.get("bodyBatteryValuesArray")
|
||||
if battery_values is not None and not isinstance(
|
||||
battery_values, list
|
||||
):
|
||||
logging.warning(
|
||||
f"Invalid bodyBatteryValuesArray type: "
|
||||
f"{type(battery_values)}, using None"
|
||||
)
|
||||
battery_values = None
|
||||
|
||||
# Validate average_stress
|
||||
avg_stress = item.get("averageStress")
|
||||
if avg_stress is not None and not isinstance(
|
||||
avg_stress, (int, float)
|
||||
):
|
||||
logging.warning(
|
||||
f"Invalid averageStress type: "
|
||||
f"{type(avg_stress)}, using None"
|
||||
)
|
||||
avg_stress = None
|
||||
|
||||
events.append(
|
||||
cls(
|
||||
event=event,
|
||||
activity_name=item.get("activityName"),
|
||||
activity_type=item.get("activityType"),
|
||||
activity_id=item.get("activityId"),
|
||||
average_stress=avg_stress,
|
||||
stress_values_array=stress_values,
|
||||
body_battery_values_array=battery_values,
|
||||
)
|
||||
)
|
||||
|
||||
except ValueError as e:
|
||||
# Re-raise validation errors with context
|
||||
logging.error(
|
||||
f"Data validation error for Body Battery event item "
|
||||
f"{item}: {e}"
|
||||
)
|
||||
continue
|
||||
except Exception as e:
|
||||
# Log unexpected errors with full context
|
||||
logging.error(
|
||||
f"Unexpected error parsing Body Battery event item "
|
||||
f"{item}: {e}",
|
||||
exc_info=True,
|
||||
)
|
||||
continue
|
||||
|
||||
# Log summary of data quality issues
|
||||
total_items = len(response)
|
||||
parsed_events = len(events)
|
||||
if parsed_events < total_items:
|
||||
skipped = total_items - parsed_events
|
||||
logging.info(
|
||||
f"Body Battery events parsing: {parsed_events}/{total_items} "
|
||||
f"successful, {skipped} skipped due to data issues"
|
||||
)
|
||||
|
||||
return events
|
||||
@@ -1,56 +0,0 @@
|
||||
from typing import Any
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class BodyBatteryReading:
|
||||
"""Individual Body Battery reading."""
|
||||
|
||||
timestamp: int
|
||||
status: str
|
||||
level: int
|
||||
version: float
|
||||
|
||||
|
||||
@dataclass
|
||||
class StressReading:
|
||||
"""Individual stress reading."""
|
||||
|
||||
timestamp: int
|
||||
stress_level: int
|
||||
|
||||
|
||||
def parse_body_battery_readings(
|
||||
body_battery_values_array: list[list[Any]] | None,
|
||||
) -> list[BodyBatteryReading]:
|
||||
"""Convert body battery values array to structured readings."""
|
||||
readings = []
|
||||
for values in body_battery_values_array or []:
|
||||
# Each reading requires 4 values: timestamp, status, level, version
|
||||
if len(values) >= 4:
|
||||
readings.append(
|
||||
BodyBatteryReading(
|
||||
timestamp=values[0],
|
||||
status=values[1],
|
||||
level=values[2],
|
||||
version=values[3],
|
||||
)
|
||||
)
|
||||
# Sort readings by timestamp to ensure chronological order
|
||||
return sorted(readings, key=lambda reading: reading.timestamp)
|
||||
|
||||
|
||||
def parse_stress_readings(
|
||||
stress_values_array: list[list[int]] | None,
|
||||
) -> list[StressReading]:
|
||||
"""Convert stress values array to structured readings."""
|
||||
readings = []
|
||||
for values in stress_values_array or []:
|
||||
# Each reading requires 2 values: timestamp, stress_level
|
||||
if len(values) >= 2:
|
||||
readings.append(
|
||||
StressReading(timestamp=values[0], stress_level=values[1])
|
||||
)
|
||||
# Sort readings by timestamp to ensure chronological order
|
||||
return sorted(readings, key=lambda reading: reading.timestamp)
|
||||
@@ -1,68 +0,0 @@
|
||||
from datetime import date, datetime
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import camel_to_snake_dict
|
||||
from ._base import Data
|
||||
|
||||
|
||||
@dataclass
|
||||
class Baseline:
|
||||
low_upper: int
|
||||
balanced_low: int
|
||||
balanced_upper: int
|
||||
marker_value: float
|
||||
|
||||
|
||||
@dataclass
|
||||
class HRVSummary:
|
||||
calendar_date: date
|
||||
weekly_avg: int
|
||||
last_night_avg: int | None
|
||||
last_night_5_min_high: int
|
||||
baseline: Baseline
|
||||
status: str
|
||||
feedback_phrase: str
|
||||
create_time_stamp: datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class HRVReading:
|
||||
hrv_value: int
|
||||
reading_time_gmt: datetime
|
||||
reading_time_local: datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class HRVData(Data):
|
||||
user_profile_pk: int
|
||||
hrv_summary: HRVSummary
|
||||
hrv_readings: list[HRVReading]
|
||||
start_timestamp_gmt: datetime
|
||||
end_timestamp_gmt: datetime
|
||||
start_timestamp_local: datetime
|
||||
end_timestamp_local: datetime
|
||||
sleep_start_timestamp_gmt: datetime
|
||||
sleep_end_timestamp_gmt: datetime
|
||||
sleep_start_timestamp_local: datetime
|
||||
sleep_end_timestamp_local: datetime
|
||||
|
||||
@classmethod
|
||||
def get(
|
||||
cls, day: date | str, *, client: http.Client | None = None
|
||||
) -> Self | None:
|
||||
client = client or http.client
|
||||
path = f"/hrv-service/hrv/{day}"
|
||||
hrv_data = client.connectapi(path)
|
||||
if not hrv_data:
|
||||
return None
|
||||
hrv_data = camel_to_snake_dict(hrv_data)
|
||||
assert isinstance(hrv_data, dict)
|
||||
return cls(**hrv_data)
|
||||
|
||||
@classmethod
|
||||
def list(cls, *args, **kwargs) -> list[Self]:
|
||||
data = super().list(*args, **kwargs)
|
||||
return sorted(data, key=lambda d: d.hrv_summary.calendar_date)
|
||||
@@ -1,123 +0,0 @@
|
||||
from datetime import date, datetime
|
||||
from typing import Optional, Union
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import camel_to_snake_dict, get_localized_datetime
|
||||
from ._base import Data
|
||||
|
||||
|
||||
@dataclass
|
||||
class Score:
|
||||
qualifier_key: str
|
||||
optimal_start: Optional[float] = None
|
||||
optimal_end: Optional[float] = None
|
||||
value: Optional[int] = None
|
||||
ideal_start_in_seconds: Optional[float] = None
|
||||
ideal_end_in_seconds: Optional[float] = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class SleepScores:
|
||||
total_duration: Score
|
||||
stress: Score
|
||||
awake_count: Score
|
||||
overall: Score
|
||||
rem_percentage: Score
|
||||
restlessness: Score
|
||||
light_percentage: Score
|
||||
deep_percentage: Score
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailySleepDTO:
|
||||
id: int
|
||||
user_profile_pk: int
|
||||
calendar_date: date
|
||||
sleep_time_seconds: int
|
||||
nap_time_seconds: int
|
||||
sleep_window_confirmed: bool
|
||||
sleep_window_confirmation_type: str
|
||||
sleep_start_timestamp_gmt: int
|
||||
sleep_end_timestamp_gmt: int
|
||||
sleep_start_timestamp_local: int
|
||||
sleep_end_timestamp_local: int
|
||||
device_rem_capable: bool
|
||||
retro: bool
|
||||
unmeasurable_sleep_seconds: Optional[int] = None
|
||||
deep_sleep_seconds: Optional[int] = None
|
||||
light_sleep_seconds: Optional[int] = None
|
||||
rem_sleep_seconds: Optional[int] = None
|
||||
awake_sleep_seconds: Optional[int] = None
|
||||
sleep_from_device: Optional[bool] = None
|
||||
sleep_version: Optional[int] = None
|
||||
awake_count: Optional[int] = None
|
||||
sleep_scores: Optional[SleepScores] = None
|
||||
auto_sleep_start_timestamp_gmt: Optional[int] = None
|
||||
auto_sleep_end_timestamp_gmt: Optional[int] = None
|
||||
sleep_quality_type_pk: Optional[int] = None
|
||||
sleep_result_type_pk: Optional[int] = None
|
||||
average_sp_o2_value: Optional[float] = None
|
||||
lowest_sp_o2_value: Optional[int] = None
|
||||
highest_sp_o2_value: Optional[int] = None
|
||||
average_sp_o2_hr_sleep: Optional[float] = None
|
||||
average_respiration_value: Optional[float] = None
|
||||
lowest_respiration_value: Optional[float] = None
|
||||
highest_respiration_value: Optional[float] = None
|
||||
avg_sleep_stress: Optional[float] = None
|
||||
age_group: Optional[str] = None
|
||||
sleep_score_feedback: Optional[str] = None
|
||||
sleep_score_insight: Optional[str] = None
|
||||
|
||||
@property
|
||||
def sleep_start(self) -> datetime:
|
||||
return get_localized_datetime(
|
||||
self.sleep_start_timestamp_gmt, self.sleep_start_timestamp_local
|
||||
)
|
||||
|
||||
@property
|
||||
def sleep_end(self) -> datetime:
|
||||
return get_localized_datetime(
|
||||
self.sleep_end_timestamp_gmt, self.sleep_end_timestamp_local
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class SleepMovement:
|
||||
start_gmt: datetime
|
||||
end_gmt: datetime
|
||||
activity_level: float
|
||||
|
||||
|
||||
@dataclass
|
||||
class SleepData(Data):
|
||||
daily_sleep_dto: DailySleepDTO
|
||||
sleep_movement: Optional[list[SleepMovement]] = None
|
||||
|
||||
@classmethod
|
||||
def get(
|
||||
cls,
|
||||
day: Union[date, str],
|
||||
*,
|
||||
buffer_minutes: int = 60,
|
||||
client: Optional[http.Client] = None,
|
||||
) -> Optional[Self]:
|
||||
client = client or http.client
|
||||
path = (
|
||||
f"/wellness-service/wellness/dailySleepData/{client.username}?"
|
||||
f"nonSleepBufferMinutes={buffer_minutes}&date={day}"
|
||||
)
|
||||
sleep_data = client.connectapi(path)
|
||||
assert sleep_data
|
||||
sleep_data = camel_to_snake_dict(sleep_data)
|
||||
assert isinstance(sleep_data, dict)
|
||||
return (
|
||||
cls(**sleep_data) if sleep_data["daily_sleep_dto"]["id"] else None
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def list(cls, *args, **kwargs) -> list[Self]:
|
||||
data = super().list(*args, **kwargs)
|
||||
return sorted(data, key=lambda x: x.daily_sleep_dto.calendar_date)
|
||||
@@ -1,81 +0,0 @@
|
||||
from datetime import date, datetime, timedelta
|
||||
from itertools import chain
|
||||
|
||||
from pydantic import Field, ValidationInfo, field_validator
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import (
|
||||
camel_to_snake_dict,
|
||||
format_end_date,
|
||||
get_localized_datetime,
|
||||
)
|
||||
from ._base import MAX_WORKERS, Data
|
||||
|
||||
|
||||
@dataclass
|
||||
class WeightData(Data):
|
||||
sample_pk: int
|
||||
calendar_date: date
|
||||
weight: int
|
||||
source_type: str
|
||||
weight_delta: float
|
||||
timestamp_gmt: int
|
||||
datetime_utc: datetime = Field(..., alias="timestamp_gmt")
|
||||
datetime_local: datetime = Field(..., alias="date")
|
||||
bmi: float | None = None
|
||||
body_fat: float | None = None
|
||||
body_water: float | None = None
|
||||
bone_mass: int | None = None
|
||||
muscle_mass: int | None = None
|
||||
physique_rating: float | None = None
|
||||
visceral_fat: float | None = None
|
||||
metabolic_age: int | None = None
|
||||
|
||||
@field_validator("datetime_local", mode="before")
|
||||
@classmethod
|
||||
def to_localized_datetime(cls, v: int, info: ValidationInfo) -> datetime:
|
||||
return get_localized_datetime(info.data["timestamp_gmt"], v)
|
||||
|
||||
@classmethod
|
||||
def get(
|
||||
cls, day: date | str, *, client: http.Client | None = None
|
||||
) -> Self | None:
|
||||
client = client or http.client
|
||||
path = f"/weight-service/weight/dayview/{day}"
|
||||
data = client.connectapi(path)
|
||||
day_weight_list = data["dateWeightList"] if data else []
|
||||
|
||||
if not day_weight_list:
|
||||
return None
|
||||
|
||||
# Get first (most recent) weight entry for the day
|
||||
weight_data = camel_to_snake_dict(day_weight_list[0])
|
||||
return cls(**weight_data)
|
||||
|
||||
@classmethod
|
||||
def list(
|
||||
cls,
|
||||
end: date | str | None = None,
|
||||
days: int = 1,
|
||||
*,
|
||||
client: http.Client | None = None,
|
||||
max_workers: int = MAX_WORKERS,
|
||||
) -> list[Self]:
|
||||
client = client or http.client
|
||||
end = format_end_date(end)
|
||||
start = end - timedelta(days=days - 1)
|
||||
|
||||
data = client.connectapi(
|
||||
f"/weight-service/weight/range/{start}/{end}?includeAll=true"
|
||||
)
|
||||
weight_summaries = data["dailyWeightSummaries"] if data else []
|
||||
weight_metrics = chain.from_iterable(
|
||||
summary["allWeightMetrics"] for summary in weight_summaries
|
||||
)
|
||||
weight_data_list = (
|
||||
cls(**camel_to_snake_dict(weight_data))
|
||||
for weight_data in weight_metrics
|
||||
)
|
||||
return sorted(weight_data_list, key=lambda d: d.datetime_utc)
|
||||
@@ -1,18 +0,0 @@
|
||||
from dataclasses import dataclass
|
||||
|
||||
from requests import HTTPError
|
||||
|
||||
|
||||
@dataclass
|
||||
class GarthException(Exception):
|
||||
"""Base exception for all garth exceptions."""
|
||||
|
||||
msg: str
|
||||
|
||||
|
||||
@dataclass
|
||||
class GarthHTTPError(GarthException):
|
||||
error: HTTPError
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.msg}: {self.error}"
|
||||
@@ -1,247 +0,0 @@
|
||||
import base64
|
||||
import json
|
||||
import os
|
||||
from typing import IO, Any, Dict, Literal, Tuple
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from requests import HTTPError, Response, Session
|
||||
from requests.adapters import HTTPAdapter, Retry
|
||||
|
||||
from . import sso
|
||||
from .auth_tokens import OAuth1Token, OAuth2Token
|
||||
from .exc import GarthHTTPError
|
||||
from .utils import asdict
|
||||
|
||||
|
||||
USER_AGENT = {"User-Agent": "GCM-iOS-5.7.2.1"}
|
||||
|
||||
|
||||
class Client:
|
||||
sess: Session
|
||||
last_resp: Response
|
||||
domain: str = "garmin.com"
|
||||
oauth1_token: OAuth1Token | Literal["needs_mfa"] | None = None
|
||||
oauth2_token: OAuth2Token | dict[str, Any] | None = None
|
||||
timeout: int = 10
|
||||
retries: int = 3
|
||||
status_forcelist: Tuple[int, ...] = (408, 429, 500, 502, 503, 504)
|
||||
backoff_factor: float = 0.5
|
||||
pool_connections: int = 10
|
||||
pool_maxsize: int = 10
|
||||
_user_profile: Dict[str, Any] | None = None
|
||||
|
||||
def __init__(self, session: Session | None = None, **kwargs):
|
||||
self.sess = session if session else Session()
|
||||
self.sess.headers.update(USER_AGENT)
|
||||
self.configure(
|
||||
timeout=self.timeout,
|
||||
retries=self.retries,
|
||||
status_forcelist=self.status_forcelist,
|
||||
backoff_factor=self.backoff_factor,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def configure(
|
||||
self,
|
||||
/,
|
||||
oauth1_token: OAuth1Token | None = None,
|
||||
oauth2_token: OAuth2Token | None = None,
|
||||
domain: str | None = None,
|
||||
proxies: Dict[str, str] | None = None,
|
||||
ssl_verify: bool | None = None,
|
||||
timeout: int | None = None,
|
||||
retries: int | None = None,
|
||||
status_forcelist: Tuple[int, ...] | None = None,
|
||||
backoff_factor: float | None = None,
|
||||
pool_connections: int | None = None,
|
||||
pool_maxsize: int | None = None,
|
||||
):
|
||||
if oauth1_token is not None:
|
||||
self.oauth1_token = oauth1_token
|
||||
if oauth2_token is not None:
|
||||
self.oauth2_token = oauth2_token
|
||||
if domain:
|
||||
self.domain = domain
|
||||
if proxies is not None:
|
||||
self.sess.proxies.update(proxies)
|
||||
if ssl_verify is not None:
|
||||
self.sess.verify = ssl_verify
|
||||
if timeout is not None:
|
||||
self.timeout = timeout
|
||||
if retries is not None:
|
||||
self.retries = retries
|
||||
if status_forcelist is not None:
|
||||
self.status_forcelist = status_forcelist
|
||||
if backoff_factor is not None:
|
||||
self.backoff_factor = backoff_factor
|
||||
if pool_connections is not None:
|
||||
self.pool_connections = pool_connections
|
||||
if pool_maxsize is not None:
|
||||
self.pool_maxsize = pool_maxsize
|
||||
|
||||
retry = Retry(
|
||||
total=self.retries,
|
||||
status_forcelist=self.status_forcelist,
|
||||
backoff_factor=self.backoff_factor,
|
||||
)
|
||||
adapter = HTTPAdapter(
|
||||
max_retries=retry,
|
||||
pool_connections=self.pool_connections,
|
||||
pool_maxsize=self.pool_maxsize,
|
||||
)
|
||||
self.sess.mount("https://", adapter)
|
||||
|
||||
@property
|
||||
def user_profile(self):
|
||||
if not self._user_profile:
|
||||
self._user_profile = self.connectapi(
|
||||
"/userprofile-service/socialProfile"
|
||||
)
|
||||
assert isinstance(self._user_profile, dict), (
|
||||
"No profile from connectapi"
|
||||
)
|
||||
return self._user_profile
|
||||
|
||||
@property
|
||||
def profile(self):
|
||||
return self.user_profile
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self.user_profile["userName"]
|
||||
|
||||
def request(
|
||||
self,
|
||||
method: str,
|
||||
subdomain: str,
|
||||
path: str,
|
||||
/,
|
||||
api: bool = False,
|
||||
referrer: str | bool = False,
|
||||
headers: dict = {},
|
||||
**kwargs,
|
||||
) -> Response:
|
||||
url = f"https://{subdomain}.{self.domain}"
|
||||
url = urljoin(url, path)
|
||||
if referrer is True and self.last_resp:
|
||||
headers["referer"] = self.last_resp.url
|
||||
if api:
|
||||
assert self.oauth1_token, (
|
||||
"OAuth1 token is required for API requests"
|
||||
)
|
||||
if (
|
||||
not isinstance(self.oauth2_token, OAuth2Token)
|
||||
or self.oauth2_token.expired
|
||||
):
|
||||
self.refresh_oauth2()
|
||||
headers["Authorization"] = str(self.oauth2_token)
|
||||
self.last_resp = self.sess.request(
|
||||
method,
|
||||
url,
|
||||
headers=headers,
|
||||
timeout=self.timeout,
|
||||
**kwargs,
|
||||
)
|
||||
try:
|
||||
self.last_resp.raise_for_status()
|
||||
except HTTPError as e:
|
||||
raise GarthHTTPError(
|
||||
msg="Error in request",
|
||||
error=e,
|
||||
)
|
||||
return self.last_resp
|
||||
|
||||
def get(self, *args, **kwargs) -> Response:
|
||||
return self.request("GET", *args, **kwargs)
|
||||
|
||||
def post(self, *args, **kwargs) -> Response:
|
||||
return self.request("POST", *args, **kwargs)
|
||||
|
||||
def delete(self, *args, **kwargs) -> Response:
|
||||
return self.request("DELETE", *args, **kwargs)
|
||||
|
||||
def put(self, *args, **kwargs) -> Response:
|
||||
return self.request("PUT", *args, **kwargs)
|
||||
|
||||
def login(self, *args, **kwargs):
|
||||
self.oauth1_token, self.oauth2_token = sso.login(
|
||||
*args, **kwargs, client=self
|
||||
)
|
||||
return self.oauth1_token, self.oauth2_token
|
||||
|
||||
def resume_login(self, *args, **kwargs):
|
||||
self.oauth1_token, self.oauth2_token = sso.resume_login(
|
||||
*args, **kwargs
|
||||
)
|
||||
return self.oauth1_token, self.oauth2_token
|
||||
|
||||
def refresh_oauth2(self):
|
||||
assert self.oauth1_token and isinstance(
|
||||
self.oauth1_token, OAuth1Token
|
||||
), "OAuth1 token is required for OAuth2 refresh"
|
||||
# There is a way to perform a refresh of an OAuth2 token, but it
|
||||
# appears even Garmin uses this approach when the OAuth2 is expired
|
||||
self.oauth2_token = sso.exchange(self.oauth1_token, self)
|
||||
|
||||
def connectapi(
|
||||
self, path: str, method="GET", **kwargs
|
||||
) -> Dict[str, Any] | None:
|
||||
resp = self.request(method, "connectapi", path, api=True, **kwargs)
|
||||
if resp.status_code == 204:
|
||||
return None
|
||||
return resp.json()
|
||||
|
||||
def download(self, path: str, **kwargs) -> bytes:
|
||||
resp = self.get("connectapi", path, api=True, **kwargs)
|
||||
return resp.content
|
||||
|
||||
def upload(
|
||||
self, fp: IO[bytes], /, path: str = "/upload-service/upload"
|
||||
) -> Dict[str, Any]:
|
||||
fname = os.path.basename(fp.name)
|
||||
files = {"file": (fname, fp)}
|
||||
result = self.connectapi(
|
||||
path,
|
||||
method="POST",
|
||||
files=files,
|
||||
)
|
||||
assert result is not None, "No result from upload"
|
||||
return result
|
||||
|
||||
def dump(self, dir_path: str):
|
||||
dir_path = os.path.expanduser(dir_path)
|
||||
os.makedirs(dir_path, exist_ok=True)
|
||||
with open(os.path.join(dir_path, "oauth1_token.json"), "w") as f:
|
||||
if self.oauth1_token:
|
||||
json.dump(asdict(self.oauth1_token), f, indent=4)
|
||||
with open(os.path.join(dir_path, "oauth2_token.json"), "w") as f:
|
||||
if self.oauth2_token:
|
||||
json.dump(asdict(self.oauth2_token), f, indent=4)
|
||||
|
||||
def dumps(self) -> str:
|
||||
r = []
|
||||
r.append(asdict(self.oauth1_token))
|
||||
r.append(asdict(self.oauth2_token))
|
||||
s = json.dumps(r)
|
||||
return base64.b64encode(s.encode()).decode()
|
||||
|
||||
def load(self, dir_path: str):
|
||||
dir_path = os.path.expanduser(dir_path)
|
||||
with open(os.path.join(dir_path, "oauth1_token.json")) as f:
|
||||
oauth1 = OAuth1Token(**json.load(f))
|
||||
with open(os.path.join(dir_path, "oauth2_token.json")) as f:
|
||||
oauth2 = OAuth2Token(**json.load(f))
|
||||
self.configure(
|
||||
oauth1_token=oauth1, oauth2_token=oauth2, domain=oauth1.domain
|
||||
)
|
||||
|
||||
def loads(self, s: str):
|
||||
oauth1, oauth2 = json.loads(base64.b64decode(s))
|
||||
self.configure(
|
||||
oauth1_token=OAuth1Token(**oauth1),
|
||||
oauth2_token=OAuth2Token(**oauth2),
|
||||
domain=oauth1.get("domain"),
|
||||
)
|
||||
|
||||
|
||||
client = Client()
|
||||
@@ -1,259 +0,0 @@
|
||||
import asyncio
|
||||
import re
|
||||
import time
|
||||
from typing import Any, Callable, Dict, Literal, Tuple
|
||||
from urllib.parse import parse_qs
|
||||
|
||||
import requests
|
||||
from requests import Session
|
||||
from requests_oauthlib import OAuth1Session
|
||||
|
||||
from . import http
|
||||
from .auth_tokens import OAuth1Token, OAuth2Token
|
||||
from .exc import GarthException
|
||||
|
||||
|
||||
CSRF_RE = re.compile(r'name="_csrf"\s+value="(.+?)"')
|
||||
TITLE_RE = re.compile(r"<title>(.+?)</title>")
|
||||
OAUTH_CONSUMER_URL = "https://thegarth.s3.amazonaws.com/oauth_consumer.json"
|
||||
OAUTH_CONSUMER: Dict[str, str] = {}
|
||||
USER_AGENT = {"User-Agent": "com.garmin.android.apps.connectmobile"}
|
||||
|
||||
|
||||
class GarminOAuth1Session(OAuth1Session):
|
||||
def __init__(
|
||||
self,
|
||||
/,
|
||||
parent: Session | None = None,
|
||||
**kwargs,
|
||||
):
|
||||
global OAUTH_CONSUMER
|
||||
if not OAUTH_CONSUMER:
|
||||
OAUTH_CONSUMER = requests.get(OAUTH_CONSUMER_URL).json()
|
||||
super().__init__(
|
||||
OAUTH_CONSUMER["consumer_key"],
|
||||
OAUTH_CONSUMER["consumer_secret"],
|
||||
**kwargs,
|
||||
)
|
||||
if parent is not None:
|
||||
self.mount("https://", parent.adapters["https://"])
|
||||
self.proxies = parent.proxies
|
||||
self.verify = parent.verify
|
||||
|
||||
|
||||
def login(
|
||||
email: str,
|
||||
password: str,
|
||||
/,
|
||||
client: "http.Client | None" = None,
|
||||
prompt_mfa: Callable | None = lambda: input("MFA code: "),
|
||||
return_on_mfa: bool = False,
|
||||
) -> (
|
||||
Tuple[OAuth1Token, OAuth2Token]
|
||||
| Tuple[Literal["needs_mfa"], dict[str, Any]]
|
||||
):
|
||||
"""Login to Garmin Connect.
|
||||
|
||||
Args:
|
||||
email: Garmin account email
|
||||
password: Garmin account password
|
||||
client: Optional HTTP client to use
|
||||
prompt_mfa: Callable that prompts for MFA code. Returns on MFA if None.
|
||||
return_on_mfa: If True, returns dict with MFA info instead of prompting
|
||||
|
||||
Returns:
|
||||
If return_on_mfa=False (default):
|
||||
Tuple[OAuth1Token, OAuth2Token]: OAuth tokens after login
|
||||
If return_on_mfa=True and MFA required:
|
||||
dict: Contains needs_mfa and client_state for resume_login()
|
||||
"""
|
||||
client = client or http.client
|
||||
|
||||
# Define params based on domain
|
||||
SSO = f"https://sso.{client.domain}/sso"
|
||||
SSO_EMBED = f"{SSO}/embed"
|
||||
SSO_EMBED_PARAMS = dict(
|
||||
id="gauth-widget",
|
||||
embedWidget="true",
|
||||
gauthHost=SSO,
|
||||
)
|
||||
SIGNIN_PARAMS = {
|
||||
**SSO_EMBED_PARAMS,
|
||||
**dict(
|
||||
gauthHost=SSO_EMBED,
|
||||
service=SSO_EMBED,
|
||||
source=SSO_EMBED,
|
||||
redirectAfterAccountLoginUrl=SSO_EMBED,
|
||||
redirectAfterAccountCreationUrl=SSO_EMBED,
|
||||
),
|
||||
}
|
||||
|
||||
# Set cookies
|
||||
client.get("sso", "/sso/embed", params=SSO_EMBED_PARAMS)
|
||||
|
||||
# Get CSRF token
|
||||
client.get(
|
||||
"sso",
|
||||
"/sso/signin",
|
||||
params=SIGNIN_PARAMS,
|
||||
referrer=True,
|
||||
)
|
||||
csrf_token = get_csrf_token(client.last_resp.text)
|
||||
|
||||
# Submit login form with email and password
|
||||
client.post(
|
||||
"sso",
|
||||
"/sso/signin",
|
||||
params=SIGNIN_PARAMS,
|
||||
referrer=True,
|
||||
data=dict(
|
||||
username=email,
|
||||
password=password,
|
||||
embed="true",
|
||||
_csrf=csrf_token,
|
||||
),
|
||||
)
|
||||
title = get_title(client.last_resp.text)
|
||||
|
||||
# Handle MFA
|
||||
if "MFA" in title:
|
||||
if return_on_mfa or prompt_mfa is None:
|
||||
return "needs_mfa", {
|
||||
"signin_params": SIGNIN_PARAMS,
|
||||
"client": client,
|
||||
}
|
||||
|
||||
handle_mfa(client, SIGNIN_PARAMS, prompt_mfa)
|
||||
title = get_title(client.last_resp.text)
|
||||
|
||||
if title != "Success":
|
||||
raise GarthException(f"Unexpected title: {title}")
|
||||
return _complete_login(client)
|
||||
|
||||
|
||||
def get_oauth1_token(ticket: str, client: "http.Client") -> OAuth1Token:
|
||||
sess = GarminOAuth1Session(parent=client.sess)
|
||||
base_url = f"https://connectapi.{client.domain}/oauth-service/oauth/"
|
||||
login_url = f"https://sso.{client.domain}/sso/embed"
|
||||
url = (
|
||||
f"{base_url}preauthorized?ticket={ticket}&login-url={login_url}"
|
||||
"&accepts-mfa-tokens=true"
|
||||
)
|
||||
resp = sess.get(
|
||||
url,
|
||||
headers=USER_AGENT,
|
||||
timeout=client.timeout,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
parsed = parse_qs(resp.text)
|
||||
token = {k: v[0] for k, v in parsed.items()}
|
||||
return OAuth1Token(domain=client.domain, **token) # type: ignore
|
||||
|
||||
|
||||
def exchange(oauth1: OAuth1Token, client: "http.Client") -> OAuth2Token:
|
||||
sess = GarminOAuth1Session(
|
||||
resource_owner_key=oauth1.oauth_token,
|
||||
resource_owner_secret=oauth1.oauth_token_secret,
|
||||
parent=client.sess,
|
||||
)
|
||||
data = dict(mfa_token=oauth1.mfa_token) if oauth1.mfa_token else {}
|
||||
base_url = f"https://connectapi.{client.domain}/oauth-service/oauth/"
|
||||
url = f"{base_url}exchange/user/2.0"
|
||||
headers = {
|
||||
**USER_AGENT,
|
||||
**{"Content-Type": "application/x-www-form-urlencoded"},
|
||||
}
|
||||
resp = sess.post(
|
||||
url,
|
||||
headers=headers,
|
||||
data=data,
|
||||
timeout=client.timeout,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
token = resp.json()
|
||||
return OAuth2Token(**set_expirations(token))
|
||||
|
||||
|
||||
def handle_mfa(
|
||||
client: "http.Client", signin_params: dict, prompt_mfa: Callable
|
||||
) -> None:
|
||||
csrf_token = get_csrf_token(client.last_resp.text)
|
||||
if asyncio.iscoroutinefunction(prompt_mfa):
|
||||
mfa_code = asyncio.run(prompt_mfa())
|
||||
else:
|
||||
mfa_code = prompt_mfa()
|
||||
client.post(
|
||||
"sso",
|
||||
"/sso/verifyMFA/loginEnterMfaCode",
|
||||
params=signin_params,
|
||||
referrer=True,
|
||||
data={
|
||||
"mfa-code": mfa_code,
|
||||
"embed": "true",
|
||||
"_csrf": csrf_token,
|
||||
"fromPage": "setupEnterMfaCode",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def set_expirations(token: dict) -> dict:
|
||||
token["expires_at"] = int(time.time() + token["expires_in"])
|
||||
token["refresh_token_expires_at"] = int(
|
||||
time.time() + token["refresh_token_expires_in"]
|
||||
)
|
||||
return token
|
||||
|
||||
|
||||
def get_csrf_token(html: str) -> str:
|
||||
m = CSRF_RE.search(html)
|
||||
if not m:
|
||||
raise GarthException("Couldn't find CSRF token")
|
||||
return m.group(1)
|
||||
|
||||
|
||||
def get_title(html: str) -> str:
|
||||
m = TITLE_RE.search(html)
|
||||
if not m:
|
||||
raise GarthException("Couldn't find title")
|
||||
return m.group(1)
|
||||
|
||||
|
||||
def resume_login(
|
||||
client_state: dict, mfa_code: str
|
||||
) -> Tuple[OAuth1Token, OAuth2Token]:
|
||||
"""Complete login after MFA code is provided.
|
||||
|
||||
Args:
|
||||
client_state: The client state from login() when MFA was needed
|
||||
mfa_code: The MFA code provided by the user
|
||||
|
||||
Returns:
|
||||
Tuple[OAuth1Token, OAuth2Token]: The OAuth tokens after login
|
||||
"""
|
||||
client = client_state["client"]
|
||||
signin_params = client_state["signin_params"]
|
||||
handle_mfa(client, signin_params, lambda: mfa_code)
|
||||
return _complete_login(client)
|
||||
|
||||
|
||||
def _complete_login(client: "http.Client") -> Tuple[OAuth1Token, OAuth2Token]:
|
||||
"""Complete the login process after successful authentication.
|
||||
|
||||
Args:
|
||||
client: The HTTP client
|
||||
|
||||
Returns:
|
||||
Tuple[OAuth1Token, OAuth2Token]: The OAuth tokens
|
||||
"""
|
||||
# Parse ticket
|
||||
m = re.search(r'embed\?ticket=([^"]+)"', client.last_resp.text)
|
||||
if not m:
|
||||
raise GarthException(
|
||||
"Couldn't find ticket in response"
|
||||
) # pragma: no cover
|
||||
ticket = m.group(1)
|
||||
|
||||
oauth1 = get_oauth1_token(ticket, client)
|
||||
oauth2 = exchange(oauth1, client)
|
||||
|
||||
return oauth1, oauth2
|
||||
@@ -1,18 +0,0 @@
|
||||
__all__ = [
|
||||
"DailyHRV",
|
||||
"DailyHydration",
|
||||
"DailyIntensityMinutes",
|
||||
"DailySleep",
|
||||
"DailySteps",
|
||||
"DailyStress",
|
||||
"WeeklyIntensityMinutes",
|
||||
"WeeklyStress",
|
||||
"WeeklySteps",
|
||||
]
|
||||
|
||||
from .hrv import DailyHRV
|
||||
from .hydration import DailyHydration
|
||||
from .intensity_minutes import DailyIntensityMinutes, WeeklyIntensityMinutes
|
||||
from .sleep import DailySleep
|
||||
from .steps import DailySteps, WeeklySteps
|
||||
from .stress import DailyStress, WeeklyStress
|
||||
@@ -1,53 +0,0 @@
|
||||
from datetime import date, timedelta
|
||||
from typing import ClassVar
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import camel_to_snake_dict, format_end_date
|
||||
|
||||
|
||||
@dataclass
|
||||
class Stats:
|
||||
calendar_date: date
|
||||
|
||||
_path: ClassVar[str]
|
||||
_page_size: ClassVar[int]
|
||||
|
||||
@classmethod
|
||||
def list(
|
||||
cls,
|
||||
end: date | str | None = None,
|
||||
period: int = 1,
|
||||
*,
|
||||
client: http.Client | None = None,
|
||||
) -> list[Self]:
|
||||
client = client or http.client
|
||||
end = format_end_date(end)
|
||||
period_type = "days" if "daily" in cls._path else "weeks"
|
||||
|
||||
if period > cls._page_size:
|
||||
page = cls.list(end, cls._page_size, client=client)
|
||||
if not page:
|
||||
return []
|
||||
page = (
|
||||
cls.list(
|
||||
end - timedelta(**{period_type: cls._page_size}),
|
||||
period - cls._page_size,
|
||||
client=client,
|
||||
)
|
||||
+ page
|
||||
)
|
||||
return page
|
||||
|
||||
start = end - timedelta(**{period_type: period - 1})
|
||||
path = cls._path.format(start=start, end=end, period=period)
|
||||
page_dirs = client.connectapi(path)
|
||||
if not isinstance(page_dirs, list) or not page_dirs:
|
||||
return []
|
||||
page_dirs = [d for d in page_dirs if isinstance(d, dict)]
|
||||
if page_dirs and "values" in page_dirs[0]:
|
||||
page_dirs = [{**stat, **stat.pop("values")} for stat in page_dirs]
|
||||
page_dirs = [camel_to_snake_dict(stat) for stat in page_dirs]
|
||||
return [cls(**stat) for stat in page_dirs]
|
||||
@@ -1,66 +0,0 @@
|
||||
from datetime import date, datetime, timedelta
|
||||
from typing import Any, ClassVar, cast
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import camel_to_snake_dict, format_end_date
|
||||
|
||||
|
||||
@dataclass
|
||||
class HRVBaseline:
|
||||
low_upper: int
|
||||
balanced_low: int
|
||||
balanced_upper: int
|
||||
marker_value: float | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailyHRV:
|
||||
calendar_date: date
|
||||
weekly_avg: int | None
|
||||
last_night_avg: int | None
|
||||
last_night_5_min_high: int | None
|
||||
baseline: HRVBaseline | None
|
||||
status: str
|
||||
feedback_phrase: str
|
||||
create_time_stamp: datetime
|
||||
|
||||
_path: ClassVar[str] = "/hrv-service/hrv/daily/{start}/{end}"
|
||||
_page_size: ClassVar[int] = 28
|
||||
|
||||
@classmethod
|
||||
def list(
|
||||
cls,
|
||||
end: date | str | None = None,
|
||||
period: int = 28,
|
||||
*,
|
||||
client: http.Client | None = None,
|
||||
) -> list[Self]:
|
||||
client = client or http.client
|
||||
end = format_end_date(end)
|
||||
|
||||
# Paginate if period is greater than page size
|
||||
if period > cls._page_size:
|
||||
page = cls.list(end, cls._page_size, client=client)
|
||||
if not page:
|
||||
return []
|
||||
page = (
|
||||
cls.list(
|
||||
end - timedelta(days=cls._page_size),
|
||||
period - cls._page_size,
|
||||
client=client,
|
||||
)
|
||||
+ page
|
||||
)
|
||||
return page
|
||||
|
||||
start = end - timedelta(days=period - 1)
|
||||
path = cls._path.format(start=start, end=end)
|
||||
response = client.connectapi(path)
|
||||
if response is None:
|
||||
return []
|
||||
daily_hrv = camel_to_snake_dict(response)["hrv_summaries"]
|
||||
daily_hrv = cast(list[dict[str, Any]], daily_hrv)
|
||||
return [cls(**hrv) for hrv in daily_hrv]
|
||||
@@ -1,17 +0,0 @@
|
||||
from typing import ClassVar
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from ._base import Stats
|
||||
|
||||
|
||||
BASE_PATH = "/usersummary-service/stats/hydration"
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailyHydration(Stats):
|
||||
value_in_ml: float
|
||||
goal_in_ml: float
|
||||
|
||||
_path: ClassVar[str] = f"{BASE_PATH}/daily/{{start}}/{{end}}"
|
||||
_page_size: ClassVar[int] = 28
|
||||
@@ -1,28 +0,0 @@
|
||||
from typing import ClassVar
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from ._base import Stats
|
||||
|
||||
|
||||
BASE_PATH = "/usersummary-service/stats/im"
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailyIntensityMinutes(Stats):
|
||||
weekly_goal: int
|
||||
moderate_value: int | None = None
|
||||
vigorous_value: int | None = None
|
||||
|
||||
_path: ClassVar[str] = f"{BASE_PATH}/daily/{{start}}/{{end}}"
|
||||
_page_size: ClassVar[int] = 28
|
||||
|
||||
|
||||
@dataclass
|
||||
class WeeklyIntensityMinutes(Stats):
|
||||
weekly_goal: int
|
||||
moderate_value: int | None = None
|
||||
vigorous_value: int | None = None
|
||||
|
||||
_path: ClassVar[str] = f"{BASE_PATH}/weekly/{{start}}/{{end}}"
|
||||
_page_size: ClassVar[int] = 52
|
||||
@@ -1,15 +0,0 @@
|
||||
from typing import ClassVar
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from ._base import Stats
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailySleep(Stats):
|
||||
value: int | None
|
||||
|
||||
_path: ClassVar[str] = (
|
||||
"/wellness-service/stats/daily/sleep/score/{start}/{end}"
|
||||
)
|
||||
_page_size: ClassVar[int] = 28
|
||||
@@ -1,30 +0,0 @@
|
||||
from typing import ClassVar
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from ._base import Stats
|
||||
|
||||
|
||||
BASE_PATH = "/usersummary-service/stats/steps"
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailySteps(Stats):
|
||||
total_steps: int | None
|
||||
total_distance: int | None
|
||||
step_goal: int
|
||||
|
||||
_path: ClassVar[str] = f"{BASE_PATH}/daily/{{start}}/{{end}}"
|
||||
_page_size: ClassVar[int] = 28
|
||||
|
||||
|
||||
@dataclass
|
||||
class WeeklySteps(Stats):
|
||||
total_steps: int
|
||||
average_steps: float
|
||||
average_distance: float
|
||||
total_distance: float
|
||||
wellness_data_days_count: int
|
||||
|
||||
_path: ClassVar[str] = f"{BASE_PATH}/weekly/{{end}}/{{period}}"
|
||||
_page_size: ClassVar[int] = 52
|
||||
@@ -1,28 +0,0 @@
|
||||
from typing import ClassVar
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
|
||||
from ._base import Stats
|
||||
|
||||
|
||||
BASE_PATH = "/usersummary-service/stats/stress"
|
||||
|
||||
|
||||
@dataclass
|
||||
class DailyStress(Stats):
|
||||
overall_stress_level: int
|
||||
rest_stress_duration: int | None = None
|
||||
low_stress_duration: int | None = None
|
||||
medium_stress_duration: int | None = None
|
||||
high_stress_duration: int | None = None
|
||||
|
||||
_path: ClassVar[str] = f"{BASE_PATH}/daily/{{start}}/{{end}}"
|
||||
_page_size: ClassVar[int] = 28
|
||||
|
||||
|
||||
@dataclass
|
||||
class WeeklyStress(Stats):
|
||||
value: int
|
||||
|
||||
_path: ClassVar[str] = f"{BASE_PATH}/weekly/{{end}}/{{period}}"
|
||||
_page_size: ClassVar[int] = 52
|
||||
@@ -1,5 +0,0 @@
|
||||
from .profile import UserProfile
|
||||
from .settings import UserSettings
|
||||
|
||||
|
||||
__all__ = ["UserProfile", "UserSettings"]
|
||||
@@ -1,79 +0,0 @@
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import camel_to_snake_dict
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserProfile:
|
||||
id: int
|
||||
profile_id: int
|
||||
garmin_guid: str
|
||||
display_name: str
|
||||
full_name: str
|
||||
user_name: str
|
||||
profile_image_type: str | None
|
||||
profile_image_url_large: str | None
|
||||
profile_image_url_medium: str | None
|
||||
profile_image_url_small: str | None
|
||||
location: str | None
|
||||
facebook_url: str | None
|
||||
twitter_url: str | None
|
||||
personal_website: str | None
|
||||
motivation: str | None
|
||||
bio: str | None
|
||||
primary_activity: str | None
|
||||
favorite_activity_types: list[str]
|
||||
running_training_speed: float
|
||||
cycling_training_speed: float
|
||||
favorite_cycling_activity_types: list[str]
|
||||
cycling_classification: str | None
|
||||
cycling_max_avg_power: float
|
||||
swimming_training_speed: float
|
||||
profile_visibility: str
|
||||
activity_start_visibility: str
|
||||
activity_map_visibility: str
|
||||
course_visibility: str
|
||||
activity_heart_rate_visibility: str
|
||||
activity_power_visibility: str
|
||||
badge_visibility: str
|
||||
show_age: bool
|
||||
show_weight: bool
|
||||
show_height: bool
|
||||
show_weight_class: bool
|
||||
show_age_range: bool
|
||||
show_gender: bool
|
||||
show_activity_class: bool
|
||||
show_vo_2_max: bool
|
||||
show_personal_records: bool
|
||||
show_last_12_months: bool
|
||||
show_lifetime_totals: bool
|
||||
show_upcoming_events: bool
|
||||
show_recent_favorites: bool
|
||||
show_recent_device: bool
|
||||
show_recent_gear: bool
|
||||
show_badges: bool
|
||||
other_activity: str | None
|
||||
other_primary_activity: str | None
|
||||
other_motivation: str | None
|
||||
user_roles: list[str]
|
||||
name_approved: bool
|
||||
user_profile_full_name: str
|
||||
make_golf_scorecards_private: bool
|
||||
allow_golf_live_scoring: bool
|
||||
allow_golf_scoring_by_connections: bool
|
||||
user_level: int
|
||||
user_point: int
|
||||
level_update_date: str
|
||||
level_is_viewed: bool
|
||||
level_point_threshold: int
|
||||
user_point_offset: int
|
||||
user_pro: bool
|
||||
|
||||
@classmethod
|
||||
def get(cls, /, client: http.Client | None = None) -> Self:
|
||||
client = client or http.client
|
||||
profile = client.connectapi("/userprofile-service/socialProfile")
|
||||
assert isinstance(profile, dict)
|
||||
return cls(**camel_to_snake_dict(profile))
|
||||
@@ -1,108 +0,0 @@
|
||||
from datetime import date
|
||||
from typing import Dict
|
||||
|
||||
from pydantic.dataclasses import dataclass
|
||||
from typing_extensions import Self
|
||||
|
||||
from .. import http
|
||||
from ..utils import camel_to_snake_dict
|
||||
|
||||
|
||||
@dataclass
|
||||
class PowerFormat:
|
||||
format_id: int
|
||||
format_key: str
|
||||
min_fraction: int
|
||||
max_fraction: int
|
||||
grouping_used: bool
|
||||
display_format: str | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class FirstDayOfWeek:
|
||||
day_id: int
|
||||
day_name: str
|
||||
sort_order: int
|
||||
is_possible_first_day: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class WeatherLocation:
|
||||
use_fixed_location: bool | None
|
||||
latitude: float | None
|
||||
longitude: float | None
|
||||
location_name: str | None
|
||||
iso_country_code: str | None
|
||||
postal_code: str | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserData:
|
||||
gender: str
|
||||
weight: float
|
||||
height: float
|
||||
time_format: str
|
||||
birth_date: date
|
||||
measurement_system: str
|
||||
activity_level: str | None
|
||||
handedness: str
|
||||
power_format: PowerFormat
|
||||
heart_rate_format: PowerFormat
|
||||
first_day_of_week: FirstDayOfWeek
|
||||
vo_2_max_running: float | None
|
||||
vo_2_max_cycling: float | None
|
||||
lactate_threshold_speed: float | None
|
||||
lactate_threshold_heart_rate: float | None
|
||||
dive_number: int | None
|
||||
intensity_minutes_calc_method: str
|
||||
moderate_intensity_minutes_hr_zone: int
|
||||
vigorous_intensity_minutes_hr_zone: int
|
||||
hydration_measurement_unit: str
|
||||
hydration_containers: list[Dict[str, float | str | None]]
|
||||
hydration_auto_goal_enabled: bool
|
||||
firstbeat_max_stress_score: float | None
|
||||
firstbeat_cycling_lt_timestamp: int | None
|
||||
firstbeat_running_lt_timestamp: int | None
|
||||
threshold_heart_rate_auto_detected: bool
|
||||
ftp_auto_detected: bool | None
|
||||
training_status_paused_date: str | None
|
||||
weather_location: WeatherLocation | None
|
||||
golf_distance_unit: str | None
|
||||
golf_elevation_unit: str | None
|
||||
golf_speed_unit: str | None
|
||||
external_bottom_time: float | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserSleep:
|
||||
sleep_time: int
|
||||
default_sleep_time: bool
|
||||
wake_time: int
|
||||
default_wake_time: bool
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserSleepWindow:
|
||||
sleep_window_frequency: str
|
||||
start_sleep_time_seconds_from_midnight: int
|
||||
end_sleep_time_seconds_from_midnight: int
|
||||
|
||||
|
||||
@dataclass
|
||||
class UserSettings:
|
||||
id: int
|
||||
user_data: UserData
|
||||
user_sleep: UserSleep
|
||||
connect_date: str | None
|
||||
source_type: str | None
|
||||
user_sleep_windows: list[UserSleepWindow] | None = None
|
||||
|
||||
@classmethod
|
||||
def get(cls, /, client: http.Client | None = None) -> Self:
|
||||
client = client or http.client
|
||||
settings = client.connectapi(
|
||||
"/userprofile-service/userprofile/user-settings"
|
||||
)
|
||||
assert isinstance(settings, dict)
|
||||
data = camel_to_snake_dict(settings)
|
||||
return cls(**data)
|
||||
@@ -1,73 +0,0 @@
|
||||
import dataclasses
|
||||
import re
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
from typing import Any, Dict, List, Union
|
||||
|
||||
|
||||
CAMEL_TO_SNAKE = re.compile(
|
||||
r"((?<=[a-z0-9])[A-Z]|(?!^)[A-Z](?=[a-z])|(?<=[a-zA-Z])[0-9])"
|
||||
)
|
||||
|
||||
|
||||
def camel_to_snake(camel_str: str) -> str:
|
||||
snake_str = CAMEL_TO_SNAKE.sub(r"_\1", camel_str)
|
||||
return snake_str.lower()
|
||||
|
||||
|
||||
def camel_to_snake_dict(camel_dict: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""
|
||||
Converts a dictionary's keys from camel case to snake case. This version
|
||||
handles nested dictionaries and lists.
|
||||
"""
|
||||
snake_dict: Dict[str, Any] = {}
|
||||
for k, v in camel_dict.items():
|
||||
new_key = camel_to_snake(k)
|
||||
if isinstance(v, dict):
|
||||
snake_dict[new_key] = camel_to_snake_dict(v)
|
||||
elif isinstance(v, list):
|
||||
snake_dict[new_key] = [
|
||||
camel_to_snake_dict(i) if isinstance(i, dict) else i for i in v
|
||||
]
|
||||
else:
|
||||
snake_dict[new_key] = v
|
||||
return snake_dict
|
||||
|
||||
|
||||
def format_end_date(end: Union[date, str, None]) -> date:
|
||||
if end is None:
|
||||
end = date.today()
|
||||
elif isinstance(end, str):
|
||||
end = date.fromisoformat(end)
|
||||
return end
|
||||
|
||||
|
||||
def date_range(date_: Union[date, str], days: int):
|
||||
date_ = date_ if isinstance(date_, date) else date.fromisoformat(date_)
|
||||
for day in range(days):
|
||||
yield date_ - timedelta(days=day)
|
||||
|
||||
|
||||
def asdict(obj):
|
||||
if dataclasses.is_dataclass(obj):
|
||||
result = {}
|
||||
for field in dataclasses.fields(obj):
|
||||
value = getattr(obj, field.name)
|
||||
result[field.name] = asdict(value)
|
||||
return result
|
||||
|
||||
if isinstance(obj, List):
|
||||
return [asdict(v) for v in obj]
|
||||
|
||||
if isinstance(obj, (datetime, date)):
|
||||
return obj.isoformat()
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
def get_localized_datetime(
|
||||
gmt_timestamp: int, local_timestamp: int
|
||||
) -> datetime:
|
||||
local_diff = local_timestamp - gmt_timestamp
|
||||
local_offset = timezone(timedelta(milliseconds=local_diff))
|
||||
gmt_time = datetime.fromtimestamp(gmt_timestamp / 1000, timezone.utc)
|
||||
return gmt_time.astimezone(local_offset)
|
||||
@@ -1 +0,0 @@
|
||||
__version__ = "0.5.17"
|
||||
193
garth/sso/sso.go
Normal file
193
garth/sso/sso.go
Normal file
@@ -0,0 +1,193 @@
|
||||
package sso
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"garmin-connect/garth/oauth"
|
||||
"garmin-connect/garth/types"
|
||||
)
|
||||
|
||||
var (
|
||||
csrfRegex = regexp.MustCompile(`name="_csrf"\s+value="(.+?)"`)
|
||||
titleRegex = regexp.MustCompile(`<title>(.+?)</title>`)
|
||||
ticketRegex = regexp.MustCompile(`embed\?ticket=([^"]+)"`)
|
||||
)
|
||||
|
||||
// Client represents an SSO client
|
||||
type Client struct {
|
||||
Domain string
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// NewClient creates a new SSO client
|
||||
func NewClient(domain string) *Client {
|
||||
return &Client{
|
||||
Domain: domain,
|
||||
HTTPClient: &http.Client{Timeout: 30 * time.Second},
|
||||
}
|
||||
}
|
||||
|
||||
// Login performs the SSO authentication flow
|
||||
func (c *Client) Login(email, password string) (*types.OAuth2Token, error) {
|
||||
fmt.Printf("Logging in to Garmin Connect (%s) using SSO flow...\n", c.Domain)
|
||||
|
||||
// Step 1: Set up SSO parameters
|
||||
ssoURL := fmt.Sprintf("https://sso.%s/sso", c.Domain)
|
||||
ssoEmbedURL := fmt.Sprintf("%s/embed", ssoURL)
|
||||
|
||||
ssoEmbedParams := url.Values{
|
||||
"id": {"gauth-widget"},
|
||||
"embedWidget": {"true"},
|
||||
"gauthHost": {ssoURL},
|
||||
}
|
||||
|
||||
signinParams := url.Values{
|
||||
"id": {"gauth-widget"},
|
||||
"embedWidget": {"true"},
|
||||
"gauthHost": {ssoEmbedURL},
|
||||
"service": {ssoEmbedURL},
|
||||
"source": {ssoEmbedURL},
|
||||
"redirectAfterAccountLoginUrl": {ssoEmbedURL},
|
||||
"redirectAfterAccountCreationUrl": {ssoEmbedURL},
|
||||
}
|
||||
|
||||
// Step 2: Initialize SSO session
|
||||
fmt.Println("Initializing SSO session...")
|
||||
embedURL := fmt.Sprintf("https://sso.%s/sso/embed?%s", c.Domain, ssoEmbedParams.Encode())
|
||||
req, err := http.NewRequest("GET", embedURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create embed request: %w", err)
|
||||
}
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36")
|
||||
|
||||
resp, err := c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to initialize SSO: %w", err)
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
// Step 3: Get signin page and CSRF token
|
||||
fmt.Println("Getting signin page...")
|
||||
signinURL := fmt.Sprintf("https://sso.%s/sso/signin?%s", c.Domain, signinParams.Encode())
|
||||
req, err = http.NewRequest("GET", signinURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create signin request: %w", err)
|
||||
}
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36")
|
||||
req.Header.Set("Referer", embedURL)
|
||||
|
||||
resp, err = c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get signin page: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read signin response: %w", err)
|
||||
}
|
||||
|
||||
// Extract CSRF token
|
||||
csrfToken := extractCSRFToken(string(body))
|
||||
if csrfToken == "" {
|
||||
return nil, fmt.Errorf("failed to find CSRF token")
|
||||
}
|
||||
fmt.Printf("Found CSRF token: %s\n", csrfToken[:10]+"...")
|
||||
|
||||
// Step 4: Submit login form
|
||||
fmt.Println("Submitting login credentials...")
|
||||
formData := url.Values{
|
||||
"username": {email},
|
||||
"password": {password},
|
||||
"embed": {"true"},
|
||||
"_csrf": {csrfToken},
|
||||
}
|
||||
|
||||
req, err = http.NewRequest("POST", signinURL, strings.NewReader(formData.Encode()))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create login request: %w", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36")
|
||||
req.Header.Set("Referer", signinURL)
|
||||
|
||||
resp, err = c.HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to submit login: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err = io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read login response: %w", err)
|
||||
}
|
||||
|
||||
// Check login result
|
||||
title := extractTitle(string(body))
|
||||
fmt.Printf("Login response title: %s\n", title)
|
||||
|
||||
if strings.Contains(title, "MFA") {
|
||||
return nil, fmt.Errorf("MFA required - not implemented yet")
|
||||
}
|
||||
|
||||
if title != "Success" {
|
||||
return nil, fmt.Errorf("login failed, unexpected title: %s", title)
|
||||
}
|
||||
|
||||
// Step 5: Extract ticket for OAuth flow
|
||||
fmt.Println("Extracting OAuth ticket...")
|
||||
ticket := extractTicket(string(body))
|
||||
if ticket == "" {
|
||||
return nil, fmt.Errorf("failed to find OAuth ticket")
|
||||
}
|
||||
fmt.Printf("Found ticket: %s\n", ticket[:10]+"...")
|
||||
|
||||
// Step 6: Get OAuth1 token
|
||||
oauth1Token, err := oauth.GetOAuth1Token(c.Domain, ticket)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get OAuth1 token: %w", err)
|
||||
}
|
||||
fmt.Println("Got OAuth1 token")
|
||||
|
||||
// Step 7: Exchange for OAuth2 token
|
||||
oauth2Token, err := oauth.ExchangeToken(oauth1Token)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to exchange for OAuth2 token: %w", err)
|
||||
}
|
||||
fmt.Printf("Got OAuth2 token: %s\n", oauth2Token.TokenType)
|
||||
|
||||
return oauth2Token, nil
|
||||
}
|
||||
|
||||
// extractCSRFToken extracts CSRF token from HTML
|
||||
func extractCSRFToken(html string) string {
|
||||
matches := csrfRegex.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// extractTitle extracts page title from HTML
|
||||
func extractTitle(html string) string {
|
||||
matches := titleRegex.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// extractTicket extracts OAuth ticket from HTML
|
||||
func extractTicket(html string) string {
|
||||
matches := ticketRegex.FindStringSubmatch(html)
|
||||
if len(matches) > 1 {
|
||||
return matches[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -1,65 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/usersummary-service/stats/stress/daily/2023-07-21/2023-07-21
|
||||
response:
|
||||
body:
|
||||
string: '[{"calendarDate": "2023-07-21", "values": {"highStressDuration": 3240,
|
||||
"lowStressDuration": 20280, "overallStressLevel": 35, "restStressDuration":
|
||||
31020, "mediumStressDuration": 11640}}]'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12d932aa00b6ee-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:57:49 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=FuGLLTTuU8CV4eTRQnQ7XY0oTrHoXEaIYrPbxrkK1vRVT4yAr2Zv0YIj4D%2BZ0eQTeYgycpuCP1gSE4yk0bZE2Aj2p29AIZ2Ce%2BuOUJqB9Mp54VyHR9uEC5AAcVLUYqtzpE4YIK0Fgw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,223 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/activity-service/activity/12135235656
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA6VW23LbNhD9lQ6eRZsXURL5ZstOookle2SpmbbT8ayAJYUGBDgAqETJ+N874EWk
|
||||
ZbV96Btx9oLF7p5d/iRALT9we1wwkgZhEMVhFE/iyegk2G4XdyT9SaqKM5KS2SxJqD9NvCQJY288
|
||||
zSIPwmnosSBE5tNxsIMpee3NV1AgSclvKgcyIpVB/aRVxgW6C8M4CSZ+OCLcLCth+XOptH0CjdKS
|
||||
NANhsHe0OZZ4t3l0odhjWZsHk2hUHz7jkaTk2NxR1vabVidMnPdPnDGUJ58ajdWcWmQnyGpeFLAT
|
||||
2CKvI4KH1s/Ztcnw0kpSsJgrzX8gIyNilLaPmqEmaeDXeaBozFxJq5VYV+LcWTh0Vmp+AIsuf5YX
|
||||
+LuSuJXctiaV5LZ+dhyO6kNjdFOg5hSu53tOIVdkRDKgVmmS+ld+7+iC5uuIFGiBgYX2Cm4eNc+5
|
||||
BEFSqyscEYYHTvGmLAWnYLmSC2ksCNF8u2yEQTh2/ZKjtP+iJyshWq1nq7nMO8g1wwelC7Augqz+
|
||||
cgbTUXtonplxW/eVMYpysMjmqtIGe9cCjN2WDCzeuRymJPTDyPMTL0w2YZCOkzSOr3zXhKVQwJD9
|
||||
h9qBM1RbLTr/ezBPShwFl3jqmj2Y+R60vQMLXcb2YD7pDS9wIV3ezQB/Ut/wraj143ixkJm6s6qu
|
||||
dE+Tp68DmjBuSgFH2XCqsFDwH9wVvBKiBZdgufxl00nKlmwF5LjV4gF0jt2DzmRLZLwqSEr21pYm
|
||||
vb420RUU8ENJ+GauqCquc9AFlx5VUiK1XqkVu26dvHDnxVxPZjEECSYeTHfojSEIvGSXJV4GFHwa
|
||||
syALwGvfc1XK/H2IzwUI8X+jiPww88PA85FOvTGjibfzaeQxF9yOxuDP6FkUbcp79tM9F2zBDEn/
|
||||
+LM93QxGUYsblEbp9nCapXUUDVaArBwfK+1GAvl4s14uVsSV8oCrqtg5tOvfcq4qN/mCYZt/Ufqr
|
||||
qmzf59zc2LILpQMbmi7Rwl3P5gZ0liSKwiSZziazgHTK7hWuu6LJdOZ34K+oDVfS4Q2xX+vGXUiL
|
||||
0rinSYv6AMIMKfBcCm57BG/5V1zC9xtjuLFLxVwumjBr0S1Yi/q4NdD34lCwxgK4HEyIWth7q4my
|
||||
eXzgxg64ua5kTa8vXLKGjo2IgkDJQN+7ae5MO0GuVVWuOcNmw7Xalb40WwqwdI9sfllaojZKglgj
|
||||
VbpfKVBZNQdB5yCU5gO2Z3BQmtt+jLgmAdHXtFtTZ0+6l25Bna7N6V9++HaBDRYaCjzUw3eutMbB
|
||||
rnsdEVMVBehj2ybGgrZuKj0o6gZ/PxFnmyBJAz+Np/VEPCl+XG7eDk7fH6gxlyWuJEmTq8l0MiKF
|
||||
OnCZ353DKKA0yN7h9JSvwC2wXaH7DNYrDQ6oIcdPa5LOpg4o4Ht9SAbSDRYlanDEI2k0btUuoVxe
|
||||
QK1uevA+y5Da7mIJqNWO081F6SXZEk3T52T1+HJzv368Xcxfbu9X9x8Wm5dgRv7R6VvD1bmpS3Q9
|
||||
b/AZHfeiEfkGFvW9sbyAutrB+3c8wA5dhberz6vHLysy+L1q9R4UsPo9syAI4mkYTuJJGNdZ6vrz
|
||||
Acp3Natb49lqNIakk8jdjJKdgDo/jGcZapQUO9yrFY3F0pXWlS4/mYRtxYZOX1//BraydeSxCgAA
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 80e771592928359a-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 29 Sep 2023 21:50:37 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=m77%2F5qqWH%2FzNYg9h9aJB23Sa8erERimKhptV3iEpuPvFpQKcBvr8kHp%2B0tcMmTnLbEN%2FZr0zE7r9yfH0C5bHKK80P8CeBzFhzo9RkFicBPRHZMMaxBDwn7fNmDGgZpOGV9NydCV2LQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '0'
|
||||
Cookie:
|
||||
- _cfuvid=SANITIZED; ADRUM_BT1=SANITIZED; ADRUM_BTa=SANITIZED; SameSite=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: DELETE
|
||||
uri: https://connectapi.garmin.com/activity-service/activity/12135235656
|
||||
response:
|
||||
body:
|
||||
string: ''
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 80e7715a5b05359a-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Date:
|
||||
- Fri, 29 Sep 2023 21:50:37 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=RR3a8akw5KIfJ40HMjm%2FVxtacqIHiN3EkPNr5ZFwq02kvcv2Wt8fzZL9kbXMXFTHMd3iL7ZcPj4074wQQsCMR29xUXurv6SH5Nd2hdW2qeQT%2Bl7fsosUtcPp3mglfZcBnFOy9JteAg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
status:
|
||||
code: 204
|
||||
message: No Content
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- _cfuvid=SANITIZED; ADRUM_BT1=SANITIZED; ADRUM_BTa=SANITIZED; SameSite=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/activity-service/activity/12135235656
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA6tWyk0tLk5MT1WyUvIICQlQMDEwUfDLL1Fwyy/NS1HSUUotKsovUrJS8ssvAQu5
|
||||
ViSnFpRk5ucp1QIAv2CADDwAAAA=
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 80e7715cbe4b359a-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 29 Sep 2023 21:50:37 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=sBhGq8nTIKEsQsz%2FTdQHQGlCFN93mqZLF20y8BX8Vf4lPeqs0bM27QSt8IU1udH7S7x8wGmhmS3PzVMmthvCEbT8L1GrNICizdJ6H28Z%2Bd3F%2B4Em9Upz9aThxIiFzIPB8Zw6iEN%2Fqg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
status:
|
||||
code: 404
|
||||
message: Not Found
|
||||
version: 1
|
||||
@@ -1,618 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/download-service/files/activity/11998957007
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
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
|
||||
6ujSg9z1Je76Y9z1w1263KVHurTnO993AX1tvt/O9/J8j9Ie7vv5vuvEt7a4rr7r5rsC3/Xy/SN8
|
||||
v7fvjvS9Ab430HeDfTo3pZMMbi1Sk2sYT9LncjnEY873EhN874l+vnfej7bh6+m7op03q7kH3P4r
|
||||
Pun9YePx9YV/C/9/8lrZ5KZ7930RPjvfD7/sCZ7v5Q6i9Vjo5Xv9tuAnnclblZd7Ij3PW44vr5a+
|
||||
vIC/udrsoDYnqM0Nauk76xXUHIFvTr6wAUEtfWEnBbUXFCeWBbXLA3dp4FYE7rLArQzSlwfpVUHt
|
||||
VUHt5qB2R1Dzy2DNr4I132PLk6+2s0t3cemuLt3NpQtcutCle7v0kS7dx6X7uvRRLj3QpUtc+hiX
|
||||
Ptalp7t0pUvPdelTXXqeSy916fNcutqlL3LptEvXuHStS9/m0ne69FaXvt+ld7r0wy79c5f+hUs/
|
||||
4tJPufTTLv0CrzrP971M38vi0V1opTlZad1918N3Rb43yPcG+16574/0/Rk8aY87zXcLfHeO7xb5
|
||||
brHvlvjuXN+d77uLff8S37/CuSudu8F3a53b5Pu7fe9J33vGd8/67jnfPe+7l31X77s9vtvru3a8
|
||||
nvUndg3/dwGtQ/7ZhbuE0P+P//CPnzv3wsVn/jt7pX/1L9xeWh/f5tm/+//yfeynyHMHJ7bktLT0
|
||||
dy0tjwTrcpsyz/dy/NxBqTPo77zT6tGz9TXXIBBtbYV4o4EtLfNa/uO7ivy2u4ppnnekl/MddoqZ
|
||||
QS3ts+gXl+F7AW8NLkG7rXAvyD8h+sUU0h7l6Kb/BVBLBwipDEp8X3oAAJRYAQBQSwECFAAUAAgI
|
||||
CACQkytXqQxKfF96AACUWAEAGAAAAAAAAAAAAAAAAAAAAAAAMTE5OTg5NTcwMDdfQUNUSVZJVFku
|
||||
Zml0UEsFBgAAAAABAAEARgAAAKV6AAAAAA==
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8051f899de562845-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/x-zip-compressed
|
||||
Date:
|
||||
- Mon, 11 Sep 2023 18:28:32 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=UasM5X17vbczyPuHS8ZkKgf9dhIaPVvfztkmUlVZCFpeDvl304Gx8EwjapAM4eMIjt70PTgSNnNAMmXtzkVKh0BVUVAUf9X3p6ro5v%2FIN2mLHmxnv3AU27akiMmY8QOJmwHsSrIsqQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
content-disposition:
|
||||
- attachment; filename="11998957007.zip"
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,105 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- python-requests/2.31.0
|
||||
method: GET
|
||||
uri: https://thegarth.s3.amazonaws.com/oauth_consumer.json
|
||||
response:
|
||||
body:
|
||||
string: '{"consumer_key": "SANITIZED", "consumer_secret": "SANITIZED"}'
|
||||
headers:
|
||||
Accept-Ranges:
|
||||
- bytes
|
||||
Content-Length:
|
||||
- '124'
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 03:43:24 GMT
|
||||
ETag:
|
||||
- '"20240b1013cb35419bb5b2cff1407a4e"'
|
||||
Last-Modified:
|
||||
- Thu, 03 Aug 2023 00:16:11 GMT
|
||||
Server:
|
||||
- AmazonS3
|
||||
x-amz-id-2:
|
||||
- V8hHVVhXCEX7RD7Vzw8IsKS//xFr7co0468z4G834xsWIJ46GpXAwZKETm68Odczy470cauMZXo=
|
||||
x-amz-request-id:
|
||||
- Z03APPY9GXZFWZ69
|
||||
x-amz-server-side-encryption:
|
||||
- AES256
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: ''
|
||||
headers:
|
||||
Accept:
|
||||
- !!binary |
|
||||
Ki8q
|
||||
Accept-Encoding:
|
||||
- !!binary |
|
||||
Z3ppcCwgZGVmbGF0ZQ==
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- !!binary |
|
||||
a2VlcC1hbGl2ZQ==
|
||||
Content-Length:
|
||||
- !!binary |
|
||||
MA==
|
||||
Content-Type:
|
||||
- !!binary |
|
||||
YXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVk
|
||||
User-Agent:
|
||||
- !!binary |
|
||||
Y29tLmdhcm1pbi5hbmRyb2lkLmFwcHMuY29ubmVjdG1vYmlsZQ==
|
||||
method: POST
|
||||
uri: https://connectapi.garmin.com/oauth-service/oauth/exchange/user/2.0
|
||||
response:
|
||||
body:
|
||||
string: '{"scope": "COMMUNITY_COURSE_READ GARMINPAY_WRITE GOLF_API_READ ATP_READ
|
||||
GHS_SAMD GHS_UPLOAD INSIGHTS_READ COMMUNITY_COURSE_WRITE CONNECT_WRITE GCOFFER_WRITE
|
||||
GARMINPAY_READ DT_CLIENT_ANALYTICS_WRITE GOLF_API_WRITE INSIGHTS_WRITE PRODUCT_SEARCH_READ
|
||||
GCOFFER_READ CONNECT_READ ATP_WRITE", "jti": "SANITIZED", "access_token":
|
||||
"SANITIZED", "token_type": "Bearer", "refresh_token": "SANITIZED", "expires_in":
|
||||
107182, "refresh_token_expires_in": 2591999}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f13cbbc2a754790-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 03:43:23 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=T5EHGPEATgD5SbyAMCZh1mKSEJkUest3sa7l%2FTpQ6dZl3uv3K%2BW7Ng20XTseNh3KPdqYzHdkCCB5d4npBML1ZgAAmVUYdkrYiM2uJhmn7WfvSdrIyme0uCf9p5t7RY6%2BRUxNYfhL8Q%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,601 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://sso.garmin.com/sso/embed?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso
|
||||
response:
|
||||
body:
|
||||
string: "<html>\n\t<head>\n\t <title>GAuth Embedded Version</title>\n\t <meta
|
||||
http-equiv=\"X-UA-Compatible\" content=\"IE=edge;\" />\n\t <style type=\"text/css\">\n\t
|
||||
\ \t#gauth-widget {border: none !important;}\n\t </style>\n\t</head>\n\t<body>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.1.1/jquery.min.js?20210319\"></script>\n\n<div>\n\t<pre>\n\t<span>ERROR:
|
||||
clientId parameter must be specified!!!</span>\n\n\t<span >Usage: https://sso.garmin.com/sso/embed?clientId=<clientId>&locale=<locale>...</span>\n\n\tRequest
|
||||
parameter configuration options:\n\n\tNAME REQ VALUES
|
||||
\ DESCRIPTION\n\t------------------
|
||||
\ --- -------------------------------------------------------
|
||||
\ ---------------------------------------------------------------------------------------------------\n\tclientId
|
||||
\ Yes \"MY_GARMIN\"/\"BUY_GARMIN\"/\"FLY_GARMIN\"/ Client
|
||||
identifier for your web application\n\t \"RMA\"/\"GarminConnect\"/\"OpenCaching\"/etc\n\tlocale
|
||||
\ Yes \"en\", \"bg\", \"cs\", \"da\", \"de\", \"es\",
|
||||
\"el\", \"fr\", \"hr\", User's current locale, to display the GAuth login
|
||||
widget internationalized properly.\n\t \"in\",
|
||||
\"it\", \"iw\", \"hu\", \"ms\", \"nb\", \"nl\", \"no\", \"pl\", (All the
|
||||
currently supported locales are listed in the Values section.)\n\t \"pt\",
|
||||
\"pt_BR\", \"ru\", \"sk\", \"sl\", \"fi\", \"sv\", \"tr\",\n\t \"uk\",
|
||||
\"th\", \"ja\", \"ko\", \"zh_TW\", \"zh\", \"vi_VN\"\n\tcssUrl No
|
||||
\ Absolute URL to custom CSS file. Use custom CSS
|
||||
styling for the GAuth login widget.\n\treauth No
|
||||
\ true/false (Default value is false) Specify true if
|
||||
you want to ensure that the GAuth login widget shows up,\n\t even
|
||||
if the SSO infrastructure remembers the user and would immediately log them
|
||||
in.\n\t This
|
||||
is useful if you know a user is logged on, but want a different user to be
|
||||
allowed to logon.\n\tinitialFocus No true/false (Default
|
||||
value is true) If you don't want the GAuth login widget
|
||||
to autofocus in it's \"Email or Username\" field upon initial loading,\n\t
|
||||
\ then
|
||||
specify this option and set it to false.\n\trememberMeShown No
|
||||
\ true/false (Default value is false) Whether the \"Remember
|
||||
Me\" check box is shown in the GAuth login widget.\n\trememberMeChecked No
|
||||
\ true/false (Default value is false) Whether the \"Remember
|
||||
Me\" check box feature is checked by default.\n\tcreateAccountShown No
|
||||
\ true/false (Default value is true) Whether the \"Don't
|
||||
have an account? Create One\" link is shown in the GAuth login widget.\n\tsocialEnabled
|
||||
\ No true/false (Default value is false) If
|
||||
set to false, do not show any social sign in elements or allow social sign
|
||||
ins.\n\tlockToEmailAddress No Email address to pre-load and
|
||||
lock. If specified, the specified email address will
|
||||
be pre-loaded in the main \"Email\" field in the SSO login form,\n\t as
|
||||
well as in in the \"Email Address\" field in the \"Forgot Password?\" password
|
||||
reset form,\n\t and
|
||||
both fields will be disabled so they can't be changed.\n\t (If
|
||||
for some reason you want to force re-authentications for a known customer
|
||||
account, you can make use of this option.)\n\topenCreateAccount No
|
||||
\ true/false (Default value is false) If set to true,
|
||||
immediately display the the account creation screen.\n\tdisplayNameShown No
|
||||
\ true/false (Default value is false) If set to true,
|
||||
show the \"Display Name\" field on the account creation screen, to allow the
|
||||
user\n\t to
|
||||
set their central MyGarmin display name upon account creation.\n\tglobalOptInShown
|
||||
\ No true/false (Default value is false) Whether
|
||||
the \"Global Opt-In\" check box is shown on the create account & create social
|
||||
account screens.\n\t If
|
||||
set to true these screens will show a \"Sign Up For Email\" check box with
|
||||
accompanying text\n\t \"I
|
||||
would also like to receive email about promotions and new products.\"\n\t
|
||||
\ If
|
||||
checked, the Customer 2.0 account that is created will have it's global opt-in
|
||||
flag set to true,\n\t and
|
||||
Garmin email communications will be allowed.\n\tglobalOptInChecked No
|
||||
\ true/false (Default value is false) Whether the \"Global
|
||||
Opt-In\" check box is checked by default.\n\tconsumeServiceTicket No
|
||||
\ true/false (Default value is true) IF you don't specify
|
||||
a redirectAfterAccountLoginUrl AND you set this to false, the GAuth login
|
||||
widget\n\t will
|
||||
NOT consume the service ticket assigned and will not seamlessly log you into
|
||||
your webapp.\n\t It
|
||||
will send a SUCCESS JavaScript event with the service ticket and service url
|
||||
you can take\n\t and
|
||||
explicitly validate against the SSO infrastructure yourself.\n\t (By
|
||||
using casClient's SingleSignOnUtils.authenticateServiceTicket() utility method,\n\t
|
||||
\ or
|
||||
calling web service customerWebServices_v1.2 AccountManagementService.authenticateServiceTicket().)\n\tmobile
|
||||
\ No true/false (Default value is false) Setting
|
||||
to true will cause mobile friendly views to be shown instead of the tradition
|
||||
screens.\n\ttermsOfUseUrl No Absolute URL to your custom
|
||||
terms of use URL. If not specified, defaults to http://www.garmin.com/terms\n\tprivacyStatementUrl
|
||||
\ No Absolute URL to your custom privacy statement URL. If
|
||||
not specified, defaults to http://www.garmin.com/privacy\n\tproductSupportUrl
|
||||
\ No Absolute URL to your custom product support URL. If
|
||||
not specified, defaults to http://www.garmin.com/us/support/contact\n\tgenerateExtraServiceTicket
|
||||
\ No true/false (Default value is false) If set
|
||||
to true, generate an extra unconsumed service ticket.\n\t\t (The
|
||||
service ticket validation response will include the extra service ticket.)\n\tgenerateTwoExtraServiceTickets
|
||||
\ No true/false (Default value is false) If set to true,
|
||||
generate two extra unconsumed service tickets.\n\t\t\t\t\t\t\t\t\t \t\t\t
|
||||
\ (The service ticket validation response will include the extra service
|
||||
tickets.)\n\tgenerateNoServiceTicket No true/false (Default value
|
||||
is false) If you don't want SSO to generate a service
|
||||
ticket at all when logging in to the GAuth login widget.\n (Useful
|
||||
when allowing logins to static sites that are not SSO enabled and can't consume
|
||||
the service ticket.)\n\tconnectLegalTerms No true/false (Default
|
||||
value is false) Whether to show the connectLegalTerms
|
||||
on the create account page\n\tshowTermsOfUse No true/false
|
||||
(Default value is false) Whether to show the showTermsOfUse
|
||||
on the create account page\n\tshowPrivacyPolicy No true/false
|
||||
(Default value is false) Whether to show the showPrivacyPolicy
|
||||
on the create account page\n\tshowConnectLegalAge No true/false
|
||||
(Default value is false) Whether to show the showConnectLegalAge
|
||||
on the create account page\n\tlocationPromptShown No true/false
|
||||
(Default value is false) If set to true, ask the customer
|
||||
during account creation to verify their country of residence.\n\tshowPassword
|
||||
\ No true/false (Default value is true) If
|
||||
set to false, mobile version for createAccount and login screens would hide
|
||||
the password\n\tuseCustomHeader No true/false (Default value
|
||||
is false) If set to true, the \"Sign in\" text will be
|
||||
replaced by custom text. Contact CDS team to set the i18n text for your client
|
||||
id.\n\tmfaRequired No true/false (Default value is false)
|
||||
\ Require multi factor authentication for all authenticating
|
||||
users.\n\tperformMFACheck No true/false (Default value is
|
||||
false) If set to true, ask the logged in user to pass
|
||||
a multi factor authentication check. (Only valid for an already logged in
|
||||
user.)\n\trememberMyBrowserShown No true/false (Default value is
|
||||
false) Whether the \"Remember My Browser\" check box
|
||||
is shown in the GAuth login widget MFA verification screen.\n\trememberMyBrowserChecked
|
||||
\ No true/false (Default value is false) Whether
|
||||
the \"Remember My Browser\" check box feature is checked by default.\n\tconsentTypeIds\t\t\t\t\tNo\tconsent_types
|
||||
ids\t\t \t\t\t\t\t\t\t\t multiple consent types ids can be passed as consentTypeIds=type1&consentTypeIds=type2\n\t</pre>\n</div>\n\n\n\t<script>(function(){var
|
||||
js = \"window['__CF$cv$params']={r:'7f1ab8a0eff61559'};_cpo=document.createElement('script');_cpo.nonce='',_cpo.src='/cdn-cgi/challenge-platform/scripts/invisible.js',document.getElementsByTagName('head')[0].appendChild(_cpo);\";var
|
||||
_0xh = document.createElement('iframe');_0xh.height = 1;_0xh.width = 1;_0xh.style.position
|
||||
= 'absolute';_0xh.style.top = 0;_0xh.style.left = 0;_0xh.style.border = 'none';_0xh.style.visibility
|
||||
= 'hidden';document.body.appendChild(_0xh);function handler() {var _0xi =
|
||||
_0xh.contentDocument || _0xh.contentWindow.document;if (_0xi) {var _0xj =
|
||||
_0xi.createElement('script');_0xj.innerHTML = js;_0xi.getElementsByTagName('head')[0].appendChild(_0xj);}}if
|
||||
(document.readyState !== 'loading') {handler();} else if (window.addEventListener)
|
||||
{document.addEventListener('DOMContentLoaded', handler);} else {var prev =
|
||||
document.onreadystatechange || function () {};document.onreadystatechange
|
||||
= function (e) {prev(e);if (document.readyState !== 'loading') {document.onreadystatechange
|
||||
= prev;handler();}};}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f1ab8a0eff61559-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:53:41 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=j5pKqMzrTlGTnexO0FnuZsm0YObQFg1OH0auGBikdNQ44TMOIITdLtHmkIg36gVUZ65RQe4mMPXUL0SfZUdBcVPtg%2F3Dr3d4GgcIueMqtynkohsWR86sKXRVMZroPe%2Fp"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- __cf_bm=SANITIZED; path=SANITIZED; expires=SANITIZED; domain=SANITIZED; HttpOnly;
|
||||
Secure; SameSite=SANITIZED
|
||||
- __cflb=SANITIZED; SameSite=SANITIZED; Secure; path=SANITIZED; expires=SANITIZED;
|
||||
HttpOnly
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_1102:6
|
||||
X-B3-Traceid:
|
||||
- 3d744417e02674885d3c4741abc1daad
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- d62a3e74-b259-4a55-437a-2635831aa9f2
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- __cf_bm=SANITIZED; _cfuvid=SANITIZED; __cflb=SANITIZED; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/embed?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso
|
||||
method: GET
|
||||
uri: https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: "<!DOCTYPE html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n <meta
|
||||
http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <meta
|
||||
name=\"viewport\" content=\"width=device-width\" />\n <meta http-equiv=\"X-UA-Compatible\"
|
||||
content=\"IE=edge;\" />\n <title>GARMIN Authentication Application</title>\n
|
||||
\ <link href=\"/sso/css/GAuth.css?20210406\" rel=\"stylesheet\" type=\"text/css\"
|
||||
media=\"all\" />\n\n\t <link rel=\"stylesheet\" href=\"\"/>\n\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.1.1/jquery.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\">jQuery.noConflict();</script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery-validate/1.16.0/jquery.validate.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/jsUtils.js?20210406\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/json2.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/consoleUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/postmessage.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/popupWindow.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/base.js?20210406\"></script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/gigyaUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/login.js?20211102\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/reCaptchaUtil.js?20230706\"></script>\n\n
|
||||
\ <script>\n var recaptchaSiteKey = null;\n var
|
||||
reCaptchaURL = \"\\\\\\/sso\\\\\\/reCaptcha?id=gauth-widget\\u0026embedWidget=true\\u0026gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\";\n
|
||||
\ var isRecaptchaEnabled = null;\n var recaptchaToken
|
||||
= null; \n </script>\n <script type=\"text/javascript\">\n
|
||||
\ var parent_url = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n
|
||||
\ var status \t\t\t= \"\";\n\t\t\tvar result = \"\";\n\t\t\tvar
|
||||
clientId\t\t= '';\n\t\t\tvar embedWidget \t= true;\n\t\t\tvar isUsernameDefined
|
||||
= (false == true) || (false == true);\n\n // Gigya callback to
|
||||
SocialSignInController for brand new social network users redirects to this
|
||||
page\n // to popup Create or Link Social Account page, but has
|
||||
a possibly mangled source parameter\n // where \"?\" is set as
|
||||
\"<QM>\", so translate it back to \"?\" here.\n parent_url = parent_url.replace('<QM>',
|
||||
'?');\n var parent_scheme = parent_url.substring(0, parent_url.indexOf(\"://\"));\n
|
||||
\ var parent_hostname = parent_url.substring(parent_scheme.length
|
||||
+ 3, parent_url.length);\n if (parent_hostname.indexOf(\"/\") !=
|
||||
-1) {\n parent_hostname = parent_hostname.substring(0, parent_hostname.indexOf(\"/\"));\n
|
||||
\ }\n var parentHost \t = parent_scheme + \"://\"
|
||||
+ parent_hostname;\n\t\t\tvar createAccountConfigURL = '\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed';\n
|
||||
\ var socialConfigURL = 'https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed';\n
|
||||
\ var gigyaURL = \"https://cdns.gigya.com/js/gigya.js?apiKey=2_R3ZGY8Bqlwwk3_63knoD9wA_m-Y19mAgW61bF_s5k9gymYnMEAtMrJiF5MjF-U7B\";\n\n
|
||||
\ if (createAccountConfigURL.indexOf('%253A%252F%252F') != -1) {\n
|
||||
\ \tcreateAccountConfigURL = decodeURIComponent(createAccountConfigURL);\n
|
||||
\ }\n consoleInfo('signin.html embedWidget: true, createAccountConfigURL:
|
||||
\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed,
|
||||
socialEnabled: true, gigyaSupported: true, socialConfigURL(): https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed');\n\n
|
||||
\ if (socialConfigURL.indexOf('%3A%2F%2F') != -1) {\n \tsocialConfigURL
|
||||
= decodeURIComponent(socialConfigURL);\n }\n\n if( status
|
||||
!= null && status != ''){\n \tsend({'status':status});\n }\n\n
|
||||
\ jQuery(document).ready( function(){\n\n\n consoleInfo(\"signin.html:
|
||||
setting field validation rules...\");\n\n jQuery(\"#username\").rules(\"add\",{\n
|
||||
\ required: true,\n messages: {\n required:
|
||||
\ \"Email is required.\"\n }});\n\n jQuery(\"#password\").rules(\"add\",
|
||||
{\n required: true,\n messages: {\n
|
||||
\ required: \"Password is required.\"\n }\n
|
||||
\ });\n\n consoleInfo(\"signin.html: done setting
|
||||
field validation rules...\");\n\n });\n\n XD.receiveMessage(function(m){\n
|
||||
\ consoleInfo(\"signin.html: \" + m.data + \" received on \"
|
||||
+ window.location.host);\n if (m && m.data) {\n var
|
||||
md = m.data;\n if (typeof(md) === 'string') {\n md
|
||||
= JSON.parse(m.data);\n }\n if (md.setUsername)
|
||||
{\n consoleInfo(\"signin.html: Setting username \\\"\"
|
||||
+ md.username + \"\\\"...\");\n jQuery(\"#signInWithDiffLink\").click();
|
||||
// Ensure the normal login form is shown.\n jQuery(\"#username\").val(md.username);\n
|
||||
\ jQuery(\"#password\").focus();\n }\n
|
||||
\ }\n }, parentHost);\n </script>\n </head>\n
|
||||
\ <body>\n\n <!-- begin GAuth component -->\n <div id=\"GAuth-component\">\n
|
||||
\ <!-- begin login component-->\n <div id=\"login-component\"
|
||||
class=\"blueForm-basic\">\n <input type=\"hidden\" id=\"queryString\"
|
||||
value=\"id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\"
|
||||
/>\n\t \t <input type=\"hidden\" id=\"contextPath\" value=\"/sso\" />\n
|
||||
\ <!-- begin login form -->\n <div id=\"login-state-default\">\n
|
||||
\ <h2>Sign In</h2>\n\n <form method=\"post\"
|
||||
id=\"login-form\">\n\n <div class=\"form-alert\">\n\t\t\t\t\t\t\t\n
|
||||
\ \n \n \n
|
||||
\ \n \n \n\n
|
||||
\ <div id=\"username-error\" style=\"display:none;\"></div>\n
|
||||
\ <div id=\"password-error\" style=\"display:none;\"></div>\n
|
||||
\ </div>\n <div class=\"textfield\">\n\t\t\t\t\t\t\t<label
|
||||
for=\"username\">Email</label>\n \t\t<!-- If the
|
||||
lockToEmailAddress parameter is specified then we want to mark the field as
|
||||
readonly,\n \t\tpreload the email address, and disable
|
||||
the other input so that null isn't sent to the server. We'll\n \t\talso
|
||||
style the field to have a darker grey background and disable the mouse pointer\n
|
||||
\ \t\t -->\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t<!--
|
||||
If the lockToEmailAddress parameter is NOT specified then keep the existing
|
||||
functionality and disable the readonly input field\n\t\t\t\t\t\t\t -->\n\t\t\t\t\t\t\t
|
||||
\ <input class=\"login_email\" name=\"username\" id=\"username\" value=\"\"
|
||||
type=\"email\" spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\"/>\n\n
|
||||
\ </div>\n\n <div class=\"textfield\">\n
|
||||
\ <label for=\"password\">Password</label>\n <a
|
||||
id=\"loginforgotpassword\" class=\"login-forgot-password\" style=\"cursor:pointer\">(Forgot?)</a>\n
|
||||
\ <input type=\"password\" name=\"password\" id=\"password\"
|
||||
spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\" />\n <strong
|
||||
id=\"capslock-warning\" class=\"information\" title=\"Caps lock is on.\" style=\"display:
|
||||
none;\">Caps lock is on.</strong>\n\t\t\t\t\t </div>\n <input
|
||||
type=\"hidden\" name=\"embed\" value=\"true\"/>\n <input
|
||||
type=\"hidden\" name=\"_csrf\" value=\"DAA89CB8362ABB6DB2548101BE44A857AFCE1CC8C7B0825A54361D5D1FB60E47649DA070B388D04CB797C2AD4C9B9FAF9E3C\"
|
||||
/>\n <button type=\"submit\" id=\"login-btn-signin\"
|
||||
class=\"btn1\" accesskey=\"l\">Sign In</button>\n \n\n\n
|
||||
\ <!-- The existence of the \"rememberme\" parameter
|
||||
at all will remember the user! -->\n \n\n </form>\n
|
||||
\ </div>\n <!-- end login form -->\n\n <!--
|
||||
begin Create Account message -->\n\t <div id=\"login-create-account\">\n\t
|
||||
\ \n\t </div>\n\t <!-- end Create Account
|
||||
message -->\n\n\t <!-- begin Social Sign In component -->\n\t <div
|
||||
id=\"SSI-component\">\n \n\n\t\t\t\t\t\n\t </div>\n\t
|
||||
\ <!-- end Social Sign In component -->\n <div class=\"clearfix\"></div>
|
||||
<!-- Ensure that GAuth-component div's height is computed correctly. -->\n
|
||||
\ </div>\n <!-- end login component-->\n\n\t\t</div>\n\t\t<!--
|
||||
end GAuth component -->\n\n <script type=\"text/javascript\">\n jQuery(document).ready(function(){\n
|
||||
\ \tresizePageOnLoad(jQuery(\"#GAuth-component\").height());\n\n\t\t
|
||||
\ if(isUsernameDefined == true){\n\t\t // If the user's login
|
||||
just failed, redisplay the email/username specified, and focus them in the
|
||||
password field.\n\t\t jQuery(\"#password\").focus();\n\t\t }
|
||||
else if(false == true && result != \"PASSWORD_RESET_RESULT\"){\n //
|
||||
Otherwise focus them in the username field of the login dialog.\n jQuery(\"#username\").focus();\n
|
||||
\ }\n\n // Scroll to top of iframe to fix problem
|
||||
where Firefox 3.0-3.6 browsers initially show top of iframe cutoff.\n location.href=\"#\";\n\n
|
||||
\ if(!embedWidget){\n \tjQuery('.createAccountLink').click(function(){\n\t
|
||||
\ send({'openLiteBox':'createAccountLink', 'popupUrl': createAccountConfigURL,
|
||||
'popupTitle':'Create An Account', 'clientId':clientId});\n\t });\n
|
||||
\ }\n });\n </script>\n <script>(function(){var
|
||||
js = \"window['__CF$cv$params']={r:'7f1ab8a1e90a155f'};_cpo=document.createElement('script');_cpo.nonce='',_cpo.src='/cdn-cgi/challenge-platform/scripts/invisible.js',document.getElementsByTagName('head')[0].appendChild(_cpo);\";var
|
||||
_0xh = document.createElement('iframe');_0xh.height = 1;_0xh.width = 1;_0xh.style.position
|
||||
= 'absolute';_0xh.style.top = 0;_0xh.style.left = 0;_0xh.style.border = 'none';_0xh.style.visibility
|
||||
= 'hidden';document.body.appendChild(_0xh);function handler() {var _0xi =
|
||||
_0xh.contentDocument || _0xh.contentWindow.document;if (_0xi) {var _0xj =
|
||||
_0xi.createElement('script');_0xj.innerHTML = js;_0xi.getElementsByTagName('head')[0].appendChild(_0xj);}}if
|
||||
(document.readyState !== 'loading') {handler();} else if (window.addEventListener)
|
||||
{document.addEventListener('DOMContentLoaded', handler);} else {var prev =
|
||||
document.onreadystatechange || function () {};document.onreadystatechange
|
||||
= function (e) {prev(e);if (document.readyState !== 'loading') {document.onreadystatechange
|
||||
= prev;handler();}};}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-Ray:
|
||||
- 7f1ab8a1e90a155f-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:53:41 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=2m3IsPHrodwZcDphNIdQkuKtFDRIq67h9%2BNyhtturCTJsq8UH%2BqzYY1lhYjgkKLu0YrwD8sYfVBP03Dj8Lf4R0Ghzc0o647YHYroy2Tkp2YQLDOtMwR56XKEVYEl0yhg"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- SESSION=SANITIZED; Path=SANITIZED; Secure; HttpOnly
|
||||
- __VCAP_ID__=SANITIZED; Path=SANITIZED; HttpOnly; Secure
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_1102:5
|
||||
X-B3-Traceid:
|
||||
- 5ebef167e205ed0449ddea900e2d06fc
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- 8bb46b1b-d486-4df3-5d3e-2767045abcdd
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: username=SANITIZED&password=SANITIZED&embed=true&_csrf=DAA89CB8362ABB6DB2548101BE44A857AFCE1CC8C7B0825A54361D5D1FB60E47649DA070B388D04CB797C2AD4C9B9FAF9E3C
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '171'
|
||||
Content-Type:
|
||||
- application/x-www-form-urlencoded
|
||||
Cookie:
|
||||
- SESSION=SANITIZED; __cf_bm=SANITIZED; _cfuvid=SANITIZED; __VCAP_ID__=SANITIZED;
|
||||
__cflb=SANITIZED; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: POST
|
||||
uri: https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: "<!DOCTYPE html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n <meta
|
||||
http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <meta
|
||||
name=\"viewport\" content=\"width=device-width\" />\n <meta http-equiv=\"X-UA-Compatible\"
|
||||
content=\"IE=edge;\" />\n <title>GARMIN Authentication Application</title>\n
|
||||
\ <link href=\"/sso/css/GAuth.css?20210406\" rel=\"stylesheet\" type=\"text/css\"
|
||||
media=\"all\" />\n\n\t <link rel=\"stylesheet\" href=\"\"/>\n\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.1.1/jquery.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\">jQuery.noConflict();</script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery-validate/1.16.0/jquery.validate.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/jsUtils.js?20210406\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/json2.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/consoleUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/postmessage.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/popupWindow.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/base.js?20210406\"></script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/gigyaUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/login.js?20211102\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/reCaptchaUtil.js?20230706\"></script>\n\n
|
||||
\ <script>\n var recaptchaSiteKey = null;\n var
|
||||
reCaptchaURL = \"\\\\\\/sso\\\\\\/reCaptcha?id=gauth-widget\\u0026embedWidget=true\\u0026gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\";\n
|
||||
\ var isRecaptchaEnabled = null;\n var recaptchaToken
|
||||
= null; \n </script>\n <script type=\"text/javascript\">\n
|
||||
\ var parent_url = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n
|
||||
\ var status \t\t\t= \"FAIL\";\n\t\t\tvar result = \"error\";\n\t\t\tvar
|
||||
clientId\t\t= '';\n\t\t\tvar embedWidget \t= true;\n\t\t\tvar isUsernameDefined
|
||||
= (true == true) || (true == true);\n\n // Gigya callback to SocialSignInController
|
||||
for brand new social network users redirects to this page\n //
|
||||
to popup Create or Link Social Account page, but has a possibly mangled source
|
||||
parameter\n // where \"?\" is set as \"<QM>\", so translate it
|
||||
back to \"?\" here.\n parent_url = parent_url.replace('<QM>', '?');\n
|
||||
\ var parent_scheme = parent_url.substring(0, parent_url.indexOf(\"://\"));\n
|
||||
\ var parent_hostname = parent_url.substring(parent_scheme.length
|
||||
+ 3, parent_url.length);\n if (parent_hostname.indexOf(\"/\") !=
|
||||
-1) {\n parent_hostname = parent_hostname.substring(0, parent_hostname.indexOf(\"/\"));\n
|
||||
\ }\n var parentHost \t = parent_scheme + \"://\"
|
||||
+ parent_hostname;\n\t\t\tvar createAccountConfigURL = '\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed';\n
|
||||
\ var socialConfigURL = 'https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed';\n
|
||||
\ var gigyaURL = \"https://cdns.gigya.com/js/gigya.js?apiKey=2_R3ZGY8Bqlwwk3_63knoD9wA_m-Y19mAgW61bF_s5k9gymYnMEAtMrJiF5MjF-U7B\";\n\n
|
||||
\ if (createAccountConfigURL.indexOf('%253A%252F%252F') != -1) {\n
|
||||
\ \tcreateAccountConfigURL = decodeURIComponent(createAccountConfigURL);\n
|
||||
\ }\n consoleInfo('signin.html embedWidget: true, createAccountConfigURL:
|
||||
\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed,
|
||||
socialEnabled: true, gigyaSupported: true, socialConfigURL(): https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed');\n\n
|
||||
\ if (socialConfigURL.indexOf('%3A%2F%2F') != -1) {\n \tsocialConfigURL
|
||||
= decodeURIComponent(socialConfigURL);\n }\n\n if( status
|
||||
!= null && status != ''){\n \tsend({'status':status});\n }\n\n
|
||||
\ jQuery(document).ready( function(){\n\n\n consoleInfo(\"signin.html:
|
||||
setting field validation rules...\");\n\n jQuery(\"#username\").rules(\"add\",{\n
|
||||
\ required: true,\n messages: {\n required:
|
||||
\ \"Email is required.\"\n }});\n\n jQuery(\"#password\").rules(\"add\",
|
||||
{\n required: true,\n messages: {\n
|
||||
\ required: \"Password is required.\"\n }\n
|
||||
\ });\n\n consoleInfo(\"signin.html: done setting
|
||||
field validation rules...\");\n\n });\n\n XD.receiveMessage(function(m){\n
|
||||
\ consoleInfo(\"signin.html: \" + m.data + \" received on \"
|
||||
+ window.location.host);\n if (m && m.data) {\n var
|
||||
md = m.data;\n if (typeof(md) === 'string') {\n md
|
||||
= JSON.parse(m.data);\n }\n if (md.setUsername)
|
||||
{\n consoleInfo(\"signin.html: Setting username \\\"\"
|
||||
+ md.username + \"\\\"...\");\n jQuery(\"#signInWithDiffLink\").click();
|
||||
// Ensure the normal login form is shown.\n jQuery(\"#username\").val(md.username);\n
|
||||
\ jQuery(\"#password\").focus();\n }\n
|
||||
\ }\n }, parentHost);\n </script>\n </head>\n
|
||||
\ <body>\n\n <!-- begin GAuth component -->\n <div id=\"GAuth-component\">\n
|
||||
\ <!-- begin login component-->\n <div id=\"login-component\"
|
||||
class=\"blueForm-basic\">\n <input type=\"hidden\" id=\"queryString\"
|
||||
value=\"id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\"
|
||||
/>\n\t \t <input type=\"hidden\" id=\"contextPath\" value=\"/sso\" />\n
|
||||
\ <!-- begin login form -->\n <div id=\"login-state-default\">\n
|
||||
\ <h2>Sign In</h2>\n\n <form method=\"post\"
|
||||
id=\"login-form\">\n\n <div class=\"form-alert\">\n\t\t\t\t\t\t\t\n
|
||||
\ \n \n \n
|
||||
\ \n \n <div
|
||||
id=\"status\" class=\"error\">Invalid sign in. (Passwords are case sensitive.)</div>\n\n
|
||||
\ <div id=\"username-error\" style=\"display:none;\"></div>\n
|
||||
\ <div id=\"password-error\" style=\"display:none;\"></div>\n
|
||||
\ </div>\n <div class=\"textfield\">\n\t\t\t\t\t\t\t<label
|
||||
for=\"username\">Email</label>\n \t\t<!-- If the
|
||||
lockToEmailAddress parameter is specified then we want to mark the field as
|
||||
readonly,\n \t\tpreload the email address, and disable
|
||||
the other input so that null isn't sent to the server. We'll\n \t\talso
|
||||
style the field to have a darker grey background and disable the mouse pointer\n
|
||||
\ \t\t -->\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t<!--
|
||||
If the lockToEmailAddress parameter is NOT specified then keep the existing
|
||||
functionality and disable the readonly input field\n\t\t\t\t\t\t\t -->\n\t\t\t\t\t\t\t
|
||||
\ <input class=\"login_email\" name=\"username\" id=\"username\" value=\"user@example.com\"
|
||||
type=\"email\" spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\"/>\n\n
|
||||
\ </div>\n\n <div class=\"textfield\">\n
|
||||
\ <label for=\"password\">Password</label>\n <a
|
||||
id=\"loginforgotpassword\" class=\"login-forgot-password\" style=\"cursor:pointer\">(Forgot?)</a>\n
|
||||
\ <input type=\"password\" name=\"password\" id=\"password\"
|
||||
spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\" />\n <strong
|
||||
id=\"capslock-warning\" class=\"information\" title=\"Caps lock is on.\" style=\"display:
|
||||
none;\">Caps lock is on.</strong>\n\t\t\t\t\t </div>\n <input
|
||||
type=\"hidden\" name=\"embed\" value=\"true\"/>\n <input
|
||||
type=\"hidden\" name=\"_csrf\" value=\"25BD4FF6F23ED011DADAD97BD7125D89DF74ACC8A85485B451F997AB2E42D9216133505121272347D78B445FB19881C9968B\"
|
||||
/>\n <button type=\"submit\" id=\"login-btn-signin\"
|
||||
class=\"btn1\" accesskey=\"l\">Sign In</button>\n \n\n\n
|
||||
\ <!-- The existence of the \"rememberme\" parameter
|
||||
at all will remember the user! -->\n \n\n </form>\n
|
||||
\ </div>\n <!-- end login form -->\n\n <!--
|
||||
begin Create Account message -->\n\t <div id=\"login-create-account\">\n\t
|
||||
\ \n\t </div>\n\t <!-- end Create Account
|
||||
message -->\n\n\t <!-- begin Social Sign In component -->\n\t <div
|
||||
id=\"SSI-component\">\n \n\n\t\t\t\t\t\n\t </div>\n\t
|
||||
\ <!-- end Social Sign In component -->\n <div class=\"clearfix\"></div>
|
||||
<!-- Ensure that GAuth-component div's height is computed correctly. -->\n
|
||||
\ </div>\n <!-- end login component-->\n\n\t\t</div>\n\t\t<!--
|
||||
end GAuth component -->\n\n <script type=\"text/javascript\">\n jQuery(document).ready(function(){\n
|
||||
\ \tresizePageOnLoad(jQuery(\"#GAuth-component\").height());\n\n\t\t
|
||||
\ if(isUsernameDefined == true){\n\t\t // If the user's login
|
||||
just failed, redisplay the email/username specified, and focus them in the
|
||||
password field.\n\t\t jQuery(\"#password\").focus();\n\t\t }
|
||||
else if(false == true && result != \"PASSWORD_RESET_RESULT\"){\n //
|
||||
Otherwise focus them in the username field of the login dialog.\n jQuery(\"#username\").focus();\n
|
||||
\ }\n\n // Scroll to top of iframe to fix problem
|
||||
where Firefox 3.0-3.6 browsers initially show top of iframe cutoff.\n location.href=\"#\";\n\n
|
||||
\ if(!embedWidget){\n \tjQuery('.createAccountLink').click(function(){\n\t
|
||||
\ send({'openLiteBox':'createAccountLink', 'popupUrl': createAccountConfigURL,
|
||||
'popupTitle':'Create An Account', 'clientId':clientId});\n\t });\n
|
||||
\ }\n });\n </script>\n <script>(function(){var
|
||||
js = \"window['__CF$cv$params']={r:'7f1ab8a41e554752'};_cpo=document.createElement('script');_cpo.nonce='',_cpo.src='/cdn-cgi/challenge-platform/scripts/invisible.js',document.getElementsByTagName('head')[0].appendChild(_cpo);\";var
|
||||
_0xh = document.createElement('iframe');_0xh.height = 1;_0xh.width = 1;_0xh.style.position
|
||||
= 'absolute';_0xh.style.top = 0;_0xh.style.left = 0;_0xh.style.border = 'none';_0xh.style.visibility
|
||||
= 'hidden';document.body.appendChild(_0xh);function handler() {var _0xi =
|
||||
_0xh.contentDocument || _0xh.contentWindow.document;if (_0xi) {var _0xj =
|
||||
_0xi.createElement('script');_0xj.innerHTML = js;_0xi.getElementsByTagName('head')[0].appendChild(_0xj);}}if
|
||||
(document.readyState !== 'loading') {handler();} else if (window.addEventListener)
|
||||
{document.addEventListener('DOMContentLoaded', handler);} else {var prev =
|
||||
document.onreadystatechange || function () {};document.onreadystatechange
|
||||
= function (e) {prev(e);if (document.readyState !== 'loading') {document.onreadystatechange
|
||||
= prev;handler();}};}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-Ray:
|
||||
- 7f1ab8a41e554752-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:53:42 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=NmXSOa2OY4MXHw09DrfMkMUFE5FijBSW8oF9uituKDizIcYfhS1rFKYV0Q3ACOQVYT6Q8Iwzj6PiIL%2BBY6E4f%2BFqsB2a20zfVAiW65WDXm6hGdPkJozBoAfyFzQZzAOc"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- __cfruid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_1102:5
|
||||
X-B3-Traceid:
|
||||
- 139f06d066cf2a2d4b988ae89e0203d7
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- b2849c1b-b909-403f-57b6-e13f20fc9546
|
||||
status:
|
||||
code: 401
|
||||
message: Unauthorized
|
||||
version: 1
|
||||
@@ -1,749 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://sso.garmin.com/sso/embed?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso
|
||||
response:
|
||||
body:
|
||||
string: "<html>\n\t<head>\n\t <title>GAuth Embedded Version</title>\n\t <meta
|
||||
http-equiv=\"X-UA-Compatible\" content=\"IE=edge;\" />\n\t <style type=\"text/css\">\n\t
|
||||
\ \t#gauth-widget {border: none !important;}\n\t </style>\n\t</head>\n\t<body>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.7.1/jquery.min.js?20210319\"></script>\n\n<div>\n\t<pre>\n\t<span>ERROR:
|
||||
clientId parameter must be specified!!!</span>\n\n\t<span >Usage: https://sso.garmin.com/sso/embed?clientId=<clientId>&locale=<locale>...</span>\n\n\tRequest
|
||||
parameter configuration options:\n\n\tNAME REQ VALUES
|
||||
\ DESCRIPTION\n\t------------------
|
||||
\ --- -------------------------------------------------------
|
||||
\ ---------------------------------------------------------------------------------------------------\n\tclientId
|
||||
\ Yes \"MY_GARMIN\"/\"BUY_GARMIN\"/\"FLY_GARMIN\"/ Client
|
||||
identifier for your web application\n\t \"RMA\"/\"GarminConnect\"/\"OpenCaching\"/etc\n\tlocale
|
||||
\ Yes \"en\", \"bg\", \"cs\", \"da\", \"de\", \"es\",
|
||||
\"el\", \"fr\", \"hr\", User's current locale, to display the GAuth login
|
||||
widget internationalized properly.\n\t \"in\",
|
||||
\"it\", \"iw\", \"hu\", \"ms\", \"nb\", \"nl\", \"no\", \"pl\", (All the
|
||||
currently supported locales are listed in the Values section.)\n\t \"pt\",
|
||||
\"pt_BR\", \"ru\", \"sk\", \"sl\", \"fi\", \"sv\", \"tr\",\n\t \"uk\",
|
||||
\"th\", \"ja\", \"ko\", \"zh_TW\", \"zh\", \"vi_VN\"\n\tcssUrl No
|
||||
\ Absolute URL to custom CSS file. Use custom CSS
|
||||
styling for the GAuth login widget.\n\treauth No
|
||||
\ true/false (Default value is false) Specify true if
|
||||
you want to ensure that the GAuth login widget shows up,\n\t even
|
||||
if the SSO infrastructure remembers the user and would immediately log them
|
||||
in.\n\t This
|
||||
is useful if you know a user is logged on, but want a different user to be
|
||||
allowed to logon.\n\tinitialFocus No true/false (Default
|
||||
value is true) If you don't want the GAuth login widget
|
||||
to autofocus in it's \"Email or Username\" field upon initial loading,\n\t
|
||||
\ then
|
||||
specify this option and set it to false.\n\trememberMeShown No
|
||||
\ true/false (Default value is false) Whether the \"Remember
|
||||
Me\" check box is shown in the GAuth login widget.\n\trememberMeChecked No
|
||||
\ true/false (Default value is false) Whether the \"Remember
|
||||
Me\" check box feature is checked by default.\n\tcreateAccountShown No
|
||||
\ true/false (Default value is true) Whether the \"Don't
|
||||
have an account? Create One\" link is shown in the GAuth login widget.\n\tsocialEnabled
|
||||
\ No true/false (Default value is false) If
|
||||
set to false, do not show any social sign in elements or allow social sign
|
||||
ins.\n\tlockToEmailAddress No Email address to pre-load and
|
||||
lock. If specified, the specified email address will
|
||||
be pre-loaded in the main \"Email\" field in the SSO login form,\n\t as
|
||||
well as in in the \"Email Address\" field in the \"Forgot Password?\" password
|
||||
reset form,\n\t and
|
||||
both fields will be disabled so they can't be changed.\n\t (If
|
||||
for some reason you want to force re-authentications for a known customer
|
||||
account, you can make use of this option.)\n\topenCreateAccount No
|
||||
\ true/false (Default value is false) If set to true,
|
||||
immediately display the the account creation screen.\n\tdisplayNameShown No
|
||||
\ true/false (Default value is false) If set to true,
|
||||
show the \"Display Name\" field on the account creation screen, to allow the
|
||||
user\n\t to
|
||||
set their central MyGarmin display name upon account creation.\n\tglobalOptInShown
|
||||
\ No true/false (Default value is false) Whether
|
||||
the \"Global Opt-In\" check box is shown on the create account & create social
|
||||
account screens.\n\t If
|
||||
set to true these screens will show a \"Sign Up For Email\" check box with
|
||||
accompanying text\n\t \"I
|
||||
would also like to receive email about promotions and new products.\"\n\t
|
||||
\ If
|
||||
checked, the Customer 2.0 account that is created will have it's global opt-in
|
||||
flag set to true,\n\t and
|
||||
Garmin email communications will be allowed.\n\tglobalOptInChecked No
|
||||
\ true/false (Default value is false) Whether the \"Global
|
||||
Opt-In\" check box is checked by default.\n\tconsumeServiceTicket No
|
||||
\ true/false (Default value is true) IF you don't specify
|
||||
a redirectAfterAccountLoginUrl AND you set this to false, the GAuth login
|
||||
widget\n\t will
|
||||
NOT consume the service ticket assigned and will not seamlessly log you into
|
||||
your webapp.\n\t It
|
||||
will send a SUCCESS JavaScript event with the service ticket and service url
|
||||
you can take\n\t and
|
||||
explicitly validate against the SSO infrastructure yourself.\n\t (By
|
||||
using casClient's SingleSignOnUtils.authenticateServiceTicket() utility method,\n\t
|
||||
\ or
|
||||
calling web service customerWebServices_v1.2 AccountManagementService.authenticateServiceTicket().)\n\tmobile
|
||||
\ No true/false (Default value is false) Setting
|
||||
to true will cause mobile friendly views to be shown instead of the tradition
|
||||
screens.\n\ttermsOfUseUrl No Absolute URL to your custom
|
||||
terms of use URL. If not specified, defaults to http://www.garmin.com/terms\n\tprivacyStatementUrl
|
||||
\ No Absolute URL to your custom privacy statement URL. If
|
||||
not specified, defaults to http://www.garmin.com/privacy\n\tproductSupportUrl
|
||||
\ No Absolute URL to your custom product support URL. If
|
||||
not specified, defaults to http://www.garmin.com/us/support/contact\n\tgenerateExtraServiceTicket
|
||||
\ No true/false (Default value is false) If set
|
||||
to true, generate an extra unconsumed service ticket.\n\t\t (The
|
||||
service ticket validation response will include the extra service ticket.)\n\tgenerateTwoExtraServiceTickets
|
||||
\ No true/false (Default value is false) If set to true,
|
||||
generate two extra unconsumed service tickets.\n\t\t\t\t\t\t\t\t\t \t\t\t
|
||||
\ (The service ticket validation response will include the extra service
|
||||
tickets.)\n\tgenerateNoServiceTicket No true/false (Default value
|
||||
is false) If you don't want SSO to generate a service
|
||||
ticket at all when logging in to the GAuth login widget.\n (Useful
|
||||
when allowing logins to static sites that are not SSO enabled and can't consume
|
||||
the service ticket.)\n\tconnectLegalTerms No true/false (Default
|
||||
value is false) Whether to show the connectLegalTerms
|
||||
on the create account page\n\tshowTermsOfUse No true/false
|
||||
(Default value is false) Whether to show the showTermsOfUse
|
||||
on the create account page\n\tshowPrivacyPolicy No true/false
|
||||
(Default value is false) Whether to show the showPrivacyPolicy
|
||||
on the create account page\n\tshowConnectLegalAge No true/false
|
||||
(Default value is false) Whether to show the showConnectLegalAge
|
||||
on the create account page\n\tlocationPromptShown No true/false
|
||||
(Default value is false) If set to true, ask the customer
|
||||
during account creation to verify their country of residence.\n\tshowPassword
|
||||
\ No true/false (Default value is true) If
|
||||
set to false, mobile version for createAccount and login screens would hide
|
||||
the password\n\tuseCustomHeader No true/false (Default value
|
||||
is false) If set to true, the \"Sign in\" text will be
|
||||
replaced by custom text. Contact CDS team to set the i18n text for your client
|
||||
id.\n\tmfaRequired No true/false (Default value is false)
|
||||
\ Require multi factor authentication for all authenticating
|
||||
users.\n\tperformMFACheck No true/false (Default value is
|
||||
false) If set to true, ask the logged in user to pass
|
||||
a multi factor authentication check. (Only valid for an already logged in
|
||||
user.)\n\trememberMyBrowserShown No true/false (Default value is
|
||||
false) Whether the \"Remember My Browser\" check box
|
||||
is shown in the GAuth login widget MFA verification screen.\n\trememberMyBrowserChecked
|
||||
\ No true/false (Default value is false) Whether
|
||||
the \"Remember My Browser\" check box feature is checked by default.\n\tconsentTypeIds\t\t\t\t\tNo\tconsent_types
|
||||
ids\t\t \t\t\t\t\t\t\t\t multiple consent types ids can be passed as consentTypeIds=type1&consentTypeIds=type2\n\t</pre>\n</div>\n\n\n\t<script>(function(){function
|
||||
c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML=\"window.__CF$cv$params={r:'949c83cf2bfb5e42',t:'MTc0ODkyNTY1Mi4wMDAwMDA='};var
|
||||
a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);\";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var
|
||||
a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else
|
||||
if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var
|
||||
e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-RAY:
|
||||
- 949c83cf2bfb5e42-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Tue, 03 Jun 2025 04:40:52 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=cwd6V1kar7GXC7ImUBfvrwg3vgZw4sMdraKN0bkZjRt%2Bsu4gSDU%2Bv0N%2BSUhVzY7ZkTgMTuIkEmTRl7ywQ5Z%2FAD3BUh03xdXX%2B2qCgU0plnOrl93fBAlMcDC9U%2FMRzoHW"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- __cf_bm=SANITIZED; path=SANITIZED; expires=SANITIZED; domain=SANITIZED; HttpOnly;
|
||||
Secure; SameSite=SANITIZED
|
||||
- __cflb=SANITIZED; SameSite=SANITIZED; Secure; path=SANITIZED; expires=SANITIZED;
|
||||
HttpOnly
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_Olathe:3
|
||||
X-B3-Traceid:
|
||||
- 85cea212845648ad7fbb7b5ad97acb70
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- 85cea212-8456-48ad-7fbb-7b5ad97acb70
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
__cflb=SANITIZED; __cf_bm=SANITIZED; _cfuvid=SANITIZED
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/embed?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso
|
||||
method: GET
|
||||
uri: https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: "<!DOCTYPE html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n <meta
|
||||
http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <meta
|
||||
name=\"viewport\" content=\"width=device-width\" />\n <meta http-equiv=\"X-UA-Compatible\"
|
||||
content=\"IE=edge;\" />\n <title>GARMIN Authentication Application</title>\n
|
||||
\ <link href=\"/sso/css/GAuth.css?20210406\" rel=\"stylesheet\" type=\"text/css\"
|
||||
media=\"all\" />\n\n\t <link rel=\"stylesheet\" href=\"\"/>\n\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.7.1/jquery.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\">jQuery.noConflict();</script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery-validate/1.16.0/jquery.validate.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/jsUtils.js?20210406\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/json2.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/consoleUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/postmessage.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/popupWindow.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/base.js?20231020\"></script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/gigyaUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/login.js?20211102\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/reCaptchaUtil.js?20230706\"></script>\n\n
|
||||
\ <script>\n var recaptchaSiteKey = null;\n var
|
||||
reCaptchaURL = \"\\\\\\/sso\\\\\\/reCaptcha?id=gauth-widget\\u0026embedWidget=true\\u0026gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\";\n
|
||||
\ var isRecaptchaEnabled = null;\n var recaptchaToken
|
||||
= null; \n </script>\n <script type=\"text/javascript\">\n
|
||||
\ var parent_url = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n
|
||||
\ var status \t\t\t= \"\";\n\t\t\tvar result = \"\";\n\t\t\tvar
|
||||
clientId\t\t= '';\n\t\t\tvar embedWidget \t= true;\n\t\t\tvar isUsernameDefined
|
||||
= (false == true) || (false == true);\n\n // Gigya callback to
|
||||
SocialSignInController for brand new social network users redirects to this
|
||||
page\n // to popup Create or Link Social Account page, but has
|
||||
a possibly mangled source parameter\n // where \"?\" is set as
|
||||
\"<QM>\", so translate it back to \"?\" here.\n parent_url = parent_url.replace('<QM>',
|
||||
'?');\n var parent_scheme = parent_url.substring(0, parent_url.indexOf(\"://\"));\n
|
||||
\ var parent_hostname = parent_url.substring(parent_scheme.length
|
||||
+ 3, parent_url.length);\n if (parent_hostname.indexOf(\"/\") !=
|
||||
-1) {\n parent_hostname = parent_hostname.substring(0, parent_hostname.indexOf(\"/\"));\n
|
||||
\ }\n var parentHost \t = parent_scheme + \"://\"
|
||||
+ parent_hostname;\n\t\t\tvar createAccountConfigURL = '\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed';\n
|
||||
\ var socialConfigURL = 'https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed';\n
|
||||
\ var gigyaURL = \"https://cdns.gigya.com/js/gigya.js?apiKey=2_R3ZGY8Bqlwwk3_63knoD9wA_m-Y19mAgW61bF_s5k9gymYnMEAtMrJiF5MjF-U7B\";\n\n
|
||||
\ if (createAccountConfigURL.indexOf('%253A%252F%252F') != -1) {\n
|
||||
\ \tcreateAccountConfigURL = decodeURIComponent(createAccountConfigURL);\n
|
||||
\ }\n consoleInfo('signin.html embedWidget: true, createAccountConfigURL:
|
||||
\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed,
|
||||
socialEnabled: true, gigyaSupported: true, socialConfigURL(): https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed');\n\n
|
||||
\ if (socialConfigURL.indexOf('%3A%2F%2F') != -1) {\n \tsocialConfigURL
|
||||
= decodeURIComponent(socialConfigURL);\n }\n\n if( status
|
||||
!= null && status != ''){\n \tsend({'status':status});\n }\n\n
|
||||
\ jQuery(document).ready( function(){\n\n\n consoleInfo(\"signin.html:
|
||||
setting field validation rules...\");\n\n jQuery(\"#username\").rules(\"add\",{\n
|
||||
\ required: true,\n messages: {\n required:
|
||||
\ \"Email is required.\"\n }});\n\n jQuery(\"#password\").rules(\"add\",
|
||||
{\n required: true,\n messages: {\n
|
||||
\ required: \"Password is required.\"\n }\n
|
||||
\ });\n\n consoleInfo(\"signin.html: done setting
|
||||
field validation rules...\");\n\n });\n\n XD.receiveMessage(function(m){\n
|
||||
\ consoleInfo(\"signin.html: \" + m.data + \" received on \"
|
||||
+ window.location.host);\n if (m && m.data) {\n var
|
||||
md = m.data;\n if (typeof(md) === 'string') {\n md
|
||||
= JSON.parse(m.data);\n }\n if (md.setUsername)
|
||||
{\n consoleInfo(\"signin.html: Setting username \\\"\"
|
||||
+ md.username + \"\\\"...\");\n jQuery(\"#signInWithDiffLink\").click();
|
||||
// Ensure the normal login form is shown.\n jQuery(\"#username\").val(md.username);\n
|
||||
\ jQuery(\"#password\").focus();\n }\n
|
||||
\ }\n }, parentHost);\n </script>\n </head>\n
|
||||
\ <body>\n\n <!-- begin GAuth component -->\n <div id=\"GAuth-component\">\n
|
||||
\ <!-- begin login component-->\n <div id=\"login-component\"
|
||||
class=\"blueForm-basic\">\n <input type=\"hidden\" id=\"queryString\"
|
||||
value=\"id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\"
|
||||
/>\n\t \t <input type=\"hidden\" id=\"contextPath\" value=\"/sso\" />\n
|
||||
\ <!-- begin login form -->\n <div id=\"login-state-default\">\n
|
||||
\ <h2>Sign In</h2>\n\n <form method=\"post\"
|
||||
id=\"login-form\">\n\n <div class=\"form-alert\">\n\t\t\t\t\t\t\t\n
|
||||
\ \n \n \n
|
||||
\ \n \n \n\n
|
||||
\ <div id=\"username-error\" style=\"display:none;\"></div>\n
|
||||
\ <div id=\"password-error\" style=\"display:none;\"></div>\n
|
||||
\ </div>\n <div class=\"textfield\">\n\t\t\t\t\t\t\t<label
|
||||
for=\"username\">Email</label>\n \t\t<!-- If the
|
||||
lockToEmailAddress parameter is specified then we want to mark the field as
|
||||
readonly,\n \t\tpreload the email address, and disable
|
||||
the other input so that null isn't sent to the server. We'll\n \t\talso
|
||||
style the field to have a darker grey background and disable the mouse pointer\n
|
||||
\ \t\t -->\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t<!--
|
||||
If the lockToEmailAddress parameter is NOT specified then keep the existing
|
||||
functionality and disable the readonly input field\n\t\t\t\t\t\t\t -->\n\t\t\t\t\t\t\t
|
||||
\ <input class=\"login_email\" name=\"username\" id=\"username\" value=\"\"
|
||||
type=\"email\" spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\"/>\n\n
|
||||
\ </div>\n\n <div class=\"textfield\">\n
|
||||
\ <label for=\"password\">Password</label>\n <a
|
||||
id=\"loginforgotpassword\" class=\"login-forgot-password\" style=\"cursor:pointer\">(Forgot?)</a>\n
|
||||
\ <input type=\"password\" name=\"password\" id=\"password\"
|
||||
spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\" />\n <strong
|
||||
id=\"capslock-warning\" class=\"information\" title=\"Caps lock is on.\" style=\"display:
|
||||
none;\">Caps lock is on.</strong>\n\t\t\t\t\t </div>\n <input
|
||||
type=\"hidden\" name=\"embed\" value=\"true\"/>\n <input
|
||||
type=\"hidden\" name=\"_csrf\" value=\"90280BE13709DE2C0CF38CAB2A77E3FC82F62894F2396D07630AD246706B197735797D02C4592A6D5AB3B8BF1F3B80460522\"
|
||||
/>\n <button type=\"submit\" id=\"login-btn-signin\"
|
||||
class=\"btn1\" accesskey=\"l\">Sign In</button>\n \n\n\n
|
||||
\ <!-- The existence of the \"rememberme\" parameter
|
||||
at all will remember the user! -->\n \n\n </form>\n
|
||||
\ </div>\n <!-- end login form -->\n\n <!--
|
||||
begin Create Account message -->\n\t <div id=\"login-create-account\">\n\t
|
||||
\ \n\t </div>\n\t <!-- end Create Account
|
||||
message -->\n\n\t <!-- begin Social Sign In component -->\n\t <div
|
||||
id=\"SSI-component\">\n \n\n\t\t\t\t\t\n\t </div>\n\t
|
||||
\ <!-- end Social Sign In component -->\n <div class=\"clearfix\"></div>
|
||||
<!-- Ensure that GAuth-component div's height is computed correctly. -->\n
|
||||
\ </div>\n <!-- end login component-->\n\n\t\t</div>\n\t\t<!--
|
||||
end GAuth component -->\n\n <script type=\"text/javascript\">\n jQuery(document).ready(function(){\n
|
||||
\ \tresizePageOnLoad(jQuery(\"#GAuth-component\").height());\n\n\t\t
|
||||
\ if(isUsernameDefined == true){\n\t\t // If the user's login
|
||||
just failed, redisplay the email/username specified, and focus them in the
|
||||
password field.\n\t\t jQuery(\"#password\").focus();\n\t\t }
|
||||
else if(false == true && result != \"PASSWORD_RESET_RESULT\"){\n //
|
||||
Otherwise focus them in the username field of the login dialog.\n jQuery(\"#username\").focus();\n
|
||||
\ }\n\n // Scroll to top of iframe to fix problem
|
||||
where Firefox 3.0-3.6 browsers initially show top of iframe cutoff.\n location.href=\"#\";\n\n
|
||||
\ if(!embedWidget){\n \tjQuery('.createAccountLink').click(function(){\n\t
|
||||
\ send({'openLiteBox':'createAccountLink', 'popupUrl': createAccountConfigURL,
|
||||
'popupTitle':'Create An Account', 'clientId':clientId});\n\t });\n
|
||||
\ }\n });\n </script>\n <script>(function(){function
|
||||
c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML=\"window.__CF$cv$params={r:'949c83d17d414f14',t:'MTc0ODkyNTY1Mi4wMDAwMDA='};var
|
||||
a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);\";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var
|
||||
a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else
|
||||
if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var
|
||||
e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-Ray:
|
||||
- 949c83d17d414f14-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Tue, 03 Jun 2025 04:40:52 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=REffANT2%2FfOZY9xYp%2FXinxsCOsc73u6TBWc0qVetJyK9oQhy63N6Qk3fNr5TDiEV9JM9RIKw5uZhoVeBr7vDZK1f0UsNdTsjHdr19V0Lnt%2FCqbU6Y3MTWpcTaQYMqUIo"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- SESSION=SANITIZED; Path=SANITIZED; Secure; HttpOnly
|
||||
- __VCAP_ID__=SANITIZED; Path=SANITIZED; HttpOnly; Secure
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_Olathe:6
|
||||
X-B3-Traceid:
|
||||
- 77e60c0ac1d641c074820aac41fbde80
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- 77e60c0a-c1d6-41c0-7482-0aac41fbde80
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: username=SANITIZED&password=SANITIZED&embed=true&_csrf=90280BE13709DE2C0CF38CAB2A77E3FC82F62894F2396D07630AD246706B197735797D02C4592A6D5AB3B8BF1F3B80460522
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '177'
|
||||
Content-Type:
|
||||
- application/x-www-form-urlencoded
|
||||
Cookie:
|
||||
- SESSION=SANITIZED; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
__cflb=SANITIZED; __VCAP_ID__=SANITIZED; __cf_bm=SANITIZED; _cfuvid=SANITIZED
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: POST
|
||||
uri: https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: ''
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-Ray:
|
||||
- 949c83d32cf657bd-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Length:
|
||||
- '0'
|
||||
Date:
|
||||
- Tue, 03 Jun 2025 04:40:54 GMT
|
||||
Location:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=8rQsZTg41dTwDgWNQriYHPcbY3UG6NQ0v%2FN6zaizxXzpDFLJALfe7s%2BopIWHB0dvU9WeEEUreQPI2Wlkgz2Gp6z9fx51UvQZtS3N2hIGKyEW7QNno8eCyuMyHYGXjJOx"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- __cfruid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_Olathe:6
|
||||
X-B3-Traceid:
|
||||
- 1da874cc48894fdf4e1ac9d9e8e269c8
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- 1da874cc-4889-4fdf-4e1a-c9d9e8e269c8
|
||||
status:
|
||||
code: 302
|
||||
message: Found
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- SESSION=SANITIZED; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
__cflb=SANITIZED; __VCAP_ID__=SANITIZED; __cf_bm=SANITIZED; _cfuvid=SANITIZED;
|
||||
__cfruid=SANITIZED
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: "<!DOCTYPE html>\n<html lang=\"en\" class=\"no-js\">\n\n<head>\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.7.1/jquery.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\">jQuery.noConflict();</script>\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery-validate/1.16.0/jquery.validate.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/base.js?20231020\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/jsUtils.js?20210406\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/json2.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/postmessage.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/consoleUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/setupMfaRequiredView.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/enterMfaCode.js?20230127\"></script>\n
|
||||
\ <script type=\"text/javascript\">\n var embedWidget = \"true\";\n
|
||||
\ if (embedWidget == \"\") {\n embedWidget = \"\";\n }\n
|
||||
\ embedWidget = (embedWidget == \"true\");\n var parent_url =
|
||||
\"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n window.onload = function()
|
||||
{\n ifrememberMyBrowserChecked();\n };\n\n jQuery(document).ready(
|
||||
function() {\n if (!embedWidget) {\n send({'gauthHeight':
|
||||
jQuery(\"#GAuth-component\").height()});\n }\n jQuery(\"#mfa-verification-code-submit\").click(function(){\n
|
||||
\ if (!validateMfaCodeAndPrivacyConsents()){\n return
|
||||
false;\n }\n jQuery('#submit-mfa-verification-code-form').submit();\n
|
||||
\ return false;\n });\n });\n var customerGuid
|
||||
= \"0690cc1d-d23d-4412-b027-80fd4ed1c0f6\";\n var mfaMethod = \"email\";\n
|
||||
\ var locale = \"\";\n var clientId = \"\";\n var codeSentTo
|
||||
= \"mt*****@gmail.com\";\n </script>\n <meta charset=\"utf-8\">\n <title>Enter
|
||||
MFA code for login</title>\n <meta name=\"description\" content=\"\">\n
|
||||
\ <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n
|
||||
\ <meta http-equiv=\"cleartype\" content=\"on\">\n <meta http-equiv=\"X-UA-Compatible\"
|
||||
content=\"IE=edge;\" />\n <link href=\"/sso/css/GAuth.css?20170505\" rel=\"stylesheet\"
|
||||
type=\"text/css\" media=\"all\" />\n <link rel=\"stylesheet\" href=\"\"
|
||||
/>\n</head>\n\n<body>\n <div id=\"GAuth-component\">\n <h2 id=\"enter-mfa-code-h2\">Enter
|
||||
security code</h2>\n <input type=\"hidden\" id=\"queryString\" value=\"id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\"
|
||||
/>\n <input type=\"hidden\" id=\"contextPath\" value=\"/sso\" />\n\n
|
||||
\ <div id=\"login-component\" class=\"blueForm-basic\">\n <div
|
||||
id=\"login-state-verifymfa\">\n <td>\n \n
|
||||
\ <span >Code sent to <b>mt*****@gmail.com</b></span>\n
|
||||
\ </td>\n <form id=\"submit-mfa-verification-code-form\"
|
||||
name=\"submit-mfa-verification-code-form\" method=\"post\" novalidate=\"novalidate\">\n
|
||||
\ <div class=\"blueForm-v2\">\n <div
|
||||
class=\"form-alert\">\n <div id=\"genericError\"
|
||||
class=\"error\" hidden>An unexpected error has occurred.</div>\n <div
|
||||
id=\"codeSentAttention\" class=\"attention\" hidden>A new code has been sent.
|
||||
You can request another code in 30 seconds.</div>\n \n
|
||||
\ \n <div id=\"maxLimit\"
|
||||
class=\"error\" hidden=\"hidden\">You have reached the maximum amount of codes
|
||||
requested. Please use a code you've received or wait 24 hours and try
|
||||
again.</div>\n \n </div>\n
|
||||
\ <div class=\"formTextField\">\n <div
|
||||
class=\"mfaFormLabel\">\n <label>\n <span>Security
|
||||
code</span>\n <br/>\n <input
|
||||
type=\"number\" pattern=\"[0-9]*\" inputmode=\"numeric\" maxlength=\"6\" id=\"mfa-code\"
|
||||
name=\"mfa-code\" autofocus oninput=\"validateMfaCodeAndPrivacyConsents()\"/>\n
|
||||
\ </label>\n </div>\n
|
||||
\ </div>\n <br><br>\n <div>\n
|
||||
\ <a href=\"https://support.garmin.com/en-US/?faq=uGHS8ZqOIhA0usBzBMdJu7\"
|
||||
target=\"_blank\" id=\"havingTrouble\">Get help</a><br>\n </div>\n
|
||||
\ <div id=\"requestNewCodeWrapper\" class=\"requestNewCode\">\n
|
||||
\ <a href=\"#\" id=\"newCode\">Request a new code</a>\n
|
||||
\ </div>\n \n \n
|
||||
\ <br>\n \n <br/>\n
|
||||
\ <button type=\"submit\" id=\"mfa-verification-code-submit\"
|
||||
class=\"btn1\">Next</button>\n </div>\n <input
|
||||
type=\"hidden\" name=\"embed\" value=\"true\"/>\n <input
|
||||
type=\"hidden\" name=\"_csrf\" value=\"9AF199177EE70FB2511C2DE25FE2780DEF8327EDCA5AB81C391FAF6E419E83EDF20E1EE31B76E282D8AA46124E3DC5EB1391\"
|
||||
/>\n <input type=\"hidden\" name=\"fromPage\" value=\"setupEnterMfaCode\"/>\n
|
||||
\ <br/>\n </form>\n </div>\n <div
|
||||
class=\"clearfix\"></div> <!-- Ensure that GAuth-component div's height is
|
||||
computed correctly. -->\n </div>\n </div>\n <script type=\"text/javascript\">\n
|
||||
\ resizePageOnLoad(jQuery(\"#GAuth-component\").height());\n </script>\n<script>(function(){function
|
||||
c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML=\"window.__CF$cv$params={r:'949c83da2a5ac1ca',t:'MTc0ODkyNTY1NC4wMDAwMDA='};var
|
||||
a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);\";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var
|
||||
a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else
|
||||
if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var
|
||||
e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>\n</html>"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-RAY:
|
||||
- 949c83da2a5ac1ca-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Tue, 03 Jun 2025 04:40:54 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=BrVkK9BHKPEC700UIxYqeYMAufPXrsMtXb56Z5naqivj9pfj%2FKyqvweC0oLp4v4n%2BecNLLGdP4o5WUnke2Iu62u0i0gzh9hqR49I8mYeEw6ABEfR8ZFJbx0waSuNNous"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_Olathe:6
|
||||
X-B3-Traceid:
|
||||
- acd069da786e436a7d98ba4e5220bcfc
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- acd069da-786e-436a-7d98-ba4e5220bcfc
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: mfa-code=123456&embed=true&_csrf=9AF199177EE70FB2511C2DE25FE2780DEF8327EDCA5AB81C391FAF6E419E83EDF20E1EE31B76E282D8AA46124E3DC5EB1391&fromPage=setupEnterMfaCode
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '160'
|
||||
Content-Type:
|
||||
- application/x-www-form-urlencoded
|
||||
Cookie:
|
||||
- SESSION=SANITIZED; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
__cflb=SANITIZED; __VCAP_ID__=SANITIZED; __cf_bm=SANITIZED; _cfuvid=SANITIZED;
|
||||
__cfruid=SANITIZED
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: POST
|
||||
uri: https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: "<!DOCTYPE html>\n<html lang=\"en\" class=\"no-js\">\n\n<head>\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.7.1/jquery.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\">jQuery.noConflict();</script>\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery-validate/1.16.0/jquery.validate.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/base.js?20231020\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/jsUtils.js?20210406\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/json2.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/postmessage.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/consoleUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/setupMfaRequiredView.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/enterMfaCode.js?20230127\"></script>\n
|
||||
\ <script type=\"text/javascript\">\n var embedWidget = \"true\";\n
|
||||
\ if (embedWidget == \"\") {\n embedWidget = \"\";\n }\n
|
||||
\ embedWidget = (embedWidget == \"true\");\n var parent_url =
|
||||
\"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n window.onload = function()
|
||||
{\n ifrememberMyBrowserChecked();\n };\n\n jQuery(document).ready(
|
||||
function() {\n if (!embedWidget) {\n send({'gauthHeight':
|
||||
jQuery(\"#GAuth-component\").height()});\n }\n jQuery(\"#mfa-verification-code-submit\").click(function(){\n
|
||||
\ if (!validateMfaCodeAndPrivacyConsents()){\n return
|
||||
false;\n }\n jQuery('#submit-mfa-verification-code-form').submit();\n
|
||||
\ return false;\n });\n });\n var customerGuid
|
||||
= \"0690cc1d-d23d-4412-b027-80fd4ed1c0f6\";\n var mfaMethod = \"email\";\n
|
||||
\ var locale = \"\";\n var clientId = \"\";\n var codeSentTo
|
||||
= \"mt*****@gmail.com\";\n </script>\n <meta charset=\"utf-8\">\n <title>Enter
|
||||
MFA code for login</title>\n <meta name=\"description\" content=\"\">\n
|
||||
\ <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n
|
||||
\ <meta http-equiv=\"cleartype\" content=\"on\">\n <meta http-equiv=\"X-UA-Compatible\"
|
||||
content=\"IE=edge;\" />\n <link href=\"/sso/css/GAuth.css?20170505\" rel=\"stylesheet\"
|
||||
type=\"text/css\" media=\"all\" />\n <link rel=\"stylesheet\" href=\"\"
|
||||
/>\n</head>\n\n<body>\n <div id=\"GAuth-component\">\n <h2 id=\"enter-mfa-code-h2\">Enter
|
||||
security code</h2>\n <input type=\"hidden\" id=\"queryString\" value=\"id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\"
|
||||
/>\n <input type=\"hidden\" id=\"contextPath\" value=\"/sso\" />\n\n
|
||||
\ <div id=\"login-component\" class=\"blueForm-basic\">\n <div
|
||||
id=\"login-state-verifymfa\">\n <td>\n \n
|
||||
\ <span >Code sent to <b>mt*****@gmail.com</b></span>\n
|
||||
\ </td>\n <form id=\"submit-mfa-verification-code-form\"
|
||||
name=\"submit-mfa-verification-code-form\" method=\"post\" novalidate=\"novalidate\">\n
|
||||
\ <div class=\"blueForm-v2\">\n <div
|
||||
class=\"form-alert\">\n <div id=\"genericError\"
|
||||
class=\"error\" hidden>An unexpected error has occurred.</div>\n <div
|
||||
id=\"codeSentAttention\" class=\"attention\" hidden>A new code has been sent.
|
||||
You can request another code in 30 seconds.</div>\n <div
|
||||
id=\"invalidCode\" class=\"error\">Invalid code. Please enter a valid code.</div>\n
|
||||
\ \n <div id=\"maxLimit\"
|
||||
class=\"error\" hidden=\"hidden\">You have reached the maximum amount of codes
|
||||
requested. Please use a code you've received or wait 24 hours and try
|
||||
again.</div>\n \n </div>\n
|
||||
\ <div class=\"formTextField\">\n <div
|
||||
class=\"mfaFormLabel\">\n <label>\n <span>Security
|
||||
code</span>\n <br/>\n <input
|
||||
type=\"number\" pattern=\"[0-9]*\" inputmode=\"numeric\" maxlength=\"6\" id=\"mfa-code\"
|
||||
name=\"mfa-code\" autofocus oninput=\"validateMfaCodeAndPrivacyConsents()\"/>\n
|
||||
\ </label>\n </div>\n
|
||||
\ </div>\n <br><br>\n <div>\n
|
||||
\ <a href=\"https://support.garmin.com/en-US/?faq=uGHS8ZqOIhA0usBzBMdJu7\"
|
||||
target=\"_blank\" id=\"havingTrouble\">Get help</a><br>\n </div>\n
|
||||
\ <div id=\"requestNewCodeWrapper\" class=\"requestNewCode\">\n
|
||||
\ <a href=\"#\" id=\"newCode\">Request a new code</a>\n
|
||||
\ </div>\n \n \n
|
||||
\ <br>\n \n <br/>\n
|
||||
\ <button type=\"submit\" id=\"mfa-verification-code-submit\"
|
||||
class=\"btn1\">Next</button>\n </div>\n <input
|
||||
type=\"hidden\" name=\"embed\" value=\"true\"/>\n <input
|
||||
type=\"hidden\" name=\"_csrf\" value=\"\" />\n <input
|
||||
type=\"hidden\" name=\"fromPage\" value=\"setupEnterMfaCode\"/>\n
|
||||
\ <br/>\n </form>\n </div>\n <div
|
||||
class=\"clearfix\"></div> <!-- Ensure that GAuth-component div's height is
|
||||
computed correctly. -->\n </div>\n </div>\n <script type=\"text/javascript\">\n
|
||||
\ resizePageOnLoad(jQuery(\"#GAuth-component\").height());\n </script>\n<script>(function(){function
|
||||
c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML=\"window.__CF$cv$params={r:'949c83dc9aa555c3',t:'MTc0ODkyNTY1NC4wMDAwMDA='};var
|
||||
a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);\";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var
|
||||
a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else
|
||||
if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var
|
||||
e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>\n</html>"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-RAY:
|
||||
- 949c83dc9aa555c3-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Tue, 03 Jun 2025 04:40:54 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=WVjXMWAY7m%2FICrofTUaszDZoZ1kIv1%2BQTcx49UDCpdhESBjLNt9LucYPatIj%2BHOhRkqNPuM%2F65Tz1kTrR4naiCX0yEAOcMcEAh1yxyiX%2BlU7qvovsvWodipj8YHB19mH"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_Olathe:6
|
||||
X-B3-Traceid:
|
||||
- 104ac62c483244cf73fb9266e97d22bb
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- 104ac62c-4832-44cf-73fb-9266e97d22bb
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,760 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://sso.garmin.com/sso/embed?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso
|
||||
response:
|
||||
body:
|
||||
string: "<html>\n\t<head>\n\t <title>GAuth Embedded Version</title>\n\t <meta
|
||||
http-equiv=\"X-UA-Compatible\" content=\"IE=edge;\" />\n\t <style type=\"text/css\">\n\t
|
||||
\ \t#gauth-widget {border: none !important;}\n\t </style>\n\t</head>\n\t<body>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.1.1/jquery.min.js?20210319\"></script>\n\n<div>\n\t<pre>\n\t<span>ERROR:
|
||||
clientId parameter must be specified!!!</span>\n\n\t<span >Usage: https://sso.garmin.com/sso/embed?clientId=<clientId>&locale=<locale>...</span>\n\n\tRequest
|
||||
parameter configuration options:\n\n\tNAME REQ VALUES
|
||||
\ DESCRIPTION\n\t------------------
|
||||
\ --- -------------------------------------------------------
|
||||
\ ---------------------------------------------------------------------------------------------------\n\tclientId
|
||||
\ Yes \"MY_GARMIN\"/\"BUY_GARMIN\"/\"FLY_GARMIN\"/ Client
|
||||
identifier for your web application\n\t \"RMA\"/\"GarminConnect\"/\"OpenCaching\"/etc\n\tlocale
|
||||
\ Yes \"en\", \"bg\", \"cs\", \"da\", \"de\", \"es\",
|
||||
\"el\", \"fr\", \"hr\", User's current locale, to display the GAuth login
|
||||
widget internationalized properly.\n\t \"in\",
|
||||
\"it\", \"iw\", \"hu\", \"ms\", \"nb\", \"nl\", \"no\", \"pl\", (All the
|
||||
currently supported locales are listed in the Values section.)\n\t \"pt\",
|
||||
\"pt_BR\", \"ru\", \"sk\", \"sl\", \"fi\", \"sv\", \"tr\",\n\t \"uk\",
|
||||
\"th\", \"ja\", \"ko\", \"zh_TW\", \"zh\", \"vi_VN\"\n\tcssUrl No
|
||||
\ Absolute URL to custom CSS file. Use custom CSS
|
||||
styling for the GAuth login widget.\n\treauth No
|
||||
\ true/false (Default value is false) Specify true if
|
||||
you want to ensure that the GAuth login widget shows up,\n\t even
|
||||
if the SSO infrastructure remembers the user and would immediately log them
|
||||
in.\n\t This
|
||||
is useful if you know a user is logged on, but want a different user to be
|
||||
allowed to logon.\n\tinitialFocus No true/false (Default
|
||||
value is true) If you don't want the GAuth login widget
|
||||
to autofocus in it's \"Email or Username\" field upon initial loading,\n\t
|
||||
\ then
|
||||
specify this option and set it to false.\n\trememberMeShown No
|
||||
\ true/false (Default value is false) Whether the \"Remember
|
||||
Me\" check box is shown in the GAuth login widget.\n\trememberMeChecked No
|
||||
\ true/false (Default value is false) Whether the \"Remember
|
||||
Me\" check box feature is checked by default.\n\tcreateAccountShown No
|
||||
\ true/false (Default value is true) Whether the \"Don't
|
||||
have an account? Create One\" link is shown in the GAuth login widget.\n\tsocialEnabled
|
||||
\ No true/false (Default value is false) If
|
||||
set to false, do not show any social sign in elements or allow social sign
|
||||
ins.\n\tlockToEmailAddress No Email address to pre-load and
|
||||
lock. If specified, the specified email address will
|
||||
be pre-loaded in the main \"Email\" field in the SSO login form,\n\t as
|
||||
well as in in the \"Email Address\" field in the \"Forgot Password?\" password
|
||||
reset form,\n\t and
|
||||
both fields will be disabled so they can't be changed.\n\t (If
|
||||
for some reason you want to force re-authentications for a known customer
|
||||
account, you can make use of this option.)\n\topenCreateAccount No
|
||||
\ true/false (Default value is false) If set to true,
|
||||
immediately display the the account creation screen.\n\tdisplayNameShown No
|
||||
\ true/false (Default value is false) If set to true,
|
||||
show the \"Display Name\" field on the account creation screen, to allow the
|
||||
user\n\t to
|
||||
set their central MyGarmin display name upon account creation.\n\tglobalOptInShown
|
||||
\ No true/false (Default value is false) Whether
|
||||
the \"Global Opt-In\" check box is shown on the create account & create social
|
||||
account screens.\n\t If
|
||||
set to true these screens will show a \"Sign Up For Email\" check box with
|
||||
accompanying text\n\t \"I
|
||||
would also like to receive email about promotions and new products.\"\n\t
|
||||
\ If
|
||||
checked, the Customer 2.0 account that is created will have it's global opt-in
|
||||
flag set to true,\n\t and
|
||||
Garmin email communications will be allowed.\n\tglobalOptInChecked No
|
||||
\ true/false (Default value is false) Whether the \"Global
|
||||
Opt-In\" check box is checked by default.\n\tconsumeServiceTicket No
|
||||
\ true/false (Default value is true) IF you don't specify
|
||||
a redirectAfterAccountLoginUrl AND you set this to false, the GAuth login
|
||||
widget\n\t will
|
||||
NOT consume the service ticket assigned and will not seamlessly log you into
|
||||
your webapp.\n\t It
|
||||
will send a SUCCESS JavaScript event with the service ticket and service url
|
||||
you can take\n\t and
|
||||
explicitly validate against the SSO infrastructure yourself.\n\t (By
|
||||
using casClient's SingleSignOnUtils.authenticateServiceTicket() utility method,\n\t
|
||||
\ or
|
||||
calling web service customerWebServices_v1.2 AccountManagementService.authenticateServiceTicket().)\n\tmobile
|
||||
\ No true/false (Default value is false) Setting
|
||||
to true will cause mobile friendly views to be shown instead of the tradition
|
||||
screens.\n\ttermsOfUseUrl No Absolute URL to your custom
|
||||
terms of use URL. If not specified, defaults to http://www.garmin.com/terms\n\tprivacyStatementUrl
|
||||
\ No Absolute URL to your custom privacy statement URL. If
|
||||
not specified, defaults to http://www.garmin.com/privacy\n\tproductSupportUrl
|
||||
\ No Absolute URL to your custom product support URL. If
|
||||
not specified, defaults to http://www.garmin.com/us/support/contact\n\tgenerateExtraServiceTicket
|
||||
\ No true/false (Default value is false) If set
|
||||
to true, generate an extra unconsumed service ticket.\n\t\t (The
|
||||
service ticket validation response will include the extra service ticket.)\n\tgenerateTwoExtraServiceTickets
|
||||
\ No true/false (Default value is false) If set to true,
|
||||
generate two extra unconsumed service tickets.\n\t\t\t\t\t\t\t\t\t \t\t\t
|
||||
\ (The service ticket validation response will include the extra service
|
||||
tickets.)\n\tgenerateNoServiceTicket No true/false (Default value
|
||||
is false) If you don't want SSO to generate a service
|
||||
ticket at all when logging in to the GAuth login widget.\n (Useful
|
||||
when allowing logins to static sites that are not SSO enabled and can't consume
|
||||
the service ticket.)\n\tconnectLegalTerms No true/false (Default
|
||||
value is false) Whether to show the connectLegalTerms
|
||||
on the create account page\n\tshowTermsOfUse No true/false
|
||||
(Default value is false) Whether to show the showTermsOfUse
|
||||
on the create account page\n\tshowPrivacyPolicy No true/false
|
||||
(Default value is false) Whether to show the showPrivacyPolicy
|
||||
on the create account page\n\tshowConnectLegalAge No true/false
|
||||
(Default value is false) Whether to show the showConnectLegalAge
|
||||
on the create account page\n\tlocationPromptShown No true/false
|
||||
(Default value is false) If set to true, ask the customer
|
||||
during account creation to verify their country of residence.\n\tshowPassword
|
||||
\ No true/false (Default value is true) If
|
||||
set to false, mobile version for createAccount and login screens would hide
|
||||
the password\n\tuseCustomHeader No true/false (Default value
|
||||
is false) If set to true, the \"Sign in\" text will be
|
||||
replaced by custom text. Contact CDS team to set the i18n text for your client
|
||||
id.\n\tmfaRequired No true/false (Default value is false)
|
||||
\ Require multi factor authentication for all authenticating
|
||||
users.\n\tperformMFACheck No true/false (Default value is
|
||||
false) If set to true, ask the logged in user to pass
|
||||
a multi factor authentication check. (Only valid for an already logged in
|
||||
user.)\n\trememberMyBrowserShown No true/false (Default value is
|
||||
false) Whether the \"Remember My Browser\" check box
|
||||
is shown in the GAuth login widget MFA verification screen.\n\trememberMyBrowserChecked
|
||||
\ No true/false (Default value is false) Whether
|
||||
the \"Remember My Browser\" check box feature is checked by default.\n\tconsentTypeIds\t\t\t\t\tNo\tconsent_types
|
||||
ids\t\t \t\t\t\t\t\t\t\t multiple consent types ids can be passed as consentTypeIds=type1&consentTypeIds=type2\n\t</pre>\n</div>\n\n\n\t<script>(function(){var
|
||||
js = \"window['__CF$cv$params']={r:'7f1ac05c5db34620'};_cpo=document.createElement('script');_cpo.nonce='',_cpo.src='/cdn-cgi/challenge-platform/scripts/invisible.js',document.getElementsByTagName('head')[0].appendChild(_cpo);\";var
|
||||
_0xh = document.createElement('iframe');_0xh.height = 1;_0xh.width = 1;_0xh.style.position
|
||||
= 'absolute';_0xh.style.top = 0;_0xh.style.left = 0;_0xh.style.border = 'none';_0xh.style.visibility
|
||||
= 'hidden';document.body.appendChild(_0xh);function handler() {var _0xi =
|
||||
_0xh.contentDocument || _0xh.contentWindow.document;if (_0xi) {var _0xj =
|
||||
_0xi.createElement('script');_0xj.innerHTML = js;_0xi.getElementsByTagName('head')[0].appendChild(_0xj);}}if
|
||||
(document.readyState !== 'loading') {handler();} else if (window.addEventListener)
|
||||
{document.addEventListener('DOMContentLoaded', handler);} else {var prev =
|
||||
document.onreadystatechange || function () {};document.onreadystatechange
|
||||
= function (e) {prev(e);if (document.readyState !== 'loading') {document.onreadystatechange
|
||||
= prev;handler();}};}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f1ac05c5db34620-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:58:58 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=oT4HuH19GyKTBkqXHXwnSmUp1kcqmbthvziWIXEZLe3kQQBobYqW0Qi%2FXSjy%2B2GN5dy3Cs4ZId74RXjz6bteuof9l6R2Qsum28N4Hy0wBm4fbvYMJZUPAeRAda3mHrUW"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- __cf_bm=SANITIZED; path=SANITIZED; expires=SANITIZED; domain=SANITIZED; HttpOnly;
|
||||
Secure; SameSite=SANITIZED
|
||||
- __cflb=SANITIZED; SameSite=SANITIZED; Secure; path=SANITIZED; expires=SANITIZED;
|
||||
HttpOnly
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_1102:0
|
||||
X-B3-Traceid:
|
||||
- 0338524d977495f906e0c0e47bda3479
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- 8cae38fd-8c5b-4d76-5f53-ed081975bd13
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- __cf_bm=SANITIZED; _cfuvid=SANITIZED; __cflb=SANITIZED; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/embed?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso
|
||||
method: GET
|
||||
uri: https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: "<!DOCTYPE html>\n<html lang=\"en\" class=\"no-js\">\n <head>\n <meta
|
||||
http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n <meta
|
||||
name=\"viewport\" content=\"width=device-width\" />\n <meta http-equiv=\"X-UA-Compatible\"
|
||||
content=\"IE=edge;\" />\n <title>GARMIN Authentication Application</title>\n
|
||||
\ <link href=\"/sso/css/GAuth.css?20210406\" rel=\"stylesheet\" type=\"text/css\"
|
||||
media=\"all\" />\n\n\t <link rel=\"stylesheet\" href=\"\"/>\n\n <script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery/3.1.1/jquery.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\">jQuery.noConflict();</script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/jquery-validate/1.16.0/jquery.validate.min.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/jsUtils.js?20210406\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/json2.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/consoleUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/postmessage.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/popupWindow.js\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/base.js?20210406\"></script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/gigyaUtils.js?20210319\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/login.js?20211102\"></script>\n
|
||||
\ <script type=\"text/javascript\" src=\"/sso/js/reCaptchaUtil.js?20230706\"></script>\n\n
|
||||
\ <script>\n var recaptchaSiteKey = null;\n var
|
||||
reCaptchaURL = \"\\\\\\/sso\\\\\\/reCaptcha?id=gauth-widget\\u0026embedWidget=true\\u0026gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\\u0026redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\";\n
|
||||
\ var isRecaptchaEnabled = null;\n var recaptchaToken
|
||||
= null; \n </script>\n <script type=\"text/javascript\">\n
|
||||
\ var parent_url = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n
|
||||
\ var status \t\t\t= \"\";\n\t\t\tvar result = \"\";\n\t\t\tvar
|
||||
clientId\t\t= '';\n\t\t\tvar embedWidget \t= true;\n\t\t\tvar isUsernameDefined
|
||||
= (false == true) || (false == true);\n\n // Gigya callback to
|
||||
SocialSignInController for brand new social network users redirects to this
|
||||
page\n // to popup Create or Link Social Account page, but has
|
||||
a possibly mangled source parameter\n // where \"?\" is set as
|
||||
\"<QM>\", so translate it back to \"?\" here.\n parent_url = parent_url.replace('<QM>',
|
||||
'?');\n var parent_scheme = parent_url.substring(0, parent_url.indexOf(\"://\"));\n
|
||||
\ var parent_hostname = parent_url.substring(parent_scheme.length
|
||||
+ 3, parent_url.length);\n if (parent_hostname.indexOf(\"/\") !=
|
||||
-1) {\n parent_hostname = parent_hostname.substring(0, parent_hostname.indexOf(\"/\"));\n
|
||||
\ }\n var parentHost \t = parent_scheme + \"://\"
|
||||
+ parent_hostname;\n\t\t\tvar createAccountConfigURL = '\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed';\n
|
||||
\ var socialConfigURL = 'https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed';\n
|
||||
\ var gigyaURL = \"https://cdns.gigya.com/js/gigya.js?apiKey=2_R3ZGY8Bqlwwk3_63knoD9wA_m-Y19mAgW61bF_s5k9gymYnMEAtMrJiF5MjF-U7B\";\n\n
|
||||
\ if (createAccountConfigURL.indexOf('%253A%252F%252F') != -1) {\n
|
||||
\ \tcreateAccountConfigURL = decodeURIComponent(createAccountConfigURL);\n
|
||||
\ }\n consoleInfo('signin.html embedWidget: true, createAccountConfigURL:
|
||||
\\/sso\\/createNewAccount?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26service%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26source%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountLoginUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed%26redirectAfterAccountCreationUrl%3Dhttps%253A%252F%252Fsso.garmin.com%252Fsso%252Fembed,
|
||||
socialEnabled: true, gigyaSupported: true, socialConfigURL(): https://sso.garmin.com/sso/socialSignIn?id%3Dgauth-widget%26embedWidget%3Dtrue%26gauthHost%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26service%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26source%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountLoginUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed%26redirectAfterAccountCreationUrl%3Dhttps%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed');\n\n
|
||||
\ if (socialConfigURL.indexOf('%3A%2F%2F') != -1) {\n \tsocialConfigURL
|
||||
= decodeURIComponent(socialConfigURL);\n }\n\n if( status
|
||||
!= null && status != ''){\n \tsend({'status':status});\n }\n\n
|
||||
\ jQuery(document).ready( function(){\n\n\n consoleInfo(\"signin.html:
|
||||
setting field validation rules...\");\n\n jQuery(\"#username\").rules(\"add\",{\n
|
||||
\ required: true,\n messages: {\n required:
|
||||
\ \"Email is required.\"\n }});\n\n jQuery(\"#password\").rules(\"add\",
|
||||
{\n required: true,\n messages: {\n
|
||||
\ required: \"Password is required.\"\n }\n
|
||||
\ });\n\n consoleInfo(\"signin.html: done setting
|
||||
field validation rules...\");\n\n });\n\n XD.receiveMessage(function(m){\n
|
||||
\ consoleInfo(\"signin.html: \" + m.data + \" received on \"
|
||||
+ window.location.host);\n if (m && m.data) {\n var
|
||||
md = m.data;\n if (typeof(md) === 'string') {\n md
|
||||
= JSON.parse(m.data);\n }\n if (md.setUsername)
|
||||
{\n consoleInfo(\"signin.html: Setting username \\\"\"
|
||||
+ md.username + \"\\\"...\");\n jQuery(\"#signInWithDiffLink\").click();
|
||||
// Ensure the normal login form is shown.\n jQuery(\"#username\").val(md.username);\n
|
||||
\ jQuery(\"#password\").focus();\n }\n
|
||||
\ }\n }, parentHost);\n </script>\n </head>\n
|
||||
\ <body>\n\n <!-- begin GAuth component -->\n <div id=\"GAuth-component\">\n
|
||||
\ <!-- begin login component-->\n <div id=\"login-component\"
|
||||
class=\"blueForm-basic\">\n <input type=\"hidden\" id=\"queryString\"
|
||||
value=\"id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed\"
|
||||
/>\n\t \t <input type=\"hidden\" id=\"contextPath\" value=\"/sso\" />\n
|
||||
\ <!-- begin login form -->\n <div id=\"login-state-default\">\n
|
||||
\ <h2>Sign In</h2>\n\n <form method=\"post\"
|
||||
id=\"login-form\">\n\n <div class=\"form-alert\">\n\t\t\t\t\t\t\t\n
|
||||
\ \n \n \n
|
||||
\ \n \n \n\n
|
||||
\ <div id=\"username-error\" style=\"display:none;\"></div>\n
|
||||
\ <div id=\"password-error\" style=\"display:none;\"></div>\n
|
||||
\ </div>\n <div class=\"textfield\">\n\t\t\t\t\t\t\t<label
|
||||
for=\"username\">Email</label>\n \t\t<!-- If the
|
||||
lockToEmailAddress parameter is specified then we want to mark the field as
|
||||
readonly,\n \t\tpreload the email address, and disable
|
||||
the other input so that null isn't sent to the server. We'll\n \t\talso
|
||||
style the field to have a darker grey background and disable the mouse pointer\n
|
||||
\ \t\t -->\n\t\t\t\t\t\t\t \n\t\t\t\t\t\t\t\t<!--
|
||||
If the lockToEmailAddress parameter is NOT specified then keep the existing
|
||||
functionality and disable the readonly input field\n\t\t\t\t\t\t\t -->\n\t\t\t\t\t\t\t
|
||||
\ <input class=\"login_email\" name=\"username\" id=\"username\" value=\"\"
|
||||
type=\"email\" spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\"/>\n\n
|
||||
\ </div>\n\n <div class=\"textfield\">\n
|
||||
\ <label for=\"password\">Password</label>\n <a
|
||||
id=\"loginforgotpassword\" class=\"login-forgot-password\" style=\"cursor:pointer\">(Forgot?)</a>\n
|
||||
\ <input type=\"password\" name=\"password\" id=\"password\"
|
||||
spellcheck=\"false\" autocorrect=\"off\" autocapitalize=\"off\" />\n <strong
|
||||
id=\"capslock-warning\" class=\"information\" title=\"Caps lock is on.\" style=\"display:
|
||||
none;\">Caps lock is on.</strong>\n\t\t\t\t\t </div>\n <input
|
||||
type=\"hidden\" name=\"embed\" value=\"true\"/>\n <input
|
||||
type=\"hidden\" name=\"_csrf\" value=\"13F3CDCE9481A2AA198AB31BDC20A8483C5FAAAC4C9BFA97A27733E25331ECCA20D8E912E7DBB994EC0F43F2E5E018326534\"
|
||||
/>\n <button type=\"submit\" id=\"login-btn-signin\"
|
||||
class=\"btn1\" accesskey=\"l\">Sign In</button>\n \n\n\n
|
||||
\ <!-- The existence of the \"rememberme\" parameter
|
||||
at all will remember the user! -->\n \n\n </form>\n
|
||||
\ </div>\n <!-- end login form -->\n\n <!--
|
||||
begin Create Account message -->\n\t <div id=\"login-create-account\">\n\t
|
||||
\ \n\t </div>\n\t <!-- end Create Account
|
||||
message -->\n\n\t <!-- begin Social Sign In component -->\n\t <div
|
||||
id=\"SSI-component\">\n \n\n\t\t\t\t\t\n\t </div>\n\t
|
||||
\ <!-- end Social Sign In component -->\n <div class=\"clearfix\"></div>
|
||||
<!-- Ensure that GAuth-component div's height is computed correctly. -->\n
|
||||
\ </div>\n <!-- end login component-->\n\n\t\t</div>\n\t\t<!--
|
||||
end GAuth component -->\n\n <script type=\"text/javascript\">\n jQuery(document).ready(function(){\n
|
||||
\ \tresizePageOnLoad(jQuery(\"#GAuth-component\").height());\n\n\t\t
|
||||
\ if(isUsernameDefined == true){\n\t\t // If the user's login
|
||||
just failed, redisplay the email/username specified, and focus them in the
|
||||
password field.\n\t\t jQuery(\"#password\").focus();\n\t\t }
|
||||
else if(false == true && result != \"PASSWORD_RESET_RESULT\"){\n //
|
||||
Otherwise focus them in the username field of the login dialog.\n jQuery(\"#username\").focus();\n
|
||||
\ }\n\n // Scroll to top of iframe to fix problem
|
||||
where Firefox 3.0-3.6 browsers initially show top of iframe cutoff.\n location.href=\"#\";\n\n
|
||||
\ if(!embedWidget){\n \tjQuery('.createAccountLink').click(function(){\n\t
|
||||
\ send({'openLiteBox':'createAccountLink', 'popupUrl': createAccountConfigURL,
|
||||
'popupTitle':'Create An Account', 'clientId':clientId});\n\t });\n
|
||||
\ }\n });\n </script>\n <script>(function(){var
|
||||
js = \"window['__CF$cv$params']={r:'7f1ac05e69e44796'};_cpo=document.createElement('script');_cpo.nonce='',_cpo.src='/cdn-cgi/challenge-platform/scripts/invisible.js',document.getElementsByTagName('head')[0].appendChild(_cpo);\";var
|
||||
_0xh = document.createElement('iframe');_0xh.height = 1;_0xh.width = 1;_0xh.style.position
|
||||
= 'absolute';_0xh.style.top = 0;_0xh.style.left = 0;_0xh.style.border = 'none';_0xh.style.visibility
|
||||
= 'hidden';document.body.appendChild(_0xh);function handler() {var _0xi =
|
||||
_0xh.contentDocument || _0xh.contentWindow.document;if (_0xi) {var _0xj =
|
||||
_0xi.createElement('script');_0xj.innerHTML = js;_0xi.getElementsByTagName('head')[0].appendChild(_0xj);}}if
|
||||
(document.readyState !== 'loading') {handler();} else if (window.addEventListener)
|
||||
{document.addEventListener('DOMContentLoaded', handler);} else {var prev =
|
||||
document.onreadystatechange || function () {};document.onreadystatechange
|
||||
= function (e) {prev(e);if (document.readyState !== 'loading') {document.onreadystatechange
|
||||
= prev;handler();}};}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-Ray:
|
||||
- 7f1ac05e69e44796-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:58:58 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=Rzl0HOKLCsW3P9JRr3RwN81d8PqMActtbSq4Dr6hqeIxBIK%2FkzLeLOMRn0KALChfJIB4cSgh1DszqkKVz6dxdWoBV7jsY4WstuGcTqyiAIeGTgRqmxgjXdR2B4Q65HZU"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- SESSION=SANITIZED; Path=SANITIZED; Secure; HttpOnly
|
||||
- __VCAP_ID__=SANITIZED; Path=SANITIZED; HttpOnly; Secure
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_1102:3
|
||||
X-B3-Traceid:
|
||||
- 60593e96725f1a2f5e057d199d84874b
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- 9799eaf1-bdf2-420f-52ab-755533296a5f
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: username=SANITIZED&password=SANITIZED&embed=true&_csrf=13F3CDCE9481A2AA198AB31BDC20A8483C5FAAAC4C9BFA97A27733E25331ECCA20D8E912E7DBB994EC0F43F2E5E018326534
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '175'
|
||||
Content-Type:
|
||||
- application/x-www-form-urlencoded
|
||||
Cookie:
|
||||
- SESSION=SANITIZED; __cf_bm=SANITIZED; _cfuvid=SANITIZED; __VCAP_ID__=SANITIZED;
|
||||
__cflb=SANITIZED; org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: POST
|
||||
uri: https://sso.garmin.com/sso/signin?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
response:
|
||||
body:
|
||||
string: "<!DOCTYPE html>\n<html class=\"no-js\">\n\t<head>\n\t\t<title>Success</title>\n\t\t<meta
|
||||
charset=\"utf-8\">\n\t\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge;\"
|
||||
/>\n\t\t<meta name=\"description\" content=\"\">\n\t\t<meta name=\"viewport\"
|
||||
content=\"width=device-width, initial-scale=1\">\n\t\t<meta http-equiv=\"cleartype\"
|
||||
content=\"on\">\n\t\t<script type=\"text/javascript\" src=\"/sso/js/jquery/3.1.1/jquery.min.js?20210319\"></script>\n\t\t<script
|
||||
type=\"text/javascript\">jQuery.noConflict();</script>\n\t\t<script type=\"text/javascript\"
|
||||
src=\"/sso/js/json2.js\"></script>\n\t\t<script type=\"text/javascript\" src=\"/sso/js/consoleUtils.js?20210319\"></script>\n\t\t<script
|
||||
type=\"text/javascript\" src=\"/sso/js/postmessage.js?20210319\"></script>\n\t\t<script
|
||||
type=\"text/javascript\">\n\t\t\tvar redirectAfterAccountLoginUrl \t = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n\t\t\tvar
|
||||
redirectAfterAccountCreationUrl = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n\t\t\tvar
|
||||
consumeServiceTicket \t = \"true\";\n\t\t\tvar service_url \t
|
||||
\ = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n\t\t\tvar parent_url \t
|
||||
\ = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n\t\t\tvar response_url
|
||||
\ \t = \"https:\\/\\/sso.garmin.com\\/sso\\/embed?ticket=ST-2459533-YeWiOAMHdTmHqEyWcWeI-cas\";\n\t\t\tvar
|
||||
logintoken \t = \"\";\n\t\t\tvar socialLogin \t
|
||||
\ = \"\";\n\t\t\tvar performMFACheck = \"\";\n\n\t\t\t// Decode
|
||||
url if it's encoded unnecessarily (which is happening when SSO GAuth logins
|
||||
redisplay the login page due to session timeouts.)\n\t\t\tif (response_url.indexOf('%3A%2F%2F')
|
||||
!= -1) {\n\t\t\t\tresponse_url = decodeURIComponent(response_url);\n\t\t\t}\n\t\t\tresponse_url
|
||||
= response_url.replace(new RegExp(\"&\", 'g'),\"&\");\n\n\t\t\tvar service_ticket
|
||||
= response_url.substring(response_url.indexOf('ticket=') + 7, response_url.length);\n\n\t\t\tif
|
||||
(redirectAfterAccountLoginUrl) {\n\t\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
redirectAfterAccountLoginUrl: [' + redirectAfterAccountLoginUrl + ']');\n\t\t\t}\n\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
consumeServiceTicket: [' + consumeServiceTicket + ']');\n\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
service_url: [' + service_url + ']');\n\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
parent_url: [' + parent_url + ']');\n\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
response_url: [' + response_url + ']');\n\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
service_ticket: [' + service_ticket + ']');\n\t\t\tif (logintoken)
|
||||
{\n\t\t\t\tconsoleInfo('casEmbedSuccess.html: logintoken: ['
|
||||
+ logintoken + ']');\n\t\t\t}\n\t\t\tif (socialLogin) {\n\t\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
socialLogin: [' + socialLogin + ']');\n\t\t\t}\n\n\t\t\tfunction
|
||||
send(msg) {\n\t\t\t\tconsoleInfo('casEmbedSuccess.html: send(): Calling XD.postMessage(msg:['
|
||||
+ JSON.stringify(msg) + '], target_url:[' + parent_url + '])...');\n\t\t\t\tXD.postMessage(msg,
|
||||
parent_url, parent);\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfunction redirect(target){\n\t\t\t\tvar
|
||||
embedWidget = \"true\";\n\t\t\t\tif (embedWidget != 'true') {\n\t\t\t\t\tif
|
||||
(logintoken || socialLogin) {\n\t\t\t\t\t\t// Tell parent to close opened
|
||||
Gauth lite box.\n\t\t\t\t\t\tsend({'closeLiteBox':'1'});\n\t\t\t\t\t} else
|
||||
{\n\t\t\t\t\t\t// Tell parent to resize Gauth widget's height to just that
|
||||
of the loading icon.\n\t\t\t\t\t\tsend({'gauthHeight':jQuery(\"#GAuth-component\").height()});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif
|
||||
(window.opener != null) {\n\t\t\t\t\tvar iframeParent = window.opener.parent;\n\t\t\t\t\tiframeParent.location.href
|
||||
= target;\n\t\t\t\t\twindow.close();\n\t\t\t\t} else {\n\t\t\t\t\t// If the
|
||||
\"redirectAfterAccountLoginUrl\" GAuth config parameter was specified,\n\t\t\t\t\t//
|
||||
a full page refresh upon logon was requested, so redirect the parent window
|
||||
upon login.\n\t\t\t\t\tif (redirectAfterAccountLoginUrl || redirectAfterAccountCreationUrl
|
||||
|| (socialLogin && socialLogin === 'true') || (performMFACheck && performMFACheck
|
||||
=== 'true')) {\n\n\t\t\t\t\t\tif (embedWidget != 'true') {\n\t\t\t\t\t\t\tsend({'status':'SUCCESS',
|
||||
'successDetails':'Login Successful'});\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Redirect
|
||||
parent of login iframe to requested service URL with ?ST=<Service Ticket ID>
|
||||
appended,\n\t\t\t\t\t\t// so the webapp can validate the service ticket and
|
||||
log the user on to the webapp.\n\t\t\t\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
Calling parent.location.href = [' + response_url + '];...');\n\t\t\t\t\t\ttop.location.href
|
||||
= response_url;\n\n\t\t\t\t\t// Else if GAuth was configured not to consume
|
||||
the service ticket, send the service ticket and service url.\n\t\t\t\t\t//
|
||||
It's then up to the parent page to hide the GAuth widget and validate the
|
||||
service ticket.\n\t\t\t\t\t} else if (consumeServiceTicket == 'false') {\n\n\t\t\t\t\t\tsend({'status':'SUCCESS',
|
||||
'successDetails':'Login Successful', 'serviceTicket':service_ticket, 'serviceUrl':service_url});\n\n\t\t\t\t\t}
|
||||
else {\n\t\t\t\t\t\t// Else consume the service ticket and log the user into
|
||||
the parent webapp, by making a JSONP request to the response url.\n\t\t\t\t\t\t//
|
||||
This service ticket request to the parent webapp will return a small amount
|
||||
of JSON that we\n\t\t\t\t\t\t// can send in the success event to the parent
|
||||
page to notify them of successful logon\n\t\t\t\t\t\t// It's then up to the
|
||||
parent page to hide the GAuth widget and do whatever it wants.\n\t\t\t\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
Loading ajax jsonp URL: [' + response_url + ']');\n\t\t\t\t\t\tjQuery.ajax({\n\t\t\t\t\t\t\ttype:
|
||||
\"REDIRECT\",\n\t\t\t\t\t\t\turl: response_url,\n\t\t\t\t\t\t\tdataType: 'jsonp',\n\t\t\t\t\t\t\terror:
|
||||
function(xhr, status, error) {\n\t\t\t\t\t\t\t\tconsoleError('casEmbedSuccess.html:
|
||||
Error loading ajax jsonp URL: [' + response_url + ']! Error: ' + error);\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tsuccess:
|
||||
function( data, status, xhr ) {\n\t\t\t\t\t\t\t\tconsoleInfo('casEmbedSuccess.html:
|
||||
success loading ajax jsonp url. data: [' + data + ']');\n\t\t\t\t\t\t\t\tvar
|
||||
userdata = data;\n\t\t\t\t\t\t\t\tif (typeof(userdata) === 'string') {\n\t\t\t\t\t\t\t\t\tuserdata
|
||||
= JSON.parse(data);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tconsoleInfo('casGenericRedirect.jsp:
|
||||
customerId: [' + userdata.customerId\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], username: [' + userdata.username\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], rememberMe: [' + userdata.rememberMe\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], password: [' + userdata.password\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], email: [' + userdata.email\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], displayName: [' + userdata.displayName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], firstName: [' + userdata.firstName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], lastName: [' + userdata.lastName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], localePreference: [' + userdata.localePreference\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], addressLine1: [' + userdata.addressLine1\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], addressLine2: [' + userdata.addressLine2\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], cityName: [' + userdata.cityName\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], state: [' + userdata.state\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], postalCode: [' + userdata.postalCode\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], country: [' + userdata.country\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], passwordChangeRequired: [' + userdata.passwordChangeRequired\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], lastLogin: [' + userdata.lastLogin\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
'], erpCustomerNumber: [' + userdata.erpCustomerNumber\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t+
|
||||
']');\n\t\t\t\t\t\t\t\tsend({'status' : 'SUCCESS',\n\t\t\t\t\t\t\t\t\t\t\t'successDetails'
|
||||
\ : 'Login Successful',\n\t\t\t\t\t\t\t\t\t\t\t'customerId' :
|
||||
userdata.customerId,\n\t\t\t\t\t\t\t\t\t\t\t'username' : userdata.username,\n\t\t\t\t\t\t\t\t\t\t\t'rememberMe'
|
||||
\ : userdata.rememberMe,\n\t\t\t\t\t\t\t\t\t\t\t'password' :
|
||||
userdata.password,\n\t\t\t\t\t\t\t\t\t\t\t'email' : userdata.email,\n\t\t\t\t\t\t\t\t\t\t\t'displayName'
|
||||
\ : userdata.displayName,\n\t\t\t\t\t\t\t\t\t\t\t'firstName' :
|
||||
userdata.firstName,\n\t\t\t\t\t\t\t\t\t\t\t'lastName' : userdata.lastName,\n\t\t\t\t\t\t\t\t\t\t\t'localePreference'
|
||||
\ : userdata.localePreference,\n\t\t\t\t\t\t\t\t\t\t\t'addressLine1'
|
||||
\ : userdata.addressLine1,\n\t\t\t\t\t\t\t\t\t\t\t'addressLine2'
|
||||
\ : userdata.addressLine2,\n\t\t\t\t\t\t\t\t\t\t\t'cityName' :
|
||||
userdata.cityName,\n\t\t\t\t\t\t\t\t\t\t\t'state' : userdata.state,\n\t\t\t\t\t\t\t\t\t\t\t'postalCode'
|
||||
\ : userdata.postalCode,\n\t\t\t\t\t\t\t\t\t\t\t'country' :
|
||||
userdata.country,\n\t\t\t\t\t\t\t\t\t\t\t'passwordChangeRequired' : userdata.passwordChangeRequired,\n\t\t\t\t\t\t\t\t\t\t\t'lastLogin'
|
||||
\ : userdata.lastLogin,\n\t\t\t\t\t\t\t\t\t\t\t'erpCustomerNumber'
|
||||
\ : userdata.erpCustomerNumber\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t</script>\n\t</head>\n\t<body>\n\t\t<div
|
||||
id=\"GAuth-component\">\n\t\t\t<img src='/sso/images/ajax-loader.gif' class=\"loaderImage\"/>\n\t\t</div>\n\t\t<script
|
||||
type=\"text/javascript\">\n\t\t\tjQuery(document).ready(function(){\n\t\t\t\tvar
|
||||
service = \"https:\\/\\/sso.garmin.com\\/sso\\/embed\";\n\t\t\t\tconsoleInfo(\"casEmbedSuccess.html:
|
||||
ready, calling redirect('\" + service + \"')...\");\n\t\t\t\tredirect(service);\n\t\t\t});\n\t\t</script>\n\t<script>(function(){var
|
||||
js = \"window['__CF$cv$params']={r:'7f1ac060fe1846d4'};_cpo=document.createElement('script');_cpo.nonce='',_cpo.src='/cdn-cgi/challenge-platform/scripts/invisible.js',document.getElementsByTagName('head')[0].appendChild(_cpo);\";var
|
||||
_0xh = document.createElement('iframe');_0xh.height = 1;_0xh.width = 1;_0xh.style.position
|
||||
= 'absolute';_0xh.style.top = 0;_0xh.style.left = 0;_0xh.style.border = 'none';_0xh.style.visibility
|
||||
= 'hidden';document.body.appendChild(_0xh);function handler() {var _0xi =
|
||||
_0xh.contentDocument || _0xh.contentWindow.document;if (_0xi) {var _0xj =
|
||||
_0xi.createElement('script');_0xj.innerHTML = js;_0xi.getElementsByTagName('head')[0].appendChild(_0xj);}}if
|
||||
(document.readyState !== 'loading') {handler();} else if (window.addEventListener)
|
||||
{document.addEventListener('DOMContentLoaded', handler);} else {var prev =
|
||||
document.onreadystatechange || function () {};document.onreadystatechange
|
||||
= function (e) {prev(e);if (document.readyState !== 'loading') {document.onreadystatechange
|
||||
= prev;handler();}};}})();</script></body>\n</html>\n"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- Access-Control-Allow-Headers, Origin,Accept, X-Requested-With, Content-Type,
|
||||
Access-Control-Request-Method, Access-Control-Request-Headers
|
||||
Access-Control-Allow-Methods:
|
||||
- GET,POST,OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- https://www.garmin.com
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-Ray:
|
||||
- 7f1ac060fe1846d4-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Language:
|
||||
- en
|
||||
Content-Type:
|
||||
- text/html;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:58:59 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=G8f1H9875FHi4mMW3X7aS9aND4jZAZnlBDAVr3KGz1hFmtUrVwqS3KipwKZMkQ40Rq4vjHtTGn22Fm5%2Bg7VA0XNSbcb3q8f%2BK%2FI0nzh0GsR2fGk%2FH0S4yBe7bsMOwol%2F"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- CASTGC=SANITIZED; Path=SANITIZED; Secure; HttpOnly
|
||||
- CASTGC=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED; Secure;
|
||||
HttpOnly
|
||||
- GARMIN-SSO=SANITIZED; Domain=SANITIZED; Path=SANITIZED
|
||||
- GARMIN-SSO=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Domain=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- GarminNoCache=SANITIZED; Domain=SANITIZED; Path=SANITIZED
|
||||
- GarminNoCache=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Domain=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- GarminBuyCacheKey=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Domain=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- GarminBuyCacheKey=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Domain=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- GARMIN-SSO-GUID=SANITIZED; Domain=SANITIZED; Path=SANITIZED
|
||||
- GARMIN-SSO-GUID=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Domain=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- GARMIN-SSO-CUST-GUID=SANITIZED; Domain=SANITIZED; Path=SANITIZED
|
||||
- GARMIN-SSO-CUST-GUID=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Domain=SANITIZED;
|
||||
Path=SANITIZED
|
||||
- CASTGC=SANITIZED; Path=SANITIZED; Secure; HttpOnly
|
||||
- CASTGC=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED; Secure;
|
||||
HttpOnly
|
||||
- __cfruid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
X-Application-Context:
|
||||
- casServer:cloud,prod,prod-US_1102:3
|
||||
X-B3-Traceid:
|
||||
- 67d13140bb74241f5ffafc30cb590ae9
|
||||
X-Robots-Tag:
|
||||
- noindex
|
||||
X-Vcap-Request-Id:
|
||||
- bb5f25d2-31ab-4879-5100-1898910361aa
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- python-requests/2.31.0
|
||||
method: GET
|
||||
uri: https://thegarth.s3.amazonaws.com/oauth_consumer.json
|
||||
response:
|
||||
body:
|
||||
string: '{"consumer_key": "SANITIZED", "consumer_secret": "SANITIZED"}'
|
||||
headers:
|
||||
Accept-Ranges:
|
||||
- bytes
|
||||
Content-Length:
|
||||
- '124'
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:59:00 GMT
|
||||
ETag:
|
||||
- '"20240b1013cb35419bb5b2cff1407a4e"'
|
||||
Last-Modified:
|
||||
- Thu, 03 Aug 2023 00:16:11 GMT
|
||||
Server:
|
||||
- AmazonS3
|
||||
x-amz-id-2:
|
||||
- MSQpXzot1gVYwlRRZFwqhhl2CaWvGVUOa87bLyZb9cWDw/4XeFMn4LLslomjV8xnr5ejXOTDRjM=
|
||||
x-amz-request-id:
|
||||
- DK3CF9X2YV7R386H
|
||||
x-amz-server-side-encryption:
|
||||
- AES256
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- !!binary |
|
||||
Ki8q
|
||||
Accept-Encoding:
|
||||
- !!binary |
|
||||
Z3ppcCwgZGVmbGF0ZQ==
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- !!binary |
|
||||
a2VlcC1hbGl2ZQ==
|
||||
User-Agent:
|
||||
- !!binary |
|
||||
Y29tLmdhcm1pbi5hbmRyb2lkLmFwcHMuY29ubmVjdG1vYmlsZQ==
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/oauth-service/oauth/preauthorized?ticket=ST-2459533-YeWiOAMHdTmHqEyWcWeI-cas&login-url=https://sso.garmin.com/sso/embed&accepts-mfa-tokens=true
|
||||
response:
|
||||
body:
|
||||
string: oauth_token=SANITIZED&oauth_token_secret=SANITIZED
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f1ac06849351556-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- text/plain;charset=utf-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:59:00 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=3MpWsX37CvkXmKc8KOczSqUhotPJCTd8xg30IHeNtiLn%2BgRHZ1OLmUEmEzCFRFA7bLdNQMtPMOWGkA4XmepxRdPww%2F92hfzoqcwW3lwmrqWWp9BAJtSvRfdnAfH%2F43eEBK5yLU%2F8CQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: ''
|
||||
headers:
|
||||
Accept:
|
||||
- !!binary |
|
||||
Ki8q
|
||||
Accept-Encoding:
|
||||
- !!binary |
|
||||
Z3ppcCwgZGVmbGF0ZQ==
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- !!binary |
|
||||
a2VlcC1hbGl2ZQ==
|
||||
Content-Length:
|
||||
- !!binary |
|
||||
MA==
|
||||
Content-Type:
|
||||
- !!binary |
|
||||
YXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVk
|
||||
User-Agent:
|
||||
- !!binary |
|
||||
Y29tLmdhcm1pbi5hbmRyb2lkLmFwcHMuY29ubmVjdG1vYmlsZQ==
|
||||
method: POST
|
||||
uri: https://connectapi.garmin.com/oauth-service/oauth/exchange/user/2.0
|
||||
response:
|
||||
body:
|
||||
string: '{"scope": "COMMUNITY_COURSE_READ GARMINPAY_WRITE GOLF_API_READ ATP_READ
|
||||
GHS_SAMD GHS_UPLOAD INSIGHTS_READ COMMUNITY_COURSE_WRITE CONNECT_WRITE GCOFFER_WRITE
|
||||
GARMINPAY_READ DT_CLIENT_ANALYTICS_WRITE GOLF_API_WRITE INSIGHTS_WRITE PRODUCT_SEARCH_READ
|
||||
GCOFFER_READ CONNECT_READ ATP_WRITE", "jti": "SANITIZED", "access_token":
|
||||
"SANITIZED", "token_type": "Bearer", "refresh_token": "SANITIZED", "expires_in":
|
||||
102003, "refresh_token_expires_in": 2591999}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f1ac06b2ea41547-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 23:59:00 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=NNCYZLaC3FVERa7klmexZY7Kh3hgtxeCrxhI99bSdoSg4HYUBlJtp%2FgVylwDlkFrU%2B0S5Ufb69lEQjC583RGLoO6U8PZFyHu1Bopl%2B%2BXq0QwIoOs36XBwicE1xqC7%2B7IWFi7pOAhKw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,82 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/userprofile-service/socialProfile
|
||||
response:
|
||||
body:
|
||||
string: '{"id": 3154645, "profileId": 2591602, "garminGUID": "0690cc1d-d23d-4412-b027-80fd4ed1c0f6",
|
||||
"displayName": "mtamizi", "fullName": "Matin Tamizi", "userName": "mtamizi",
|
||||
"profileImageType": "UPLOADED_PHOTO", "profileImageUrlLarge": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/73240e81-6e4d-43fc-8af8-c8f6c51b3b8f-2591602.png",
|
||||
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/685a19e9-a7be-4a11-9bf9-faca0c5d1f1a-2591602.png",
|
||||
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/6302f021-0ec7-4dc9-b0c3-d5a19bc5a08c-2591602.png",
|
||||
"location": "Ciudad de M\u00e9xico, CDMX", "facebookUrl": null, "twitterUrl":
|
||||
null, "personalWebsite": null, "motivation": null, "bio": null, "primaryActivity":
|
||||
null, "favoriteActivityTypes": [], "runningTrainingSpeed": 0.0, "cyclingTrainingSpeed":
|
||||
0.0, "favoriteCyclingActivityTypes": [], "cyclingClassification": null, "cyclingMaxAvgPower":
|
||||
0.0, "swimmingTrainingSpeed": 0.0, "profileVisibility": "private", "activityStartVisibility":
|
||||
"private", "activityMapVisibility": "public", "courseVisibility": "public",
|
||||
"activityHeartRateVisibility": "public", "activityPowerVisibility": "public",
|
||||
"badgeVisibility": "private", "showAge": false, "showWeight": false, "showHeight":
|
||||
false, "showWeightClass": false, "showAgeRange": false, "showGender": false,
|
||||
"showActivityClass": false, "showVO2Max": false, "showPersonalRecords": false,
|
||||
"showLast12Months": false, "showLifetimeTotals": false, "showUpcomingEvents":
|
||||
false, "showRecentFavorites": false, "showRecentDevice": false, "showRecentGear":
|
||||
false, "showBadges": true, "otherActivity": null, "otherPrimaryActivity":
|
||||
null, "otherMotivation": null, "userRoles": ["SCOPE_ATP_READ", "SCOPE_ATP_WRITE",
|
||||
"SCOPE_COMMUNITY_COURSE_READ", "SCOPE_COMMUNITY_COURSE_WRITE", "SCOPE_CONNECT_READ",
|
||||
"SCOPE_CONNECT_WRITE", "SCOPE_DT_CLIENT_ANALYTICS_WRITE", "SCOPE_GARMINPAY_READ",
|
||||
"SCOPE_GARMINPAY_WRITE", "SCOPE_GCOFFER_READ", "SCOPE_GCOFFER_WRITE", "SCOPE_GHS_SAMD",
|
||||
"SCOPE_GHS_UPLOAD", "SCOPE_GOLF_API_READ", "SCOPE_GOLF_API_WRITE", "SCOPE_INSIGHTS_READ",
|
||||
"SCOPE_INSIGHTS_WRITE", "SCOPE_OMT_CAMPAIGN_READ", "SCOPE_OMT_SUBSCRIPTION_READ",
|
||||
"SCOPE_PRODUCT_SEARCH_READ", "ROLE_CONNECTUSER", "ROLE_FITNESS_USER", "ROLE_WELLNESS_USER",
|
||||
"ROLE_OUTDOOR_USER", "ROLE_CONNECT_2_USER", "ROLE_TACX_APP_USER"], "nameApproved":
|
||||
true, "userProfileFullName": "Matin Tamizi", "makeGolfScorecardsPrivate":
|
||||
true, "allowGolfLiveScoring": false, "allowGolfScoringByConnections": true,
|
||||
"userLevel": 4, "userPoint": 166, "levelUpdateDate": "2024-01-31T12:18:59.0",
|
||||
"levelIsViewed": false, "levelPointThreshold": 300, "userPointOffset": 0,
|
||||
"userPro": false}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8f0d992ebcfb6c34-DFW
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 12 Dec 2024 12:08:11 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=niRDLu7E86gruuRnFLQL4RUQO9vMZyAA5NQ64mt7vW0Gmmsl2%2BCut6v2k9Pj6yXDDr42mqOH%2B%2BvYhVgRbnkLUTD3xXo3YREb7jiUYBGZhBKpRQafvfz0TvC63Co%2BVJCaehygZ%2B9HlA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,133 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: '[{"changeState": "CHANGED", "trainingMethod": "HR_RESERVE", "lactateThresholdHeartRateUsed":
|
||||
170, "maxHeartRateUsed": 185, "restingHrAutoUpdateUsed": false, "sport": "DEFAULT",
|
||||
"zone1Floor": 130, "zone2Floor": 140, "zone3Floor": 150, "zone4Floor": 160,
|
||||
"zone5Floor": 170}]'
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '272'
|
||||
Content-Type:
|
||||
- application/json
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: PUT
|
||||
uri: https://connectapi.garmin.com/biometric-service/heartRateZones
|
||||
response:
|
||||
body:
|
||||
string: ''
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 80f7523e7a572165-MAD
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Sun, 01 Oct 2023 20:05:35 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=CgUHNfj6nCHwLWrYOFgl0OXLp6K6aHVOe5Mh7xn1vbd30JRWu6lJQSC4quw%2FLJFh%2BXkgEOsJ8R2dJ1lX7s1TLQkg5F6rm9mey6S40Yele44L6ykjlVQmfQZPBRBCH7rl%2Bdb%2B0w393g%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 204
|
||||
message: No Content
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- ADRUM_BTa=SANITIZED; SameSite=SANITIZED; ADRUM_BT1=SANITIZED; _cfuvid=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/biometric-service/heartRateZones
|
||||
response:
|
||||
body:
|
||||
string: '[{"trainingMethod": "HR_RESERVE", "restingHeartRateUsed": 42, "lactateThresholdHeartRateUsed":
|
||||
170, "zone1Floor": 130, "zone2Floor": 140, "zone3Floor": 150, "zone4Floor":
|
||||
160, "zone5Floor": 170, "maxHeartRateUsed": 185, "restingHrAutoUpdateUsed":
|
||||
false, "sport": "DEFAULT", "changeState": "UNCHANGED"}]'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 80f752435bf2666b-MAD
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Sun, 01 Oct 2023 20:05:36 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=kkTPrb69Gsx4APeQBgtestcf2%2BIDf9pLcQhn1Bv3hfXr%2FH1B09AZNsqL%2Bk5eQygFQbE0F9pZzdJ1XmqfHBql6tqQX5pTwiDiAHy7jV2hy7qnCZmCtlV3REKoEo%2FZ0oIEtX7vyn7FRg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,193 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- python-requests/2.31.0
|
||||
method: GET
|
||||
uri: https://thegarth.s3.amazonaws.com/oauth_consumer.json
|
||||
response:
|
||||
body:
|
||||
string: '{"consumer_key": "SANITIZED", "consumer_secret": "SANITIZED"}'
|
||||
headers:
|
||||
Accept-Ranges:
|
||||
- bytes
|
||||
Content-Length:
|
||||
- '124'
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sun, 06 Aug 2023 14:28:00 GMT
|
||||
ETag:
|
||||
- '"20240b1013cb35419bb5b2cff1407a4e"'
|
||||
Last-Modified:
|
||||
- Thu, 03 Aug 2023 00:16:11 GMT
|
||||
Server:
|
||||
- AmazonS3
|
||||
x-amz-id-2:
|
||||
- 9tePW1jJAYQ3uv6MTzPUchn0ZP+JWMF2a9Zc1mB8quIAtuIxVG/I/LUQHhTiZgd8wChW+eR2PA1ATnw0Tkjldw==
|
||||
x-amz-request-id:
|
||||
- 07RRD5QKQXX1GET8
|
||||
x-amz-server-side-encryption:
|
||||
- AES256
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: mfa_token=MFA-1578-9cKDf5iVPDPdBpT3HZtpEhyIZ4Bmger7gIpit5siAlFPGPrVJk-cas
|
||||
headers:
|
||||
Accept:
|
||||
- !!binary |
|
||||
Ki8q
|
||||
Accept-Encoding:
|
||||
- !!binary |
|
||||
Z3ppcCwgZGVmbGF0ZQ==
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- !!binary |
|
||||
a2VlcC1hbGl2ZQ==
|
||||
Content-Length:
|
||||
- '73'
|
||||
Content-Type:
|
||||
- !!binary |
|
||||
YXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVk
|
||||
User-Agent:
|
||||
- !!binary |
|
||||
Y29tLmdhcm1pbi5hbmRyb2lkLmFwcHMuY29ubmVjdG1vYmlsZQ==
|
||||
method: POST
|
||||
uri: https://connectapi.garmin.com/oauth-service/oauth/exchange/user/2.0
|
||||
response:
|
||||
body:
|
||||
string: '{"scope": "COMMUNITY_COURSE_READ GARMINPAY_WRITE GOLF_API_READ ATP_READ
|
||||
GHS_SAMD GHS_UPLOAD INSIGHTS_READ COMMUNITY_COURSE_WRITE CONNECT_WRITE GCOFFER_WRITE
|
||||
GARMINPAY_READ DT_CLIENT_ANALYTICS_WRITE GOLF_API_WRITE INSIGHTS_WRITE PRODUCT_SEARCH_READ
|
||||
GCOFFER_READ CONNECT_READ ATP_WRITE", "jti": "SANITIZED", "access_token":
|
||||
"SANITIZED", "token_type": "Bearer", "refresh_token": "SANITIZED", "expires_in":
|
||||
65481, "refresh_token_expires_in": 2591999}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f27f6bfcef57ea5-LAX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sun, 06 Aug 2023 14:28:01 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=1gipzcbhAhY0bP2r3RhDsanmOc8Hzo0tPhViR5ht3fD6bJu%2B7FT8M8H333APSe3wQ4WHJUwlX3xu0DvvdK3SbcTDTNWWEf3aMp1wQ0D7llAZ3%2Bjbf1ZBEE53kH2xR%2BCpZRg%2FQwx9fg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/userprofile-service/socialProfile
|
||||
response:
|
||||
body:
|
||||
string: '{"id": 3154645, "profileId": 2591602, "garminGUID": "0690cc1d-d23d-4412-b027-80fd4ed1c0f6",
|
||||
"displayName": "mtamizi", "fullName": "Matin Tamizi", "userName": "mtamizi",
|
||||
"profileImageUuid": "73240e81-6e4d-43fc-8af8-c8f6c51b3b8f", "profileImageUrlLarge":
|
||||
"https://s3.amazonaws.com/garmin-connect-prod/profile_images/73240e81-6e4d-43fc-8af8-c8f6c51b3b8f-2591602.png",
|
||||
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/685a19e9-a7be-4a11-9bf9-faca0c5d1f1a-2591602.png",
|
||||
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/6302f021-0ec7-4dc9-b0c3-d5a19bc5a08c-2591602.png",
|
||||
"location": "Ciudad de M\u00e9xico, CDMX", "facebookUrl": null, "twitterUrl":
|
||||
null, "personalWebsite": null, "motivation": null, "bio": null, "primaryActivity":
|
||||
null, "favoriteActivityTypes": [], "runningTrainingSpeed": 0.0, "cyclingTrainingSpeed":
|
||||
0.0, "favoriteCyclingActivityTypes": [], "cyclingClassification": null, "cyclingMaxAvgPower":
|
||||
0.0, "swimmingTrainingSpeed": 0.0, "profileVisibility": "private", "activityStartVisibility":
|
||||
"private", "activityMapVisibility": "public", "courseVisibility": "public",
|
||||
"activityHeartRateVisibility": "public", "activityPowerVisibility": "public",
|
||||
"badgeVisibility": "private", "showAge": false, "showWeight": false, "showHeight":
|
||||
false, "showWeightClass": false, "showAgeRange": false, "showGender": false,
|
||||
"showActivityClass": false, "showVO2Max": false, "showPersonalRecords": false,
|
||||
"showLast12Months": false, "showLifetimeTotals": false, "showUpcomingEvents":
|
||||
false, "showRecentFavorites": false, "showRecentDevice": false, "showRecentGear":
|
||||
false, "showBadges": true, "otherActivity": null, "otherPrimaryActivity":
|
||||
null, "otherMotivation": null, "userRoles": ["SCOPE_ATP_READ", "SCOPE_ATP_WRITE",
|
||||
"SCOPE_COMMUNITY_COURSE_READ", "SCOPE_COMMUNITY_COURSE_WRITE", "SCOPE_CONNECT_READ",
|
||||
"SCOPE_CONNECT_WRITE", "SCOPE_DT_CLIENT_ANALYTICS_WRITE", "SCOPE_GARMINPAY_READ",
|
||||
"SCOPE_GARMINPAY_WRITE", "SCOPE_GCOFFER_READ", "SCOPE_GCOFFER_WRITE", "SCOPE_GHS_SAMD",
|
||||
"SCOPE_GHS_UPLOAD", "SCOPE_GOLF_API_READ", "SCOPE_GOLF_API_WRITE", "SCOPE_INSIGHTS_READ",
|
||||
"SCOPE_INSIGHTS_WRITE", "SCOPE_PRODUCT_SEARCH_READ", "ROLE_CONNECTUSER", "ROLE_FITNESS_USER",
|
||||
"ROLE_WELLNESS_USER", "ROLE_OUTDOOR_USER", "ROLE_CONNECT_2_USER", "ROLE_TACX_APP_USER"],
|
||||
"nameApproved": true, "userProfileFullName": "Matin Tamizi", "makeGolfScorecardsPrivate":
|
||||
true, "allowGolfLiveScoring": false, "allowGolfScoringByConnections": true,
|
||||
"userLevel": 3, "userPoint": 117, "levelUpdateDate": "2020-12-12T15:20:38.0",
|
||||
"levelIsViewed": false, "levelPointThreshold": 140, "userPointOffset": 0,
|
||||
"userPro": false}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f27f6cc6d8ecfb4-SJC
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Sun, 06 Aug 2023 14:28:02 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=vQb1I7nl3NUQFoAFFYc8Ez1h%2Br4sa%2FdhPV%2FmnWwcDKVnx9u5zcZbfNerjOwsMYYxfu60yEfBHhJjfrZuTtiFPW6oJF0TsOcft20SZ2E4CrbOEPJuYqkHg05AR%2BKaWXab1WNJ3csk9Q%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,181 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: !!binary |
|
||||
LS0yYTllN2ZiNzAxNjU4NzI1M2M0ZmIwNWZhMGFkMzZkOQ0KQ29udGVudC1EaXNwb3NpdGlvbjog
|
||||
Zm9ybS1kYXRhOyBuYW1lPSJmaWxlIjsgZmlsZW5hbWU9IjEyMTI5MTE1NzI2X0FDVElWSVRZLmZp
|
||||
dCINCg0KDhB5UpkUAAAuRklUyeVAAAAAAAcDBIwEBIYHBIYBAoQCAoQFAoQAAQAAOXF7xhLKeD//
|
||||
////AQDbDP//BEEAADEABQIUBwAChAEBAgMBAAQBAAEAAAAAAAAAAAAAAAAAAAAAAAAAACgK////
|
||||
QgAAIAEE/QSGAgKEAAEBAQEBAhHKeD///39/QwAARwEI/QSGAwSGBASGBQSGAAECAQECAgECBgEA
|
||||
AxHKeD8MAAAAoCAAAAQAAAAJAQIAAxHKeD8MAAAAoCAAAAQAAAAJAQIARAAARgED/QSGAASGAQSG
|
||||
BBHKeD8xAAAAAwAAAEUAABUAB/0EhgMEhgABAAEBAAQBAhMBAhQBAgURyng/AAAAAAAAAP//RgAA
|
||||
FwAc/QSGAwSMBwSGCASGDwSGEASGESAHGASMHwSGAgKEBAKEBQKECgKEDQKEFQKLAAECAQECBgEC
|
||||
CQECCwECEgEAFAEKFgEAFwECGQEAHQYCHgECIAECBhHKeD85cXvG/////////////////////wAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////8BANsMKAr/////AAAA//////8A
|
||||
//8F//////////8GEcp4PwAAAAD/////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAA/////wEA2wwoCv////8AAAEE/////wD//wX//////////wYRyng/AAAA
|
||||
AP////////////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////
|
||||
/////////////wAAAgj/////AP//Bf//////////BhHKeD8AAAAA/////////////////////wAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////ZAD/////AAADCv////8A
|
||||
//8F//////////8GEcp4PwAAAAD/////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAA/////wEA4AyhCP////8AAAQM/////wD//wX//////////0cAABYAC/0E
|
||||
hgABAgEBAgIBAgMBAgQBAgUBAAYBAggBAg4BAg8BAgcRyng//////wMD/////0gAAI0ABf0EhgEE
|
||||
hgIEhgMEhgABAAgRyng/AHZ3P4CwgD//////AUkAAAIAawEEhgIEhloEhqdABwgChDEChDoChDsC
|
||||
hAABAgMBAAQBAAUBAQkBAAoBAAsBAAwBAA0BAg4BAg8BAhYBABcBABkBABoBABwBAB4BAB8BACIB
|
||||
ACMBACQBACYBACkBACoBACsBACwBAC0BAC4BAC8BADABADUBADYBADcBADgBAD8NAEABAEEBAEIB
|
||||
AEMBAEQBAEUBAEsBAEwBAE0BAFABAFEBAFIBAFMBAFQBAFUBAFcBAF4BAmABAGEBCmIBAGUBAGge
|
||||
AGsBAGwBAG0BAG4BAG8BAHABAHQBAHUBAHwBAn0BAn4BAH8BAIABAIEBAIIBAIMBAIQBAIUBAIkB
|
||||
AIoBAIsBAI0BAo4BAo8BApABAJEBAJQBAJUBAJcBAKABAKEBAKMBAKQBAqgBAKoPArEBArIBArMB
|
||||
ALQBALUBANoBANsBAAkAAAAAoKv//////38AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////9AH8AAAAgEA/wADAwQeMgABAf7/
|
||||
Af//AQEBAQEA/wEAAQAB//8BAQAAAAAAAAEAAQABAQEAAgEBAwEBCQEBAQIAAQH/AAMAAgAhBBAO
|
||||
DAYaAwId/////////////////////////wEBAQEBAQACMgQBAQIAAQIAAQAAAQMAZAEBAQAAAQAA
|
||||
KAAIBwkNCwwFBg4KAQQAAgMFHgEBAAEBSgAAAwAkHASGHQSGKQSGKgSGBAKEHwKEIAKEIQKEJQKE
|
||||
JgKEAQEAAwECBQEABgEABwEACAECDAEADQEADgEAEQEAEgEAFQEAGAECHgEAJAECKwEALAECLQEK
|
||||
LwEANAEANQECNgECOQEAOgEAPAcAPgEACsBdAAAQOgEA/ChFPv////9FA////////30A//8BtgAA
|
||||
AAABAAAyAgBUAAAAEQoBAAMEAAEAAAAAAAICAUsAAJMAQQAEjAIQBw0EhhIEChQMCkAEhkEEhkYE
|
||||
hv4ChAoChAsChBUChBkChBoChCAChCEChCIChCMChCgCizcChDgChDkChEkCi1UChAEBAgMBAAQB
|
||||
AAUBAAYBAAcBAAkBAgwBAg4BAg8BAhABAhEBChMBChgBAB8BAiQBACUHACYHACcHACkHAioBACsB
|
||||
ACwBCi0BAC4BAC8BADABADIGAjMBADQBADUBAjoBADsBAjwBAD0BAD4BAj8BAEcBAFIBAFYBAFcB
|
||||
AAvkR3ihSFJNLVBybzo2NzM3NjQAAP////8AAAAAAAAAAAAAAAAAAAAA////////////////AAD/
|
||||
////////////5AwBAHAD//8AAP///////wMA//8AAf///////////wAA////////////////////
|
||||
////////////////////////vwEB//9U5BJ+o90AAAH/////AP//////CwAAAABCZWF0cyBGaXQg
|
||||
UHJvAAAA/////wAAAAAAAAAAAAAAAAAAAAD///////////////8BAP//////////////////////
|
||||
/wAA////////BAD///8B////////////AAD/////////////////////////////////////////
|
||||
//8A//////TUiNzp7wIW//////////////9MAABPACf9BIYQBIYRBIUSBIUTBIUVBIUWBIUZBIYa
|
||||
BIYdBIYeBIYjBIYkBIUAAoQDAoQIAoQJAoQLAoQMAoQNAoQUAoQXAoMhAoQiAoQlAoMBAQICAQIE
|
||||
AQAFAQAGAQIHAQEKAQIOAQIPAQIYAQIbAQIcAQIfAQIgAQIMEcp4P0MEN+sHwQwAi70OACTADABP
|
||||
cAEAIdAeAMBdAAAQOgEAfDIpAGj+ZgCSAizrHTEWAAQzPgMBAH8CqADIAH0AAACY/gAAswAAACa2
|
||||
AUa+ASoAGf8MAP//TQAADAANAyAHCgQCAAEAAQEABQEABgEACQECCwEADAECDQEADwEAEwMAFQEA
|
||||
DVlvZ2EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/1UA/worAQAAAf8A/wD//wFOAAANAEsE
|
||||
BIYFBIUGBIUfBIYhBIYpBIU2BIZEBIVJEIVKEIVaBIb+AoQCAoQIAoQWAoQgAoRAAoQBAQADAQAH
|
||||
AQALAQIMAQANAQAOAQAPAQAQAQAVAQAXAQAYAQAbAQAcAQAdAQAeAQAiAQAjAQAkAQAlAQAmAQIn
|
||||
AQIoAQAqAQIrAQAsAQAtAQAuAQAvAQAwAQAzAQA1AQA3AQA5AQA8AQA+AQA/AQBBAQBCAQBHAQBI
|
||||
AQBLAQBMAQBOAQBPAQBRAQBSAQBTAQBVAQBWAQJZAQBdAQBeAQBoAQBrAQBsAQB0AQB4AQAOoIYB
|
||||
AP///3////9/pnQCAP////8bQQAA/////////3////9/////f////3////9/////f////3////9/
|
||||
////f/////8AAEcQbQX//zIaTQAABgAKAAAAAAH//wAA//8AAQAAAP//AR7///8B/////wD/Af8A
|
||||
AAD///8AAf///////wD///8AAP//TwAABwANEASG/gKEAwKECAKEDwKEAQECAgECBQEABwEACQEA
|
||||
CgEACwEADAEAD/////8AAMgA/////76oAQEAAQEAQAAAFAAH/QSGdAKEAwECDQEBhgEChwECiAEC
|
||||
ABHKeD+cGFYi/7BWQQAA6QABAgQNARsBBAAAEsp4P5wYVSL/sFUBHqAPCwATyng/nBhWIv+wVgEI
|
||||
AAAQABTKeD+cGFci/7BXQgAA4QAO/gSGAASGBgSGAwKEBAKEBwaECAaECQKECgKECwKEDAKEDQKE
|
||||
AgMKBQECAhTKeD9lCwAAEcp4P////////////////////////wAA////////AAAAAUMAANgADf0E
|
||||
hgIchgUghgkQhAAChAEChA8ChAYGAgoBAAsBAgwBAg0BAg4BAAMUyng/ywoAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAP//////////////////////////////////////////////////////////
|
||||
/////9gAAAD//3yJlqOxvgG+AKj/AQoAABgAFcp4P5wYViL/sFYBCkAJIAAWyng/nBhWIv+wVgEE
|
||||
XgUoABjKeD+cGFki/7BZAcAf8DcAGcp4P5wYWCL/sFgCGcp4PyUPAAAUyng/////////////////
|
||||
////////AQD///////8AAAABAxnKeD8gDwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
|
||||
////////////////////////////////////////////////////////2AABAP//fImWo7G+Ab4A
|
||||
qP8BrsgCOAAayng/cBdYIv+wWAEoZCBAABvKeD9wF1ci/7BXBRvKeD8AAAAAAAQA//8GG8p4Pzlx
|
||||
e8b/////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
|
||||
/wEA2wwoCv////8AAAD//////wD//wX//////////wYbyng/AAAAAP////////////////////8A
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AQDbDCgK/////wAAAQT/////
|
||||
AP//Bf//////////BhvKeD8AAAAA/////////////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAAAAAAAAAAAAAAAAAP//////////////////AAACCP////8A//8F//////////8GG8p4PwAA
|
||||
AAD/////////////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////
|
||||
//////9kAP////8AAAMK/////wD//wX//////////wYbyng/AAAAAP////////////////////8A
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AQDgDKEI/////wAABAz/////
|
||||
AP//Bf//////////AQwADEgBAAAAUAEbAQQAAR6gDwsBEgAAEAEKAAAYAiDKeD9CCwAAGcp4P///
|
||||
/////////////////////wIA////////AAAAAQMgyng/PgsAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
AAAAAP///////////////////////////////////////////////////////////////9gAAgD/
|
||||
/3yJlqOxvgG+AKj/BSHKeD/YAAAAMAMB//9EAACMADv9BIYCBIUDBIUFBIUGBIUHBIUVBIUYBIUa
|
||||
BIUbBIUcBIUdBIUgBIUjBIYkBIYlBIUmBIUnBIUoBIUwBIY2BIUJAoQKAoQOAoQPAoQQAoQrAoMs
|
||||
AoMtAoM3AoQ5AoQ6AoQAAQIBAQIEAQIIAQELAQAMAQANAQIRAQESAQITAQIUAQIWAQIXAQIZAQIe
|
||||
AQEfAQEhAQIiAQApAQAqAQIuAQIxAQIyAQIzAQA0AQA1AQI4AQIEIcp4P8QUAADEFAAAn9MEAKJD
|
||||
AQAAAAAA+KYVALXAGwDEFAAAAAAAAAAAAAAAAAAAAAAgTucmAAD/////xBQAAAAAAADEFAAAAAAA
|
||||
AMF1eD8AAAAAAQCn8AAAAAAAAAAAAAAAAAAA/////1oAAAAKKwAAARQAEgAZnP8AAAD/Av//AP8A
|
||||
CkcAABIAdP0EhgIEhgMEhQQEhQcEhggEhgkEhgoEhh0EhR4EhR8EhSAEhSYEhScEhSkEhjAEhk4E
|
||||
hm4gB3AEhnQEAnUEAnYEAncEAngEhHkEhHwEhn0EhpgEhqgEhbUEiLsEiP4ChAsChA4ChA8ChBQC
|
||||
hBUChBYChBcChBkChBoChCEChCIChCMChCQChCUChCoChCwChC0ChC8ChE8ChFAChFkChFoChFsC
|
||||
hGoChGsChGwChHEChIQChIUChIYChJcChJ0ChJ4ChKkChKoChLEChLIChLMChLQChL0ChL4ChMQC
|
||||
hAABAAEBAAUBAAYBABABAhEBAhIBAhMBAhgBAhsBAhwBACsBAC4BADkBAToBAVEBAFwBAl0BAl4B
|
||||
AmUBAmYBAmcBAmgBAmkBAm0BAnIBAXMBAXoCAnsCAokBAooCApYBAbgBALwBAMABAsEBAsIBAsMB
|
||||
AscBAsgBAskBAsoBAgchyng/Ecp4P////3////9/zCUAAMwlAAD/////AAAAAP///3////9/////
|
||||
f////3////9/////f///////////zCUAAFlvZ2EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
////////////////////////////////////////////////AAAAAMQUAAD//////////wAAAQD/
|
||||
//////////////8AAAMA/////////////////////////////////////wAA////////////////
|
||||
AwD/////////////AQD/////nBhwFwAACQEKK1dZ//8A/wD//yIiAP///////////39//////wAS
|
||||
ACIAAP///z7//z//AyHKeD8pJQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////////
|
||||
////////////////////////////////////////////////EgAAAP//fImWo7G+Ab4AqP9IAAAi
|
||||
AAn9BIYABIYFBIYBAoQCAQADAQAEAQAGAQIHAQIIIcp4P8wlAADBdXg/AQAAGgH//z81DQotLTJh
|
||||
OWU3ZmI3MDE2NTg3MjUzYzRmYjA1ZmEwYWQzNmQ5LS0NCg==
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '5449'
|
||||
Content-Type:
|
||||
- multipart/form-data; boundary=2a9e7fb7016587253c4fb05fa0ad36d9
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: POST
|
||||
uri: https://connectapi.garmin.com/upload-service/upload
|
||||
response:
|
||||
body:
|
||||
string: '{"detailedImportResult": {"uploadId": 212157427938, "uploadUuid": {"uuid":
|
||||
"6e56051d-1dd4-4f2c-b8ba-00a1a7d82eb3"}, "owner": 2591602, "fileSize": 5289,
|
||||
"processingTime": 36, "creationDate": "2023-09-29 01:58:19.113 GMT", "ipAddress":
|
||||
null, "fileName": "12129115726_ACTIVITY.fit", "report": null, "successes":
|
||||
[], "failures": []}}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 80e09ed13b9a2e61-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '306'
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 29 Sep 2023 01:58:19 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=quFuhjwXbu43jBRTUG6ygPyLzpTrl7hb9J0FKhbc18TnrdjIvIWV8RmYcKVuXmw6QNmCb9E7IxGdoO0h1zUCKS0JhGmlfUxPi39dpZ%2Fz80FyuPPGQSSsSBY9SmgJAWComnBkN5LiNw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
location:
|
||||
- https://connectapi.garmin.com/activity-service/activity/status/1695952699113/6e56051d1dd44f2cb8ba00a1a7d82eb3
|
||||
location-in-milliseconds:
|
||||
- '1000'
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 202
|
||||
message: Accepted
|
||||
version: 1
|
||||
@@ -1,105 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/userprofile-service/socialProfile
|
||||
response:
|
||||
body:
|
||||
string: '{"id": 3154645, "profileId": 2591602, "garminGUID": "0690cc1d-d23d-4412-b027-80fd4ed1c0f6",
|
||||
"displayName": "mtamizi", "fullName": "Matin Tamizi", "userName": "mtamizi",
|
||||
"profileImageType": "UPLOADED_PHOTO", "profileImageUrlLarge":
|
||||
"https://s3.amazonaws.com/garmin-connect-prod/profile_images/73240e81-6e4d-43fc-8af8-c8f6c51b3b8f-2591602.png",
|
||||
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/685a19e9-a7be-4a11-9bf9-faca0c5d1f1a-2591602.png",
|
||||
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/6302f021-0ec7-4dc9-b0c3-d5a19bc5a08c-2591602.png",
|
||||
"location": "Ciudad de M\u00e9xico, CDMX", "facebookUrl": null, "twitterUrl":
|
||||
null, "personalWebsite": null, "motivation": null, "bio": null, "primaryActivity":
|
||||
null, "favoriteActivityTypes": [], "runningTrainingSpeed": 0.0, "cyclingTrainingSpeed":
|
||||
0.0, "favoriteCyclingActivityTypes": [], "cyclingClassification": null, "cyclingMaxAvgPower":
|
||||
0.0, "swimmingTrainingSpeed": 0.0, "profileVisibility": "private", "activityStartVisibility":
|
||||
"private", "activityMapVisibility": "public", "courseVisibility": "public",
|
||||
"activityHeartRateVisibility": "public", "activityPowerVisibility": "public",
|
||||
"badgeVisibility": "private", "showAge": false, "showWeight": false, "showHeight":
|
||||
false, "showWeightClass": false, "showAgeRange": false, "showGender": false,
|
||||
"showActivityClass": false, "showVO2Max": false, "showPersonalRecords": false,
|
||||
"showLast12Months": false, "showLifetimeTotals": false, "showUpcomingEvents":
|
||||
false, "showRecentFavorites": false, "showRecentDevice": false, "showRecentGear":
|
||||
false, "showBadges": true, "otherActivity": null, "otherPrimaryActivity":
|
||||
null, "otherMotivation": null, "userRoles": ["SCOPE_ATP_READ", "SCOPE_ATP_WRITE",
|
||||
"SCOPE_COMMUNITY_COURSE_READ", "SCOPE_COMMUNITY_COURSE_WRITE", "SCOPE_CONNECT_READ",
|
||||
"SCOPE_CONNECT_WRITE", "SCOPE_DT_CLIENT_ANALYTICS_WRITE", "SCOPE_GARMINPAY_READ",
|
||||
"SCOPE_GARMINPAY_WRITE", "SCOPE_GCOFFER_READ", "SCOPE_GCOFFER_WRITE", "SCOPE_GHS_SAMD",
|
||||
"SCOPE_GHS_UPLOAD", "SCOPE_GOLF_API_READ", "SCOPE_GOLF_API_WRITE", "SCOPE_INSIGHTS_READ",
|
||||
"SCOPE_INSIGHTS_WRITE", "SCOPE_PRODUCT_SEARCH_READ", "ROLE_CONNECTUSER", "ROLE_FITNESS_USER",
|
||||
"ROLE_WELLNESS_USER", "ROLE_OUTDOOR_USER", "ROLE_CONNECT_2_USER", "ROLE_TACX_APP_USER"],
|
||||
"nameApproved": true, "userProfileFullName": "Matin Tamizi", "makeGolfScorecardsPrivate":
|
||||
true, "allowGolfLiveScoring": false, "allowGolfScoringByConnections": true,
|
||||
"userLevel": 3, "userPoint": 118, "levelUpdateDate": "2020-12-12T15:20:38.0",
|
||||
"levelIsViewed": false, "levelPointThreshold": 140, "userPointOffset": 0,
|
||||
"userPro": false}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8151c9a72daf49d9-MFE
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 12 Oct 2023 19:35:44 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=R8lDBzpYOR3%2FKDhkcX7x9WXPLE2Ta1MmqgZzYqack%2F9HmkidgIW8z0cDhgWQ6rWprYuN3oyv%2FS5AGsx8HRk8jJf7qR%2B6ogw0VgKh%2BXZXH83duGw3x3g492pKPeIj6hazTlIxSeK6HA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,92 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/userprofile-service/userprofile/user-settings
|
||||
response:
|
||||
body:
|
||||
string: '{"id": 2591602, "userData": {"gender": "MALE", "weight": 83000.0, "height":
|
||||
182.0, "timeFormat": "time_twenty_four_hr", "birthDate": "2000-01-01", "measurementSystem":
|
||||
"metric", "activityLevel": null, "handedness": "RIGHT", "powerFormat": {"formatId":
|
||||
30, "formatKey": "watt", "minFraction": 0, "maxFraction": 0, "groupingUsed":
|
||||
true, "displayFormat": null}, "heartRateFormat": {"formatId": 21, "formatKey":
|
||||
"bpm", "minFraction": 0, "maxFraction": 0, "groupingUsed": false, "displayFormat":
|
||||
null}, "firstDayOfWeek": {"dayId": 2, "dayName": "sunday", "sortOrder": 2,
|
||||
"isPossibleFirstDay": true}, "vo2MaxRunning": 45.0, "vo2MaxCycling": null,
|
||||
"lactateThresholdSpeed": 0.34722125000000004, "lactateThresholdHeartRate":
|
||||
null, "diveNumber": null, "intensityMinutesCalcMethod": "AUTO", "moderateIntensityMinutesHrZone":
|
||||
3, "vigorousIntensityMinutesHrZone": 4, "hydrationMeasurementUnit": "milliliter",
|
||||
"hydrationContainers": [], "hydrationAutoGoalEnabled": true, "firstbeatMaxStressScore":
|
||||
null, "firstbeatCyclingLtTimestamp": null, "firstbeatRunningLtTimestamp":
|
||||
1044719868, "thresholdHeartRateAutoDetected": true, "ftpAutoDetected": null,
|
||||
"trainingStatusPausedDate": null, "weatherLocation": null, "golfDistanceUnit":
|
||||
"statute_us", "golfElevationUnit": null, "golfSpeedUnit": null, "externalBottomTime":
|
||||
null}, "userSleep": {"sleepTime": 80400, "defaultSleepTime": false, "wakeTime":
|
||||
24000, "defaultWakeTime": false}, "connectDate": null, "sourceType": null}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8151c6bdebf649df-MFE
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 12 Oct 2023 19:33:45 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=Mi%2Fn%2B7ExcrekhLBUA3vIWTc6xe5E0cMSeFdwGALv%2FKUypkIKnfCikzoAsV5BFgVarsRYtmB0Um640X9SA9p0dMp%2F1saQUEs7VRjVvLn4W0I2%2FLTw5qKr6A1w%2BN8x3SWzFXZX5dojfA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,116 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
referer:
|
||||
- https://sso.garmin.com/sso/verifyMFA/loginEnterMfaCode?id=gauth-widget&embedWidget=true&gauthHost=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&service=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&source=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountLoginUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed&redirectAfterAccountCreationUrl=https%3A%2F%2Fsso.garmin.com%2Fsso%2Fembed
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/userprofile-service/userprofile/user-settings
|
||||
response:
|
||||
body:
|
||||
string: '{"id": 2591602, "userData": {"gender": "MALE", "weight": 83000.0, "height":
|
||||
182.0, "timeFormat": "time_twenty_four_hr", "birthDate": "2000-01-01", "measurementSystem":
|
||||
"metric", "activityLevel": null, "handedness": "RIGHT", "powerFormat": {"formatId":
|
||||
30, "formatKey": "watt", "minFraction": 0, "maxFraction": 0, "groupingUsed":
|
||||
true, "displayFormat": null}, "heartRateFormat": {"formatId": 21, "formatKey":
|
||||
"bpm", "minFraction": 0, "maxFraction": 0, "groupingUsed": false, "displayFormat":
|
||||
null}, "firstDayOfWeek": {"dayId": 2, "dayName": "sunday", "sortOrder": 2,
|
||||
"isPossibleFirstDay": true}, "vo2MaxRunning": 45.0, "vo2MaxCycling": null,
|
||||
"lactateThresholdSpeed": 0.34722125000000004, "lactateThresholdHeartRate":
|
||||
null, "diveNumber": null, "intensityMinutesCalcMethod": "AUTO", "moderateIntensityMinutesHrZone":
|
||||
3, "vigorousIntensityMinutesHrZone": 4, "hydrationMeasurementUnit": "milliliter",
|
||||
"hydrationContainers": [], "hydrationAutoGoalEnabled": true, "firstbeatMaxStressScore":
|
||||
null, "firstbeatCyclingLtTimestamp": null, "firstbeatRunningLtTimestamp":
|
||||
1044719868, "thresholdHeartRateAutoDetected": true, "ftpAutoDetected": null,
|
||||
"trainingStatusPausedDate": null, "weatherLocation": null, "golfDistanceUnit":
|
||||
"statute_us", "golfElevationUnit": null, "golfSpeedUnit": null, "externalBottomTime":
|
||||
null}, "userSleep": {"sleepTime": 80400, "defaultSleepTime": false, "wakeTime":
|
||||
24000, "defaultWakeTime": false}, "connectDate": null, "sourceType": null,
|
||||
"userSleepWindows": [{"sleepWindowFrequency": "SUNDAY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800},
|
||||
{"sleepWindowFrequency": "MONDAY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800},
|
||||
{"sleepWindowFrequency": "TUESDAY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800},
|
||||
{"sleepWindowFrequency": "WEDNESDAY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800},
|
||||
{"sleepWindowFrequency": "THURSDAY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800},
|
||||
{"sleepWindowFrequency": "FRIDAY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800},
|
||||
{"sleepWindowFrequency": "SATURDAY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800},
|
||||
{"sleepWindowFrequency": "DAILY",
|
||||
"startSleepTimeSecondsFromMidnight": 77400,
|
||||
"endSleepTimeSecondsFromMidnight": 19800}]}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 8151c6bdebf649df-MFE
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 12 Oct 2023 19:33:45 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=Mi%2Fn%2B7ExcrekhLBUA3vIWTc6xe5E0cMSeFdwGALv%2FKUypkIKnfCikzoAsV5BFgVarsRYtmB0Um640X9SA9p0dMp%2F1saQUEs7VRjVvLn4W0I2%2FLTw5qKr6A1w%2BN8x3SWzFXZX5dojfA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,91 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/userprofile-service/socialProfile
|
||||
response:
|
||||
body:
|
||||
string: '{"id": 3154645, "profileId": 2591602, "garminGUID": "0690cc1d-d23d-4412-b027-80fd4ed1c0f6",
|
||||
"displayName": "mtamizi", "fullName": "Matin Tamizi", "userName": "mtamizi",
|
||||
"profileImageUuid": "73240e81-6e4d-43fc-8af8-c8f6c51b3b8f", "profileImageUrlLarge":
|
||||
"https://s3.amazonaws.com/garmin-connect-prod/profile_images/73240e81-6e4d-43fc-8af8-c8f6c51b3b8f-2591602.png",
|
||||
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/685a19e9-a7be-4a11-9bf9-faca0c5d1f1a-2591602.png",
|
||||
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/6302f021-0ec7-4dc9-b0c3-d5a19bc5a08c-2591602.png",
|
||||
"location": "Ciudad de M\u00e9xico, CDMX", "facebookUrl": null, "twitterUrl":
|
||||
null, "personalWebsite": null, "motivation": null, "bio": null, "primaryActivity":
|
||||
null, "favoriteActivityTypes": [], "runningTrainingSpeed": 0.0, "cyclingTrainingSpeed":
|
||||
0.0, "favoriteCyclingActivityTypes": [], "cyclingClassification": null, "cyclingMaxAvgPower":
|
||||
0.0, "swimmingTrainingSpeed": 0.0, "profileVisibility": "private", "activityStartVisibility":
|
||||
"private", "activityMapVisibility": "public", "courseVisibility": "public",
|
||||
"activityHeartRateVisibility": "public", "activityPowerVisibility": "public",
|
||||
"badgeVisibility": "private", "showAge": false, "showWeight": false, "showHeight":
|
||||
false, "showWeightClass": false, "showAgeRange": false, "showGender": false,
|
||||
"showActivityClass": false, "showVO2Max": false, "showPersonalRecords": false,
|
||||
"showLast12Months": false, "showLifetimeTotals": false, "showUpcomingEvents":
|
||||
false, "showRecentFavorites": false, "showRecentDevice": false, "showRecentGear":
|
||||
false, "showBadges": true, "otherActivity": null, "otherPrimaryActivity":
|
||||
null, "otherMotivation": null, "userRoles": ["SCOPE_ATP_READ", "SCOPE_ATP_WRITE",
|
||||
"SCOPE_COMMUNITY_COURSE_READ", "SCOPE_COMMUNITY_COURSE_WRITE", "SCOPE_CONNECT_READ",
|
||||
"SCOPE_CONNECT_WRITE", "SCOPE_DT_CLIENT_ANALYTICS_WRITE", "SCOPE_GARMINPAY_READ",
|
||||
"SCOPE_GARMINPAY_WRITE", "SCOPE_GCOFFER_READ", "SCOPE_GCOFFER_WRITE", "SCOPE_GHS_SAMD",
|
||||
"SCOPE_GHS_UPLOAD", "SCOPE_GOLF_API_READ", "SCOPE_GOLF_API_WRITE", "SCOPE_INSIGHTS_READ",
|
||||
"SCOPE_INSIGHTS_WRITE", "SCOPE_PRODUCT_SEARCH_READ", "ROLE_CONNECTUSER", "ROLE_FITNESS_USER",
|
||||
"ROLE_WELLNESS_USER", "ROLE_OUTDOOR_USER", "ROLE_CONNECT_2_USER", "ROLE_TACX_APP_USER"],
|
||||
"nameApproved": true, "userProfileFullName": "Matin Tamizi", "makeGolfScorecardsPrivate":
|
||||
true, "allowGolfLiveScoring": false, "allowGolfScoringByConnections": true,
|
||||
"userLevel": 3, "userPoint": 117, "levelUpdateDate": "2020-12-12T15:20:38.0",
|
||||
"levelIsViewed": false, "levelPointThreshold": 140, "userPointOffset": 0,
|
||||
"userPro": false}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12d41c38a11557-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:54:20 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=G2IB1TvEJWwpf1qx1pmxuSXoRW%2FSZEU8HyTOlPTBTCyG2dipRZTZe8A9ulowoM3j%2F6hYqLLs1uU2ifU%2FnZpB2j2uzj6ePqBlmx4IjtlABarp0HGJAvv98zpC%2F5t8DFDPLSS58dBYsA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,169 +0,0 @@
|
||||
import gzip
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from requests import Session
|
||||
|
||||
from garth.auth_tokens import OAuth1Token, OAuth2Token
|
||||
from garth.http import Client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def session():
|
||||
return Session()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def client(session) -> Client:
|
||||
return Client(session=session)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def oauth1_token_dict() -> dict:
|
||||
return dict(
|
||||
oauth_token="7fdff19aa9d64dda83e9d7858473aed1",
|
||||
oauth_token_secret="49919d7c4c8241ac93fb4345886fbcea",
|
||||
mfa_token="ab316f8640f3491f999f3298f3d6f1bb",
|
||||
mfa_expiration_timestamp="2024-08-02 05:56:10.000",
|
||||
domain="garmin.com",
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def oauth1_token(oauth1_token_dict) -> OAuth1Token:
|
||||
return OAuth1Token(**oauth1_token_dict)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def oauth2_token_dict() -> dict:
|
||||
return dict(
|
||||
scope="CONNECT_READ CONNECT_WRITE",
|
||||
jti="foo",
|
||||
token_type="Bearer",
|
||||
access_token="bar",
|
||||
refresh_token="baz",
|
||||
expires_in=3599,
|
||||
refresh_token_expires_in=7199,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def oauth2_token(oauth2_token_dict: dict) -> OAuth2Token:
|
||||
token = OAuth2Token(
|
||||
expires_at=int(time.time() + 3599),
|
||||
refresh_token_expires_at=int(time.time() + 7199),
|
||||
**oauth2_token_dict,
|
||||
)
|
||||
return token
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def authed_client(
|
||||
oauth1_token: OAuth1Token, oauth2_token: OAuth2Token
|
||||
) -> Client:
|
||||
client = Client()
|
||||
try:
|
||||
client.load(os.environ["GARTH_HOME"])
|
||||
except KeyError:
|
||||
client.configure(oauth1_token=oauth1_token, oauth2_token=oauth2_token)
|
||||
assert client.oauth2_token and isinstance(client.oauth2_token, OAuth2Token)
|
||||
assert not client.oauth2_token.expired
|
||||
return client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vcr(vcr):
|
||||
if "GARTH_HOME" not in os.environ:
|
||||
vcr.record_mode = "none"
|
||||
return vcr
|
||||
|
||||
|
||||
def sanitize_cookie(cookie_value) -> str:
|
||||
return re.sub(r"=[^;]*", "=SANITIZED", cookie_value)
|
||||
|
||||
|
||||
def sanitize_request(request):
|
||||
if request.body:
|
||||
try:
|
||||
body = request.body.decode("utf8")
|
||||
except UnicodeDecodeError:
|
||||
...
|
||||
else:
|
||||
for key in ["username", "password", "refresh_token"]:
|
||||
body = re.sub(key + r"=[^&]*", f"{key}=SANITIZED", body)
|
||||
request.body = body.encode("utf8")
|
||||
|
||||
if "Cookie" in request.headers:
|
||||
cookies = request.headers["Cookie"].split("; ")
|
||||
sanitized_cookies = [sanitize_cookie(cookie) for cookie in cookies]
|
||||
request.headers["Cookie"] = "; ".join(sanitized_cookies)
|
||||
return request
|
||||
|
||||
|
||||
def sanitize_response(response):
|
||||
try:
|
||||
encoding = response["headers"].pop("Content-Encoding")
|
||||
except KeyError:
|
||||
...
|
||||
else:
|
||||
if encoding[0] == "gzip":
|
||||
body = response["body"]["string"]
|
||||
buffer = io.BytesIO(body)
|
||||
try:
|
||||
body = gzip.GzipFile(fileobj=buffer).read()
|
||||
except gzip.BadGzipFile: # pragma: no cover
|
||||
...
|
||||
else:
|
||||
response["body"]["string"] = body
|
||||
|
||||
for key in ["set-cookie", "Set-Cookie"]:
|
||||
if key in response["headers"]:
|
||||
cookies = response["headers"][key]
|
||||
sanitized_cookies = [sanitize_cookie(cookie) for cookie in cookies]
|
||||
response["headers"][key] = sanitized_cookies
|
||||
|
||||
try:
|
||||
body = response["body"]["string"].decode("utf8")
|
||||
except UnicodeDecodeError:
|
||||
pass
|
||||
else:
|
||||
patterns = [
|
||||
"oauth_token=[^&]*",
|
||||
"oauth_token_secret=[^&]*",
|
||||
"mfa_token=[^&]*",
|
||||
]
|
||||
for pattern in patterns:
|
||||
body = re.sub(pattern, pattern.split("=")[0] + "=SANITIZED", body)
|
||||
try:
|
||||
body_json = json.loads(body)
|
||||
except json.JSONDecodeError:
|
||||
pass
|
||||
else:
|
||||
if body_json and isinstance(body_json, dict):
|
||||
for field in [
|
||||
"access_token",
|
||||
"refresh_token",
|
||||
"jti",
|
||||
"consumer_key",
|
||||
"consumer_secret",
|
||||
]:
|
||||
if field in body_json:
|
||||
body_json[field] = "SANITIZED"
|
||||
|
||||
body = json.dumps(body_json)
|
||||
response["body"]["string"] = body.encode("utf8")
|
||||
|
||||
return response
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def vcr_config():
|
||||
return {
|
||||
"filter_headers": [("Authorization", "Bearer SANITIZED")],
|
||||
"before_record_request": sanitize_request,
|
||||
"before_record_response": sanitize_response,
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/bodyBattery/events/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '[{"event": {"eventType": "sleep", "eventStartTimeGmt": "2023-07-19T21:30:00.000",
|
||||
"timezoneOffset": -25200000, "durationInMilliseconds": 28800000, "bodyBatteryImpact": 35,
|
||||
"feedbackType": "good_sleep", "shortFeedback": "Good sleep restored your Body Battery"},
|
||||
"activityName": null, "activityType": null, "activityId": null, "averageStress": 15.5,
|
||||
"stressValuesArray": [[1689811800000, 12], [1689812100000, 18], [1689812400000, 15]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0], [1689812100000, "charging", 48, 1.0],
|
||||
[1689812400000, "charging", 52, 1.0], [1689840600000, "draining", 85, 1.0]]}]'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 20 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,90 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/bodyBattery/events/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '[{"event": {"eventType": "sleep", "eventStartTimeGmt": "2023-07-19T21:30:00.000",
|
||||
"timezoneOffset": -25200000, "durationInMilliseconds": 28800000, "bodyBatteryImpact": 35,
|
||||
"feedbackType": "good_sleep", "shortFeedback": "Good sleep restored your Body Battery"},
|
||||
"activityName": null, "activityType": null, "activityId": null, "averageStress": 15.5,
|
||||
"stressValuesArray": [[1689811800000, 12], [1689812100000, 18]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0], [1689840600000, "draining", 85, 1.0]]}]'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 20 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/bodyBattery/events/2023-07-19
|
||||
response:
|
||||
body:
|
||||
string: '[]'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 19 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/bodyBattery/events/2023-07-18
|
||||
response:
|
||||
body:
|
||||
string: '[{"event": null, "activityName": "Running", "activityType": "running",
|
||||
"activityId": "12345", "averageStress": 45.2, "stressValuesArray": [],
|
||||
"bodyBatteryValuesArray": [[1689667200000, "draining", 75, 1.0], [1689670800000, "draining", 65, 1.0]]}]'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Tue, 18 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,33 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/dailyStress/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '{"userProfilePK": 2591602, "calendarDate": "2023-07-20",
|
||||
"startTimestampGMT": "2023-07-20T06:00:00.000Z", "endTimestampGMT": "2023-07-21T05:59:59.999Z",
|
||||
"startTimestampLocal": "2023-07-19T23:00:00.000Z", "endTimestampLocal": "2023-07-20T22:59:59.999Z",
|
||||
"maxStressLevel": 0, "avgStressLevel": 0, "stressChartValueOffset": 0, "stressChartYAxisOrigin": 0,
|
||||
"stressValuesArray": [], "bodyBatteryValuesArray": []}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 20 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,41 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/dailyStress/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '{"userProfilePK": 2591602, "calendarDate": "2023-07-20",
|
||||
"startTimestampGMT": "2023-07-20T06:00:00.000Z", "endTimestampGMT": "2023-07-21T05:59:59.999Z",
|
||||
"startTimestampLocal": "2023-07-19T23:00:00.000Z", "endTimestampLocal": "2023-07-20T22:59:59.999Z",
|
||||
"maxStressLevel": 85, "avgStressLevel": 25, "stressChartValueOffset": 0, "stressChartYAxisOrigin": 0,
|
||||
"stressValuesArray": [[1689811800000, 12], [1689812100000, 18], [1689812400000, 15],
|
||||
[1689815700000, 45], [1689819300000, 85], [1689822900000, 35], [1689826500000, 20],
|
||||
[1689830100000, 15], [1689833700000, 25], [1689837300000, 30]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0], [1689812100000, "charging", 48, 1.0],
|
||||
[1689812400000, "charging", 52, 1.0], [1689815700000, "charging", 65, 1.0],
|
||||
[1689819300000, "draining", 85, 1.0], [1689822900000, "draining", 75, 1.0],
|
||||
[1689826500000, "draining", 65, 1.0], [1689830100000, "draining", 55, 1.0],
|
||||
[1689833700000, "draining", 45, 1.0], [1689837300000, "draining", 35, 1.0],
|
||||
[1689840900000, "draining", 25, 1.0]]}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 20 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,29 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/dailyStress/2020-01-01
|
||||
response:
|
||||
body:
|
||||
string: 'null'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Wed, 01 Jan 2020 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,93 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/dailyStress/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '{"userProfilePK": 2591602, "calendarDate": "2023-07-20",
|
||||
"startTimestampGMT": "2023-07-20T06:00:00.000Z", "endTimestampGMT": "2023-07-21T05:59:59.999Z",
|
||||
"startTimestampLocal": "2023-07-19T23:00:00.000Z", "endTimestampLocal": "2023-07-20T22:59:59.999Z",
|
||||
"maxStressLevel": 85, "avgStressLevel": 25, "stressChartValueOffset": 0, "stressChartYAxisOrigin": 0,
|
||||
"stressValuesArray": [[1689811800000, 12], [1689812100000, 18]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0], [1689840900000, "draining", 25, 1.0]]}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Thu, 20 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/dailyStress/2023-07-19
|
||||
response:
|
||||
body:
|
||||
string: '{"userProfilePK": 2591602, "calendarDate": "2023-07-19",
|
||||
"startTimestampGMT": "2023-07-19T06:00:00.000Z", "endTimestampGMT": "2023-07-20T05:59:59.999Z",
|
||||
"startTimestampLocal": "2023-07-18T23:00:00.000Z", "endTimestampLocal": "2023-07-19T22:59:59.999Z",
|
||||
"maxStressLevel": 65, "avgStressLevel": 30, "stressChartValueOffset": 0, "stressChartYAxisOrigin": 0,
|
||||
"stressValuesArray": [[1689725400000, 25], [1689729000000, 40]],
|
||||
"bodyBatteryValuesArray": [[1689725400000, "draining", 80, 1.0], [1689754200000, "charging", 30, 1.0]]}'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Wed, 19 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/dailyStress/2023-07-18
|
||||
response:
|
||||
body:
|
||||
string: 'null'
|
||||
headers:
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Tue, 18 Jul 2023 12:00:00 GMT
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,58 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/weight-service/weight/dayview/2025-06-15
|
||||
response:
|
||||
body:
|
||||
string: '{"startDate": "2025-06-15", "endDate": "2025-06-15", "dateWeightList":
|
||||
[{"samplePk": 1749996902851, "date": 1749975276000, "calendarDate": "2025-06-15",
|
||||
"weight": 59720.0, "bmi": 22.799999237060547, "bodyFat": 19.3, "bodyWater":
|
||||
58.9, "boneMass": 3539, "muscleMass": 26979, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null, "sourceType": "INDEX_SCALE", "timestampGMT": 1749996876000,
|
||||
"weightDelta": 200.00000000000284}], "totalAverage": {"from": 1749945600000,
|
||||
"until": 1750031999999, "weight": 59720.0, "bmi": 22.799999237060547, "bodyFat":
|
||||
19.3, "bodyWater": 58.9, "boneMass": 3539, "muscleMass": 26979, "physiqueRating":
|
||||
null, "visceralFat": null, "metabolicAge": null}}'
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 9505ceb74f5fd875-QRO
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sun, 15 Jun 2025 23:22:05 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=UH9A8geP4FHMJjd6y07FBmPslL9A%2B3JKPZa2WHai0fGEwDokhD2YqXsG155VIgSjGPY8Av3IYcI%2B%2FH%2B38GY15TN4THIsNucuROuGSc3NlFY1c%2BmSER4pGCfCqwF1BH1cmMr%2Fu8TKFKFjkS8bzk1P%2FM4l%2Bg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,62 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/weight-service/weight/dayview/2025-06-14
|
||||
response:
|
||||
body:
|
||||
string: '{"startDate": "2025-06-14", "endDate": "2025-06-14", "dateWeightList":
|
||||
[{"samplePk": 1749948744411, "date": 1749927125175, "calendarDate": "2025-06-14",
|
||||
"weight": 59500.0, "bmi": null, "bodyFat": null, "bodyWater": null, "boneMass":
|
||||
null, "muscleMass": null, "physiqueRating": null, "visceralFat": null, "metabolicAge":
|
||||
null, "sourceType": "MANUAL", "timestampGMT": 1749948725175, "weightDelta":
|
||||
399.9999999999986}, {"samplePk": 1749909217098, "date": 1749887580000, "calendarDate":
|
||||
"2025-06-14", "weight": 59130.0, "bmi": 22.5, "bodyFat": 20.3, "bodyWater":
|
||||
58.2, "boneMass": 3430, "muscleMass": 26840, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null, "sourceType": "INDEX_SCALE", "timestampGMT": 1749909180000,
|
||||
"weightDelta": -100.00000000000142}], "totalAverage": {"from": 1749859200000,
|
||||
"until": 1749945599999, "weight": 59315.0, "bmi": 22.5, "bodyFat": 20.3, "bodyWater":
|
||||
58.2, "boneMass": 3430, "muscleMass": 26840, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null}}'
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 95064313addc55c3-QRO
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 16 Jun 2025 00:41:31 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=4k83lvSQ0EaF3v3SPJQfFUMAz%2FRDzu%2BJpC4JQGBU9eLNTYcx5pUfnIWwmgS0AdXoavdcbR4CvPW0TyI%2BRQBpV%2FQo3qe1GcGAaUzrQq5KRBbEpkHZseRhz1jmcUv17rnmwMucrfKf9wMne477n%2BBT0wPNgg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,53 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/weight-service/weight/dayview/2020-01-01
|
||||
response:
|
||||
body:
|
||||
string: '{"startDate": "2020-01-01", "endDate": "2020-01-01", "dateWeightList":
|
||||
[], "totalAverage": {"from": 1577836800000, "until": 1577923199999, "weight":
|
||||
null, "bmi": null, "bodyFat": null, "bodyWater": null, "boneMass": null, "muscleMass":
|
||||
null, "physiqueRating": null, "visceralFat": null, "metabolicAge": null}}'
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 950644801ca4d9f7-QRO
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 16 Jun 2025 00:42:29 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=BJIcx9Zh1zt1cLoKMZAVgYYQfsvpXBQP04VMD2f4iMyfjHCnNu5Sh%2BdA7NcZ2FkaJ7%2Bxw8up1nDASiKuMf8XqsAi1BYG2kqRNBvEQQEkvhY0L63y%2BXwDbb%2BUcurig3gGRUI3oNq%2F8II2iL62j6q0iLJ9pA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,222 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '{"userProfilePk": 2591602, "hrvSummary": {"calendarDate": "2023-07-20",
|
||||
"weeklyAvg": 39, "lastNightAvg": 42, "lastNight5MinHigh": 66, "baseline":
|
||||
{"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue": 0.25},
|
||||
"status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp":
|
||||
"2023-07-20T12:14:11.898"}, "hrvReadings": [{"hrvValue": 54, "readingTimeGMT":
|
||||
"2023-07-20T05:29:48.0", "readingTimeLocal": "2023-07-19T23:29:48.0"}, {"hrvValue":
|
||||
56, "readingTimeGMT": "2023-07-20T05:34:48.0", "readingTimeLocal": "2023-07-19T23:34:48.0"},
|
||||
{"hrvValue": 51, "readingTimeGMT": "2023-07-20T05:39:48.0", "readingTimeLocal":
|
||||
"2023-07-19T23:39:48.0"}, {"hrvValue": 50, "readingTimeGMT": "2023-07-20T05:44:48.0",
|
||||
"readingTimeLocal": "2023-07-19T23:44:48.0"}, {"hrvValue": 55, "readingTimeGMT":
|
||||
"2023-07-20T05:49:48.0", "readingTimeLocal": "2023-07-19T23:49:48.0"}, {"hrvValue":
|
||||
55, "readingTimeGMT": "2023-07-20T05:54:48.0", "readingTimeLocal": "2023-07-19T23:54:48.0"},
|
||||
{"hrvValue": 55, "readingTimeGMT": "2023-07-20T05:59:48.0", "readingTimeLocal":
|
||||
"2023-07-19T23:59:48.0"}, {"hrvValue": 43, "readingTimeGMT": "2023-07-20T06:04:48.0",
|
||||
"readingTimeLocal": "2023-07-20T00:04:48.0"}, {"hrvValue": 53, "readingTimeGMT":
|
||||
"2023-07-20T06:09:48.0", "readingTimeLocal": "2023-07-20T00:09:48.0"}, {"hrvValue":
|
||||
53, "readingTimeGMT": "2023-07-20T06:14:48.0", "readingTimeLocal": "2023-07-20T00:14:48.0"},
|
||||
{"hrvValue": 41, "readingTimeGMT": "2023-07-20T06:19:48.0", "readingTimeLocal":
|
||||
"2023-07-20T00:19:48.0"}, {"hrvValue": 47, "readingTimeGMT": "2023-07-20T06:24:48.0",
|
||||
"readingTimeLocal": "2023-07-20T00:24:48.0"}, {"hrvValue": 45, "readingTimeGMT":
|
||||
"2023-07-20T06:29:48.0", "readingTimeLocal": "2023-07-20T00:29:48.0"}, {"hrvValue":
|
||||
38, "readingTimeGMT": "2023-07-20T06:34:48.0", "readingTimeLocal": "2023-07-20T00:34:48.0"},
|
||||
{"hrvValue": 33, "readingTimeGMT": "2023-07-20T06:39:48.0", "readingTimeLocal":
|
||||
"2023-07-20T00:39:48.0"}, {"hrvValue": 43, "readingTimeGMT": "2023-07-20T06:44:48.0",
|
||||
"readingTimeLocal": "2023-07-20T00:44:48.0"}, {"hrvValue": 49, "readingTimeGMT":
|
||||
"2023-07-20T06:49:48.0", "readingTimeLocal": "2023-07-20T00:49:48.0"}, {"hrvValue":
|
||||
43, "readingTimeGMT": "2023-07-20T06:54:48.0", "readingTimeLocal": "2023-07-20T00:54:48.0"},
|
||||
{"hrvValue": 47, "readingTimeGMT": "2023-07-20T06:59:48.0", "readingTimeLocal":
|
||||
"2023-07-20T00:59:48.0"}, {"hrvValue": 38, "readingTimeGMT": "2023-07-20T07:04:48.0",
|
||||
"readingTimeLocal": "2023-07-20T01:04:48.0"}, {"hrvValue": 39, "readingTimeGMT":
|
||||
"2023-07-20T07:09:48.0", "readingTimeLocal": "2023-07-20T01:09:48.0"}, {"hrvValue":
|
||||
33, "readingTimeGMT": "2023-07-20T07:14:48.0", "readingTimeLocal": "2023-07-20T01:14:48.0"},
|
||||
{"hrvValue": 43, "readingTimeGMT": "2023-07-20T07:19:48.0", "readingTimeLocal":
|
||||
"2023-07-20T01:19:48.0"}, {"hrvValue": 45, "readingTimeGMT": "2023-07-20T07:24:48.0",
|
||||
"readingTimeLocal": "2023-07-20T01:24:48.0"}, {"hrvValue": 36, "readingTimeGMT":
|
||||
"2023-07-20T07:29:48.0", "readingTimeLocal": "2023-07-20T01:29:48.0"}, {"hrvValue":
|
||||
47, "readingTimeGMT": "2023-07-20T07:34:48.0", "readingTimeLocal": "2023-07-20T01:34:48.0"},
|
||||
{"hrvValue": 46, "readingTimeGMT": "2023-07-20T07:39:48.0", "readingTimeLocal":
|
||||
"2023-07-20T01:39:48.0"}, {"hrvValue": 53, "readingTimeGMT": "2023-07-20T07:44:48.0",
|
||||
"readingTimeLocal": "2023-07-20T01:44:48.0"}, {"hrvValue": 35, "readingTimeGMT":
|
||||
"2023-07-20T07:49:48.0", "readingTimeLocal": "2023-07-20T01:49:48.0"}, {"hrvValue":
|
||||
28, "readingTimeGMT": "2023-07-20T07:54:48.0", "readingTimeLocal": "2023-07-20T01:54:48.0"},
|
||||
{"hrvValue": 30, "readingTimeGMT": "2023-07-20T07:59:48.0", "readingTimeLocal":
|
||||
"2023-07-20T01:59:48.0"}, {"hrvValue": 38, "readingTimeGMT": "2023-07-20T08:04:48.0",
|
||||
"readingTimeLocal": "2023-07-20T02:04:48.0"}, {"hrvValue": 49, "readingTimeGMT":
|
||||
"2023-07-20T08:09:48.0", "readingTimeLocal": "2023-07-20T02:09:48.0"}, {"hrvValue":
|
||||
46, "readingTimeGMT": "2023-07-20T08:14:48.0", "readingTimeLocal": "2023-07-20T02:14:48.0"},
|
||||
{"hrvValue": 31, "readingTimeGMT": "2023-07-20T08:19:48.0", "readingTimeLocal":
|
||||
"2023-07-20T02:19:48.0"}, {"hrvValue": 29, "readingTimeGMT": "2023-07-20T08:24:48.0",
|
||||
"readingTimeLocal": "2023-07-20T02:24:48.0"}, {"hrvValue": 32, "readingTimeGMT":
|
||||
"2023-07-20T08:29:48.0", "readingTimeLocal": "2023-07-20T02:29:48.0"}, {"hrvValue":
|
||||
27, "readingTimeGMT": "2023-07-20T08:34:48.0", "readingTimeLocal": "2023-07-20T02:34:48.0"},
|
||||
{"hrvValue": 31, "readingTimeGMT": "2023-07-20T08:39:48.0", "readingTimeLocal":
|
||||
"2023-07-20T02:39:48.0"}, {"hrvValue": 33, "readingTimeGMT": "2023-07-20T08:44:48.0",
|
||||
"readingTimeLocal": "2023-07-20T02:44:48.0"}, {"hrvValue": 32, "readingTimeGMT":
|
||||
"2023-07-20T08:49:48.0", "readingTimeLocal": "2023-07-20T02:49:48.0"}, {"hrvValue":
|
||||
29, "readingTimeGMT": "2023-07-20T08:54:48.0", "readingTimeLocal": "2023-07-20T02:54:48.0"},
|
||||
{"hrvValue": 35, "readingTimeGMT": "2023-07-20T08:59:48.0", "readingTimeLocal":
|
||||
"2023-07-20T02:59:48.0"}, {"hrvValue": 30, "readingTimeGMT": "2023-07-20T09:04:48.0",
|
||||
"readingTimeLocal": "2023-07-20T03:04:48.0"}, {"hrvValue": 32, "readingTimeGMT":
|
||||
"2023-07-20T09:09:48.0", "readingTimeLocal": "2023-07-20T03:09:48.0"}, {"hrvValue":
|
||||
37, "readingTimeGMT": "2023-07-20T09:14:48.0", "readingTimeLocal": "2023-07-20T03:14:48.0"},
|
||||
{"hrvValue": 40, "readingTimeGMT": "2023-07-20T09:19:48.0", "readingTimeLocal":
|
||||
"2023-07-20T03:19:48.0"}, {"hrvValue": 39, "readingTimeGMT": "2023-07-20T09:24:48.0",
|
||||
"readingTimeLocal": "2023-07-20T03:24:48.0"}, {"hrvValue": 47, "readingTimeGMT":
|
||||
"2023-07-20T09:29:48.0", "readingTimeLocal": "2023-07-20T03:29:48.0"}, {"hrvValue":
|
||||
45, "readingTimeGMT": "2023-07-20T09:34:48.0", "readingTimeLocal": "2023-07-20T03:34:48.0"},
|
||||
{"hrvValue": 43, "readingTimeGMT": "2023-07-20T09:39:48.0", "readingTimeLocal":
|
||||
"2023-07-20T03:39:48.0"}, {"hrvValue": 31, "readingTimeGMT": "2023-07-20T09:44:48.0",
|
||||
"readingTimeLocal": "2023-07-20T03:44:48.0"}, {"hrvValue": 35, "readingTimeGMT":
|
||||
"2023-07-20T09:49:48.0", "readingTimeLocal": "2023-07-20T03:49:48.0"}, {"hrvValue":
|
||||
40, "readingTimeGMT": "2023-07-20T09:54:48.0", "readingTimeLocal": "2023-07-20T03:54:48.0"},
|
||||
{"hrvValue": 44, "readingTimeGMT": "2023-07-20T09:59:48.0", "readingTimeLocal":
|
||||
"2023-07-20T03:59:48.0"}, {"hrvValue": 35, "readingTimeGMT": "2023-07-20T10:04:48.0",
|
||||
"readingTimeLocal": "2023-07-20T04:04:48.0"}, {"hrvValue": 43, "readingTimeGMT":
|
||||
"2023-07-20T10:09:48.0", "readingTimeLocal": "2023-07-20T04:09:48.0"}, {"hrvValue":
|
||||
54, "readingTimeGMT": "2023-07-20T10:14:48.0", "readingTimeLocal": "2023-07-20T04:14:48.0"},
|
||||
{"hrvValue": 57, "readingTimeGMT": "2023-07-20T10:19:48.0", "readingTimeLocal":
|
||||
"2023-07-20T04:19:48.0"}, {"hrvValue": 66, "readingTimeGMT": "2023-07-20T10:24:48.0",
|
||||
"readingTimeLocal": "2023-07-20T04:24:48.0"}, {"hrvValue": 58, "readingTimeGMT":
|
||||
"2023-07-20T10:29:48.0", "readingTimeLocal": "2023-07-20T04:29:48.0"}, {"hrvValue":
|
||||
61, "readingTimeGMT": "2023-07-20T10:34:48.0", "readingTimeLocal": "2023-07-20T04:34:48.0"},
|
||||
{"hrvValue": 45, "readingTimeGMT": "2023-07-20T10:39:48.0", "readingTimeLocal":
|
||||
"2023-07-20T04:39:48.0"}, {"hrvValue": 52, "readingTimeGMT": "2023-07-20T10:44:48.0",
|
||||
"readingTimeLocal": "2023-07-20T04:44:48.0"}, {"hrvValue": 43, "readingTimeGMT":
|
||||
"2023-07-20T10:49:48.0", "readingTimeLocal": "2023-07-20T04:49:48.0"}, {"hrvValue":
|
||||
33, "readingTimeGMT": "2023-07-20T10:54:48.0", "readingTimeLocal": "2023-07-20T04:54:48.0"},
|
||||
{"hrvValue": 31, "readingTimeGMT": "2023-07-20T10:59:48.0", "readingTimeLocal":
|
||||
"2023-07-20T04:59:48.0"}, {"hrvValue": 11, "readingTimeGMT": "2023-07-20T11:04:48.0",
|
||||
"readingTimeLocal": "2023-07-20T05:04:48.0"}, {"hrvValue": 32, "readingTimeGMT":
|
||||
"2023-07-20T11:09:48.0", "readingTimeLocal": "2023-07-20T05:09:48.0"}, {"hrvValue":
|
||||
38, "readingTimeGMT": "2023-07-20T11:14:48.0", "readingTimeLocal": "2023-07-20T05:14:48.0"},
|
||||
{"hrvValue": 38, "readingTimeGMT": "2023-07-20T11:19:48.0", "readingTimeLocal":
|
||||
"2023-07-20T05:19:48.0"}, {"hrvValue": 29, "readingTimeGMT": "2023-07-20T11:24:48.0",
|
||||
"readingTimeLocal": "2023-07-20T05:24:48.0"}, {"hrvValue": 38, "readingTimeGMT":
|
||||
"2023-07-20T11:29:48.0", "readingTimeLocal": "2023-07-20T05:29:48.0"}, {"hrvValue":
|
||||
27, "readingTimeGMT": "2023-07-20T11:34:48.0", "readingTimeLocal": "2023-07-20T05:34:48.0"},
|
||||
{"hrvValue": 30, "readingTimeGMT": "2023-07-20T11:39:48.0", "readingTimeLocal":
|
||||
"2023-07-20T05:39:48.0"}, {"hrvValue": 55, "readingTimeGMT": "2023-07-20T11:44:48.0",
|
||||
"readingTimeLocal": "2023-07-20T05:44:48.0"}, {"hrvValue": 33, "readingTimeGMT":
|
||||
"2023-07-20T11:49:48.0", "readingTimeLocal": "2023-07-20T05:49:48.0"}, {"hrvValue":
|
||||
40, "readingTimeGMT": "2023-07-20T11:54:48.0", "readingTimeLocal": "2023-07-20T05:54:48.0"},
|
||||
{"hrvValue": 42, "readingTimeGMT": "2023-07-20T11:59:48.0", "readingTimeLocal":
|
||||
"2023-07-20T05:59:48.0"}, {"hrvValue": 50, "readingTimeGMT": "2023-07-20T12:04:48.0",
|
||||
"readingTimeLocal": "2023-07-20T06:04:48.0"}, {"hrvValue": 38, "readingTimeGMT":
|
||||
"2023-07-20T12:09:48.0", "readingTimeLocal": "2023-07-20T06:09:48.0"}], "startTimestampGMT":
|
||||
"2023-07-20T05:25:00.0", "endTimestampGMT": "2023-07-20T12:09:48.0", "startTimestampLocal":
|
||||
"2023-07-19T23:25:00.0", "endTimestampLocal": "2023-07-20T06:09:48.0", "sleepStartTimestampGMT":
|
||||
"2023-07-20T05:25:00.0", "sleepEndTimestampGMT": "2023-07-20T12:11:00.0",
|
||||
"sleepStartTimestampLocal": "2023-07-19T23:25:00.0", "sleepEndTimestampLocal":
|
||||
"2023-07-20T06:11:00.0"}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7fea5791ac5b155e-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Wed, 30 Aug 2023 04:38:03 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=WPNDBwn%2Bfxqb0O6vEmlCrJ8G95qISZzDCH%2BKyUwlszTlFuY1obIOOv%2Flxxab8UwAeJMjXilnv4GT5%2Be6xR62sdLvcthLHgBQS9Imf3tn%2FOtkM0RaVRGP7MnFn1Klb26eMJo3fXWLjw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- _cfuvid=SANITIZED; ADRUM_BT1=SANITIZED; ADRUM_BTa=SANITIZED; SameSite=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/2021-07-20
|
||||
response:
|
||||
body:
|
||||
string: ''
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7fea5792ff3b154b-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Date:
|
||||
- Wed, 30 Aug 2023 04:38:04 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=AbFAU6ePddXCH6t5Ivd3iEs8icSg%2BboWeYfDzAOhakCxvGS0NvnCzxvNFMi5Cog2IvU82WhBEv8tUKYeIFzeOW%2BvE4c%2BQ1E4RCmoWq%2FeAc859qFp7U0wQgbZXS%2F5r8dBFEb0244AOA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
status:
|
||||
code: 204
|
||||
message: No Content
|
||||
version: 1
|
||||
@@ -1,162 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA52aXU/bMBSG/4uvA/LxRxLnjg00LgAh6LiZJhRa01ZNP5S0IIT636cUiiizd975
|
||||
ksT49WMnT46TvopN59vrdvk4bfz1TFTKOsqlysSkfbrdzOd1+yKqVzGsG78Y1e1pvfaiEkoqfSSL
|
||||
IyVFJp69nzUvJ09jUWmXiabu1lfT8WS9O2LUpyP2cro4n44nosrzTDzUnW+mC9/33yyff65WvhWV
|
||||
3p1p6sXQjy6Wz2997g+8t7EqE/O6nfn2rm42XlTyWNltJrp1vd50ohLfTi5Orr6fnYpMPHo/eqiH
|
||||
s+tJW3f92M9v7u735+8LkYlh6+u1H0zn/nZdz1cHeANSFZmK6Lh0pdjupuXG16PpYtyJ6tdr//f7
|
||||
GKzJRPt2qu/rx+XgsCdpK+UqUx73c/ap4cVyWDefmpIbKP3RdJsdZORshjZwxr7plwziM3AOHeaQ
|
||||
bIbBOUyYw/IZOIdxiRkW57CpHBbnsEEOo5mMvJIIR99UfjT9wgFkODzDJWYQzkFBDkN8Bs5B4fUo
|
||||
2AyFc6gwh+UzcI6wr3TJZmicI+wrza+5xjl06v1hcI6wr4zjM3AOk8phcY6wr4Br1+IcNu26KnBf
|
||||
UcRX2vEZDs9wSddugfuKYr4CMnCOiK8sm6FwjrCvdM5n4BwqzbsF7iuK+MrwHBrn0GnPwQL3FUV8
|
||||
pfk1NzhH2FeKv88tzhH2lZZ8Bs6R6KsS95WK+Ip9fpS4r1TEV+y1W+K+UhFfaeIzcI6wrxQ/Vwrn
|
||||
iPhK8Rk4R9hXqmAzNM6hU9dD4xw67TlY4r5SMV/x62FwDpN6XVmcw6Z5t8R9pWK+4pzocF/pWH2l
|
||||
+AyHZ4Q5CjaDcI5IfcXPFeEcYV+xtajDfaVj+0F+rhTOodLqRIf7Kvb+iq13He6r2Psr1okO95VO
|
||||
ra8c7qvY+yvg2rU4R2Q/aPgMnCPiK2auSOK+MrH6SvMZDs8I1+2GzSCcI+wrW/AZOEfYV3nOZiic
|
||||
I+wrW/IZOEfYVzmxGRrn0Env4UjivjKx/aBiMwzOYVLvD4NzmKQ6kSTuKxOrr/g1tzhH2FfEZRDu
|
||||
K5tYXxHhvrKx+qpkMwjniOwHgQycI20/SIT7ysb2gzyHwjnS9oNEuK9sbD8o+QycQyd9VyPCfWVj
|
||||
9ZXmM3COtPqKCPeVjdVX/H1ucQ6b9L2WFO6rPOarks9weMae4/fuZwHtum/a9d/3gx/mbSXlrmO/
|
||||
GMVbHgzhsNfIV/xgv/8ecSa6xvvV7X8MevcPZ8zIe9/LWP/c8P9KCDPsM7Z/ALlCPuhYIgAA
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 812800c81f4c479e-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sat, 07 Oct 2023 17:53:20 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=1efXaZ9bQvYJF8jZkRNJeCENTFUGwDN6ljNCY3V9t8M17uF6Eq4aI4bI%2BrhUvg2sw5dEWCCf7SVlDKE0sYvbYE1MtrVNYOqposaDhcgu3w7t9t1Vpz1Lher36IKgicfzMAEw5RmXtw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- _cfuvid=SANITIZED; ADRUM_BT1=SANITIZED; ADRUM_BTa=SANITIZED; SameSite=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/2023-07-19
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA52aUW/TPBSG/4uvw+Rz7JPUuRsf6ONioIn14wYhFFqzVUu7Ke2Y0LT//qmFTVT4
|
||||
cF58ucTz68eOn9pOHtzdNk/n083X1ZjPr13Pkqj13Lir6dvF3Xo9TN9d/+AWw5g3y2F6Neyy6x17
|
||||
Di9894KSa9x9ztfj99Nvl64PqXHjsN29W11e7Q5XYvjlirxdbd6sLq9c3/rGfRm2eVxt8r7+8eb+
|
||||
v9vbPLk+tPs747BZ5OXZzf2POp8u/Cwj3Lj1MF3n6cMw3mXX+xOWx8Ztd8Pubut69/L07PTdP69f
|
||||
ucZ9zXn5ZVhcn19Nw3bf9jfvP3x+uv85usYtpjzs8ny1zhe7YX17hDen2MfQU3sSUnSPh255n4fl
|
||||
anO5df3Hh/3fP9sQuXHTj1v7uv59Oz+uyUsfUh9nJ94dFTy7WQzjr0Vncw7PRR+bv8yIEc54Knqc
|
||||
EcTOwDlimcObGYJzSJmjtTNwDilyhJmR0fYe4khz75+LHmdwZ2ckPKPIwcnMIJyDyuMBZOAcVB6P
|
||||
YGYwzsFlDrYzcA4uz49oZgScI5SfK/vZDThH2VdAX0WcQ/GVzRFxjkpftaCvDhlS+1wJziF186PD
|
||||
fUWKr5CMhGeUOTozg3AOqvv96HBfkeYrm4NxjrKvxOZgnIPr5keH+4oUX0WbI+AcyvpqZmZEnKPs
|
||||
KyQD54i181xwjkpfdbivSPOVNeYz3Fes+CqSnZHwjLp5PsN9xZqv2M7AOcq+EruvGOeo9NUM9xVr
|
||||
vrI5As6h+Moe84BzKOurZGZEnKPsK/F2Bs6hrK9sDsE5pJZDcA6pmx8J91VQfCViZyQ8o8zRmRmE
|
||||
c1DdeCTcV0HxVbT7inEOrluXJNxXQfPVzMwIOIfiq2Rn4BxlXwmbGRHniLXPVcQ5Yi2H4BxlX7U2
|
||||
h+Aciq+M54o87quo+SrYGQnPqBoP8rivouIra49DHvdV1Hxl9xXjHFx1XkIe91VUfBWimRFwjlC1
|
||||
PyeP+ypq+0E7I+IcdftB8rivouIrFjNDcI6yr9juK8E5yr5ia54T7ivR9oOdnZHwjKrzEiLcV1Lr
|
||||
K8J9Jdp+MJgZjHNw1XsDItxXovhK7DEPOEfZV2I/uwHnqFtfEeG+ksr3g0S4r0Q7v7IzBOeQut9B
|
||||
wn0liq+sNTUx7qtWO2/v7IyEZ1TtP4hxX7XafjDYGThHpa8Y91WrnV+JnYFzcNW5DzHuq1ZbX0U7
|
||||
A+eoez9IjPuq1dZX9phHnOPZV58On5tMu33R7f67EeWDD+8PFefNUi951ITjWtWvQwr1/rnFjduO
|
||||
Od9e/EWjD//w2mi5UB9Fq99q/m8JZYanjMf/AU1pYOmwJAAA
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 812800c8f836479e-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Sat, 07 Oct 2023 17:53:20 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=aYF7%2Fjff6q%2BSW3DoLj4L0k%2BOVpTIJg1uTyZAJlPPxWfk8qcKnyoYSbdeMeFKDwiveT57hbjuS7p2fiY%2FKfvkmhY4ie2PKVugdBz29e64xajlg0jA3eE5e9fSMkV%2BZHMbJkLa4r%2BPOw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,170 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/userprofile-service/socialProfile
|
||||
response:
|
||||
body:
|
||||
string: '{"id": 3154645, "profileId": 2591602, "garminGUID": "0690cc1d-d23d-4412-b027-80fd4ed1c0f6",
|
||||
"displayName": "mtamizi", "fullName": "Matin Tamizi", "userName": "mtamizi",
|
||||
"profileImageUuid": "73240e81-6e4d-43fc-8af8-c8f6c51b3b8f", "profileImageUrlLarge":
|
||||
"https://s3.amazonaws.com/garmin-connect-prod/profile_images/73240e81-6e4d-43fc-8af8-c8f6c51b3b8f-2591602.png",
|
||||
"profileImageUrlMedium": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/685a19e9-a7be-4a11-9bf9-faca0c5d1f1a-2591602.png",
|
||||
"profileImageUrlSmall": "https://s3.amazonaws.com/garmin-connect-prod/profile_images/6302f021-0ec7-4dc9-b0c3-d5a19bc5a08c-2591602.png",
|
||||
"location": "Ciudad de M\u00e9xico, CDMX", "facebookUrl": null, "twitterUrl":
|
||||
null, "personalWebsite": null, "motivation": null, "bio": null, "primaryActivity":
|
||||
null, "favoriteActivityTypes": [], "runningTrainingSpeed": 0.0, "cyclingTrainingSpeed":
|
||||
0.0, "favoriteCyclingActivityTypes": [], "cyclingClassification": null, "cyclingMaxAvgPower":
|
||||
0.0, "swimmingTrainingSpeed": 0.0, "profileVisibility": "private", "activityStartVisibility":
|
||||
"private", "activityMapVisibility": "public", "courseVisibility": "public",
|
||||
"activityHeartRateVisibility": "public", "activityPowerVisibility": "public",
|
||||
"badgeVisibility": "private", "showAge": false, "showWeight": false, "showHeight":
|
||||
false, "showWeightClass": false, "showAgeRange": false, "showGender": false,
|
||||
"showActivityClass": false, "showVO2Max": false, "showPersonalRecords": false,
|
||||
"showLast12Months": false, "showLifetimeTotals": false, "showUpcomingEvents":
|
||||
false, "showRecentFavorites": false, "showRecentDevice": false, "showRecentGear":
|
||||
false, "showBadges": true, "otherActivity": null, "otherPrimaryActivity":
|
||||
null, "otherMotivation": null, "userRoles": ["SCOPE_ATP_READ", "SCOPE_ATP_WRITE",
|
||||
"SCOPE_COMMUNITY_COURSE_READ", "SCOPE_COMMUNITY_COURSE_WRITE", "SCOPE_CONNECT_READ",
|
||||
"SCOPE_CONNECT_WRITE", "SCOPE_DT_CLIENT_ANALYTICS_WRITE", "SCOPE_GARMINPAY_READ",
|
||||
"SCOPE_GARMINPAY_WRITE", "SCOPE_GCOFFER_READ", "SCOPE_GCOFFER_WRITE", "SCOPE_GHS_SAMD",
|
||||
"SCOPE_GHS_UPLOAD", "SCOPE_GOLF_API_READ", "SCOPE_GOLF_API_WRITE", "SCOPE_INSIGHTS_READ",
|
||||
"SCOPE_INSIGHTS_WRITE", "SCOPE_PRODUCT_SEARCH_READ", "ROLE_CONNECTUSER", "ROLE_FITNESS_USER",
|
||||
"ROLE_WELLNESS_USER", "ROLE_OUTDOOR_USER", "ROLE_CONNECT_2_USER", "ROLE_TACX_APP_USER"],
|
||||
"nameApproved": true, "userProfileFullName": "Matin Tamizi", "makeGolfScorecardsPrivate":
|
||||
true, "allowGolfLiveScoring": false, "allowGolfScoringByConnections": true,
|
||||
"userLevel": 3, "userPoint": 117, "levelUpdateDate": "2020-12-12T15:20:38.0",
|
||||
"levelIsViewed": false, "levelPointThreshold": 140, "userPointOffset": 0,
|
||||
"userPro": false}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12d0081a724797-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:51:33 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=7Jm3%2BQkQNnW8yDQr8zz%2FW93FRmApY0UugFBzK5SgwmO8atpbxSWdU7uz2UcLfuGZajQJkLQ28E%2FBQ7f0ki9S6f2eY3EDSfVn7CNNgmuZdvo38guNpuMK5guqKP3cYIQy4fF5GLPHUQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- _cfuvid=SANITIZED; ADRUM_BT1=SANITIZED; ADRUM_BTa=SANITIZED; SameSite=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/wellness-service/wellness/dailySleepData/mtamizi?nonSleepBufferMinutes=60&date=2021-07-20
|
||||
response:
|
||||
body:
|
||||
string: '{"dailySleepDTO": {"id": 1626758400000, "userProfilePK": 2591602, "calendarDate":
|
||||
"2021-07-20", "sleepTimeSeconds": 25740, "napTimeSeconds": 0, "sleepWindowConfirmed":
|
||||
true, "sleepWindowConfirmationType": "enhanced_confirmed_final", "sleepStartTimestampGMT":
|
||||
1626758400000, "sleepEndTimestampGMT": 1626785940000, "sleepStartTimestampLocal":
|
||||
1626740400000, "sleepEndTimestampLocal": 1626767940000, "autoSleepStartTimestampGMT":
|
||||
null, "autoSleepEndTimestampGMT": null, "sleepQualityTypePK": null, "sleepResultTypePK":
|
||||
null, "unmeasurableSleepSeconds": 0, "deepSleepSeconds": 4440, "lightSleepSeconds":
|
||||
18720, "remSleepSeconds": 2580, "awakeSleepSeconds": 1800, "deviceRemCapable":
|
||||
true, "retro": false, "sleepFromDevice": true, "averageSpO2Value": 92.0, "lowestSpO2Value":
|
||||
84, "highestSpO2Value": 100, "averageSpO2HRSleep": 51.0, "averageRespirationValue":
|
||||
15.0, "lowestRespirationValue": 8.0, "highestRespirationValue": 18.0, "sleepVersion":
|
||||
1}, "sleepMovement": [], "remSleepData": true, "sleepLevels": [], "wellnessSpO2SleepSummaryDTO":
|
||||
{"userProfilePk": 2591602, "deviceId": 3329978681, "sleepMeasurementStartGMT":
|
||||
"2021-07-20T05:21:00.0", "sleepMeasurementEndGMT": "2021-07-20T12:56:00.0",
|
||||
"alertThresholdValue": null, "numberOfEventsBelowThreshold": null, "durationOfEventsBelowThreshold":
|
||||
null, "averageSPO2": 92.0, "averageSpO2HR": 51.0, "lowestSPO2": 84}}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12d0093b58b6e2-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json;charset=UTF-8
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:51:34 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=asU9NqPsuSmxxN96St1ca3wY06WSkANwfXch1MOBitkjzSuq45fyuSUC%2BXGE%2F7S9FHwRT13HYOi%2FDLINfwbYmWT9Vrwld3zjhkDxpGkSP2EsN7vdWSKXrF23uV3RSIoBkU9JthnrZQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,97 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/weight-service/weight/range/2025-06-01/2025-06-15?includeAll=true
|
||||
response:
|
||||
body:
|
||||
string: '{"dailyWeightSummaries": [{"summaryDate": "2025-06-15", "numOfWeightEntries":
|
||||
1, "minWeight": 59720.0, "maxWeight": 59720.0, "latestWeight": {"samplePk":
|
||||
1749996902851, "date": 1749975276000, "calendarDate": "2025-06-15", "weight":
|
||||
59720.0, "bmi": 22.799999237060547, "bodyFat": 19.3, "bodyWater": 58.9, "boneMass":
|
||||
3539, "muscleMass": 26979, "physiqueRating": null, "visceralFat": null, "metabolicAge":
|
||||
null, "sourceType": "INDEX_SCALE", "timestampGMT": 1749996876000, "weightDelta":
|
||||
200.00000000000284}, "allWeightMetrics": [{"samplePk": 1749996902851, "date":
|
||||
1749975276000, "calendarDate": "2025-06-15", "weight": 59720.0, "bmi": 22.799999237060547,
|
||||
"bodyFat": 19.3, "bodyWater": 58.9, "boneMass": 3539, "muscleMass": 26979,
|
||||
"physiqueRating": null, "visceralFat": null, "metabolicAge": null, "sourceType":
|
||||
"INDEX_SCALE", "timestampGMT": 1749996876000, "weightDelta": 200.00000000000284}]},
|
||||
{"summaryDate": "2025-06-14", "numOfWeightEntries": 2, "minWeight": 59130.0,
|
||||
"maxWeight": 59500.0, "latestWeight": {"samplePk": 1749948744411, "date":
|
||||
1749927125175, "calendarDate": "2025-06-14", "weight": 59500.0, "bmi": null,
|
||||
"bodyFat": null, "bodyWater": null, "boneMass": null, "muscleMass": null,
|
||||
"physiqueRating": null, "visceralFat": null, "metabolicAge": null, "sourceType":
|
||||
"MANUAL", "timestampGMT": 1749948725175, "weightDelta": 299.99999999999716},
|
||||
"allWeightMetrics": [{"samplePk": 1749948744411, "date": 1749927125175, "calendarDate":
|
||||
"2025-06-14", "weight": 59500.0, "bmi": null, "bodyFat": null, "bodyWater":
|
||||
null, "boneMass": null, "muscleMass": null, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null, "sourceType": "MANUAL", "timestampGMT": 1749948725175,
|
||||
"weightDelta": 399.9999999999986}, {"samplePk": 1749909217098, "date": 1749887580000,
|
||||
"calendarDate": "2025-06-14", "weight": 59130.0, "bmi": 22.5, "bodyFat": 20.3,
|
||||
"bodyWater": 58.2, "boneMass": 3430, "muscleMass": 26840, "physiqueRating":
|
||||
null, "visceralFat": null, "metabolicAge": null, "sourceType": "INDEX_SCALE",
|
||||
"timestampGMT": 1749909180000, "weightDelta": -100.00000000000142}]}, {"summaryDate":
|
||||
"2025-06-07", "numOfWeightEntries": 1, "minWeight": 59189.0, "maxWeight":
|
||||
59189.0, "latestWeight": {"samplePk": 1749307692871, "date": 1749286058000,
|
||||
"calendarDate": "2025-06-07", "weight": 59189.0, "bmi": 22.600000381469727,
|
||||
"bodyFat": 20.0, "bodyWater": 58.4, "boneMass": 3450, "muscleMass": 26850,
|
||||
"physiqueRating": null, "visceralFat": null, "metabolicAge": null, "sourceType":
|
||||
"INDEX_SCALE", "timestampGMT": 1749307658000, "weightDelta": 500.0}, "allWeightMetrics":
|
||||
[{"samplePk": 1749307692871, "date": 1749286058000, "calendarDate": "2025-06-07",
|
||||
"weight": 59189.0, "bmi": 22.600000381469727, "bodyFat": 20.0, "bodyWater":
|
||||
58.4, "boneMass": 3450, "muscleMass": 26850, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null, "sourceType": "INDEX_SCALE", "timestampGMT": 1749307658000,
|
||||
"weightDelta": 500.0}]}], "totalAverage": {"from": 1748736000000, "until":
|
||||
1750031999999, "weight": 59469.666666666664, "bmi": 22.699999809265137, "bodyFat":
|
||||
19.7, "bodyWater": 58.7, "boneMass": 3494, "muscleMass": 26914, "physiqueRating":
|
||||
null, "visceralFat": null, "metabolicAge": null}, "previousDateWeight": {"samplePk":
|
||||
1748709464191, "date": 1748687805000, "calendarDate": "2025-05-31", "weight":
|
||||
58700.0, "bmi": 22.399999618530273, "bodyFat": 20.7, "bodyWater": 57.9, "boneMass":
|
||||
3369, "muscleMass": 26729, "physiqueRating": null, "visceralFat": null, "metabolicAge":
|
||||
null, "sourceType": "INDEX_SCALE", "timestampGMT": 1748709405000, "weightDelta":
|
||||
null}, "nextDateWeight": {"samplePk": null, "date": null, "calendarDate":
|
||||
null, "weight": null, "bmi": null, "bodyFat": null, "bodyWater": null, "boneMass":
|
||||
null, "muscleMass": null, "physiqueRating": null, "visceralFat": null, "metabolicAge":
|
||||
null, "sourceType": null, "timestampGMT": null, "weightDelta": null}}'
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 95064b68690b1f84-QRO
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 16 Jun 2025 00:47:12 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=9ExXlb7xohhNWV42MyBDMFTW8fcvDW7s7NvGZZsQ7QjtfUyT%2FYq2LTKDwbG1mdwpyUYacYYBjzSOZNw3Tu8MfsrfLBPOgWE4LsgwmirKigo5mVi5%2FJqIfZgyWULExMxPoeX88D%2B6iXcluwUE8dlp4VL2yA%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,61 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/weight-service/weight/range/2019-12-18/2020-01-01?includeAll=true
|
||||
response:
|
||||
body:
|
||||
string: '{"dailyWeightSummaries": [], "totalAverage": {"from": 1576627200000,
|
||||
"until": 1577923199999, "weight": null, "bmi": null, "bodyFat": null, "bodyWater":
|
||||
null, "boneMass": null, "muscleMass": null, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null}, "previousDateWeight": {"samplePk": null, "date":
|
||||
null, "calendarDate": null, "weight": null, "bmi": null, "bodyFat": null,
|
||||
"bodyWater": null, "boneMass": null, "muscleMass": null, "physiqueRating":
|
||||
null, "visceralFat": null, "metabolicAge": null, "sourceType": null, "timestampGMT":
|
||||
null, "weightDelta": null}, "nextDateWeight": {"samplePk": null, "date": null,
|
||||
"calendarDate": null, "weight": null, "bmi": null, "bodyFat": null, "bodyWater":
|
||||
null, "boneMass": null, "muscleMass": null, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null, "sourceType": null, "timestampGMT": null, "weightDelta":
|
||||
null}}'
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 95065fe3afea2fde-QRO
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 16 Jun 2025 01:01:11 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=YZscbyvERqaC8NIT00%2Fv%2FV3X%2BSEXE8LosKNrrmILOYZWBqF906BX31WBG9C5u4NtRh73%2BRPj2OyWX%2FgtYZcd9QricbIkwL8Np9kXdKtPcufnwwAg7odFD4X4JnUeS0d%2BEk1u5Kb2VAIyW4O%2BxfR1FNVErw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,77 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/weight-service/weight/range/2025-06-14/2025-06-14?includeAll=true
|
||||
response:
|
||||
body:
|
||||
string: '{"dailyWeightSummaries": [{"summaryDate": "2025-06-14", "numOfWeightEntries":
|
||||
2, "minWeight": 59130.0, "maxWeight": 59500.0, "latestWeight": {"samplePk":
|
||||
1749948744411, "date": 1749927125175, "calendarDate": "2025-06-14", "weight":
|
||||
59500.0, "bmi": null, "bodyFat": null, "bodyWater": null, "boneMass": null,
|
||||
"muscleMass": null, "physiqueRating": null, "visceralFat": null, "metabolicAge":
|
||||
null, "sourceType": "MANUAL", "timestampGMT": 1749948725175, "weightDelta":
|
||||
299.99999999999716}, "allWeightMetrics": [{"samplePk": 1749948744411, "date":
|
||||
1749927125175, "calendarDate": "2025-06-14", "weight": 59500.0, "bmi": null,
|
||||
"bodyFat": null, "bodyWater": null, "boneMass": null, "muscleMass": null,
|
||||
"physiqueRating": null, "visceralFat": null, "metabolicAge": null, "sourceType":
|
||||
"MANUAL", "timestampGMT": 1749948725175, "weightDelta": 399.9999999999986},
|
||||
{"samplePk": 1749909217098, "date": 1749887580000, "calendarDate": "2025-06-14",
|
||||
"weight": 59130.0, "bmi": 22.5, "bodyFat": 20.3, "bodyWater": 58.2, "boneMass":
|
||||
3430, "muscleMass": 26840, "physiqueRating": null, "visceralFat": null, "metabolicAge":
|
||||
null, "sourceType": "INDEX_SCALE", "timestampGMT": 1749909180000, "weightDelta":
|
||||
-100.00000000000142}]}], "totalAverage": {"from": 1749859200000, "until":
|
||||
1749945599999, "weight": 59500.0, "bmi": null, "bodyFat": null, "bodyWater":
|
||||
null, "boneMass": null, "muscleMass": null, "physiqueRating": null, "visceralFat":
|
||||
null, "metabolicAge": null}, "previousDateWeight": {"samplePk": 1749307692871,
|
||||
"date": 1749286058000, "calendarDate": "2025-06-07", "weight": 59189.0, "bmi":
|
||||
22.600000381469727, "bodyFat": 20.0, "bodyWater": 58.4, "boneMass": 3450,
|
||||
"muscleMass": 26850, "physiqueRating": null, "visceralFat": null, "metabolicAge":
|
||||
null, "sourceType": "INDEX_SCALE", "timestampGMT": 1749307658000, "weightDelta":
|
||||
null}, "nextDateWeight": {"samplePk": 1749996902851, "date": 1749975276000,
|
||||
"calendarDate": "2025-06-15", "weight": 59720.0, "bmi": 22.799999237060547,
|
||||
"bodyFat": 19.3, "bodyWater": 58.9, "boneMass": 3539, "muscleMass": 26979,
|
||||
"physiqueRating": null, "visceralFat": null, "metabolicAge": null, "sourceType":
|
||||
"INDEX_SCALE", "timestampGMT": 1749996876000, "weightDelta": null}}'
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 9506620b6d30b6e5-QRO
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 16 Jun 2025 01:02:39 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=TNhpJPozun%2FMkRaaYU%2FYH7B2ZrX%2BfDEbq2rKyeuDmDpxQgshSkQTs0eOWr0XO1i1EwLmf%2F0SYtAecesFwm0eugpiNFopVrsvBlvMj1vk3RaPwL37B46JBHOYvrvm1OhMNzNqTF7QWLHAFYe%2Bk6zeTmTcVQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,335 +0,0 @@
|
||||
from datetime import date
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
from garth import BodyBatteryData, DailyBodyBatteryStress
|
||||
from garth.http import Client
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_body_battery_data_get(authed_client: Client):
|
||||
body_battery_data = BodyBatteryData.get("2023-07-20", client=authed_client)
|
||||
assert isinstance(body_battery_data, list)
|
||||
|
||||
if body_battery_data:
|
||||
# Check first event if available
|
||||
event = body_battery_data[0]
|
||||
assert event is not None
|
||||
|
||||
# Test body battery readings property
|
||||
readings = event.body_battery_readings
|
||||
assert isinstance(readings, list)
|
||||
|
||||
if readings:
|
||||
# Test reading structure
|
||||
reading = readings[0]
|
||||
assert hasattr(reading, "timestamp")
|
||||
assert hasattr(reading, "status")
|
||||
assert hasattr(reading, "level")
|
||||
assert hasattr(reading, "version")
|
||||
|
||||
# Test level properties
|
||||
assert event.current_level is not None and isinstance(
|
||||
event.current_level, int
|
||||
)
|
||||
assert event.max_level is not None and isinstance(
|
||||
event.max_level, int
|
||||
)
|
||||
assert event.min_level is not None and isinstance(
|
||||
event.min_level, int
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_body_battery_data_list(authed_client: Client):
|
||||
days = 3
|
||||
end = date(2023, 7, 20)
|
||||
body_battery_data = BodyBatteryData.list(end, days, client=authed_client)
|
||||
assert isinstance(body_battery_data, list)
|
||||
|
||||
# Test that we get data (may be empty if no events)
|
||||
assert len(body_battery_data) >= 0
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_daily_body_battery_stress_get(authed_client: Client):
|
||||
daily_data = DailyBodyBatteryStress.get("2023-07-20", client=authed_client)
|
||||
|
||||
if daily_data:
|
||||
# Test basic structure
|
||||
assert daily_data.user_profile_pk
|
||||
assert daily_data.calendar_date == date(2023, 7, 20)
|
||||
assert daily_data.start_timestamp_gmt
|
||||
assert daily_data.end_timestamp_gmt
|
||||
|
||||
# Test stress data
|
||||
assert isinstance(daily_data.max_stress_level, int)
|
||||
assert isinstance(daily_data.avg_stress_level, int)
|
||||
assert isinstance(daily_data.stress_values_array, list)
|
||||
assert isinstance(daily_data.body_battery_values_array, list)
|
||||
|
||||
# Test stress readings property
|
||||
stress_readings = daily_data.stress_readings
|
||||
assert isinstance(stress_readings, list)
|
||||
|
||||
if stress_readings:
|
||||
stress_reading = stress_readings[0]
|
||||
assert hasattr(stress_reading, "timestamp")
|
||||
assert hasattr(stress_reading, "stress_level")
|
||||
|
||||
# Test body battery readings property
|
||||
bb_readings = daily_data.body_battery_readings
|
||||
assert isinstance(bb_readings, list)
|
||||
|
||||
if bb_readings:
|
||||
bb_reading = bb_readings[0]
|
||||
assert hasattr(bb_reading, "timestamp")
|
||||
assert hasattr(bb_reading, "status")
|
||||
assert hasattr(bb_reading, "level")
|
||||
assert hasattr(bb_reading, "version")
|
||||
|
||||
# Test computed properties
|
||||
assert daily_data.current_body_battery is not None and isinstance(
|
||||
daily_data.current_body_battery, int
|
||||
)
|
||||
assert daily_data.max_body_battery is not None and isinstance(
|
||||
daily_data.max_body_battery, int
|
||||
)
|
||||
assert daily_data.min_body_battery is not None and isinstance(
|
||||
daily_data.min_body_battery, int
|
||||
)
|
||||
|
||||
# Test body battery change
|
||||
if len(bb_readings) >= 2:
|
||||
change = daily_data.body_battery_change
|
||||
assert change is not None
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_daily_body_battery_stress_get_no_data(authed_client: Client):
|
||||
# Test with a date that likely has no data
|
||||
daily_data = DailyBodyBatteryStress.get("2020-01-01", client=authed_client)
|
||||
# Should return None if no data available
|
||||
assert daily_data is None or isinstance(daily_data, DailyBodyBatteryStress)
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_daily_body_battery_stress_list(authed_client: Client):
|
||||
days = 3
|
||||
end = date(2023, 7, 20)
|
||||
# Use max_workers=1 to avoid VCR issues with concurrent requests
|
||||
daily_data_list = DailyBodyBatteryStress.list(
|
||||
end, days, client=authed_client, max_workers=1
|
||||
)
|
||||
assert isinstance(daily_data_list, list)
|
||||
assert (
|
||||
len(daily_data_list) <= days
|
||||
) # May be less if some days have no data
|
||||
|
||||
# Test that each item is correct type
|
||||
for daily_data in daily_data_list:
|
||||
assert isinstance(daily_data, DailyBodyBatteryStress)
|
||||
assert isinstance(daily_data.calendar_date, date)
|
||||
assert daily_data.user_profile_pk
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_body_battery_properties_edge_cases(authed_client: Client):
|
||||
# Test empty data handling
|
||||
daily_data = DailyBodyBatteryStress.get("2023-07-20", client=authed_client)
|
||||
|
||||
if daily_data:
|
||||
# Test with potentially empty arrays
|
||||
if not daily_data.body_battery_values_array:
|
||||
assert daily_data.body_battery_readings == []
|
||||
assert daily_data.current_body_battery is None
|
||||
assert daily_data.max_body_battery is None
|
||||
assert daily_data.min_body_battery is None
|
||||
assert daily_data.body_battery_change is None
|
||||
|
||||
if not daily_data.stress_values_array:
|
||||
assert daily_data.stress_readings == []
|
||||
|
||||
|
||||
# Error handling tests for BodyBatteryData.get()
|
||||
def test_body_battery_data_get_api_error():
|
||||
"""Test handling of API errors."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.side_effect = Exception("API Error")
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == []
|
||||
|
||||
|
||||
def test_body_battery_data_get_invalid_response():
|
||||
"""Test handling of non-list responses."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = {"error": "Invalid response"}
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == []
|
||||
|
||||
|
||||
def test_body_battery_data_get_missing_event_data():
|
||||
"""Test handling of items with missing event data."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{"activityName": "Test", "averageStress": 25} # Missing "event" key
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert len(result) == 1
|
||||
assert result[0].event is None
|
||||
|
||||
|
||||
def test_body_battery_data_get_missing_event_start_time():
|
||||
"""Test handling of event data missing eventStartTimeGmt."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {"eventType": "sleep"}, # Missing eventStartTimeGmt
|
||||
"activityName": "Test",
|
||||
"averageStress": 25,
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == [] # Should skip invalid items
|
||||
|
||||
|
||||
def test_body_battery_data_get_invalid_datetime_format():
|
||||
"""Test handling of invalid datetime format."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "invalid-date",
|
||||
},
|
||||
"activityName": "Test",
|
||||
"averageStress": 25,
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert result == [] # Should skip invalid items
|
||||
|
||||
|
||||
def test_body_battery_data_get_invalid_field_types():
|
||||
"""Test handling of invalid field types."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
"timezoneOffset": "invalid", # Should be number
|
||||
"durationInMilliseconds": "invalid", # Should be number
|
||||
"bodyBatteryImpact": "invalid", # Should be number
|
||||
},
|
||||
"activityName": "Test",
|
||||
"averageStress": "invalid", # Should be number
|
||||
"stressValuesArray": "invalid", # Should be list
|
||||
"bodyBatteryValuesArray": "invalid", # Should be list
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
assert len(result) == 1
|
||||
# Should handle invalid types gracefully
|
||||
|
||||
|
||||
def test_body_battery_data_get_validation_error():
|
||||
"""Test handling of validation errors during object creation."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
# Missing required fields for BodyBatteryEvent
|
||||
},
|
||||
# Missing required fields for BodyBatteryData
|
||||
}
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
# Should handle validation errors and continue processing
|
||||
assert isinstance(result, list)
|
||||
assert len(result) == 1 # Should create object with missing fields as None
|
||||
assert result[0].event is not None # Event should be created
|
||||
assert result[0].activity_name is None # Missing fields should be None
|
||||
|
||||
|
||||
def test_body_battery_data_get_mixed_valid_invalid():
|
||||
"""Test processing with mix of valid and invalid items."""
|
||||
mock_client = MagicMock()
|
||||
mock_client.connectapi.return_value = [
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
"timezoneOffset": -25200000,
|
||||
"durationInMilliseconds": 28800000,
|
||||
"bodyBatteryImpact": 35,
|
||||
"feedbackType": "good_sleep",
|
||||
"shortFeedback": "Good sleep",
|
||||
},
|
||||
"activityName": None,
|
||||
"activityType": None,
|
||||
"activityId": None,
|
||||
"averageStress": 15.5,
|
||||
"stressValuesArray": [[1689811800000, 12]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0]],
|
||||
},
|
||||
{
|
||||
# Invalid - missing eventStartTimeGmt
|
||||
"event": {"eventType": "sleep"},
|
||||
"activityName": "Test",
|
||||
},
|
||||
]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
# Should process valid items and skip invalid ones
|
||||
assert len(result) == 1 # Only the valid item should be processed
|
||||
assert result[0].event is not None
|
||||
|
||||
|
||||
def test_body_battery_data_get_unexpected_error():
|
||||
"""Test handling of unexpected errors during object creation."""
|
||||
mock_client = MagicMock()
|
||||
|
||||
# Create a special object that raises an exception when accessed
|
||||
class ExceptionRaisingDict(dict):
|
||||
def get(self, key, default=None):
|
||||
if key == "activityName":
|
||||
raise RuntimeError("Unexpected error during object creation")
|
||||
return super().get(key, default)
|
||||
|
||||
# Create mock data with problematic item
|
||||
mock_response_item = ExceptionRaisingDict(
|
||||
{
|
||||
"event": {
|
||||
"eventType": "sleep",
|
||||
"eventStartTimeGmt": "2023-07-20T10:00:00.000Z",
|
||||
"timezoneOffset": -25200000,
|
||||
"durationInMilliseconds": 28800000,
|
||||
"bodyBatteryImpact": 35,
|
||||
"feedbackType": "good_sleep",
|
||||
"shortFeedback": "Good sleep",
|
||||
},
|
||||
"activityName": None,
|
||||
"activityType": None,
|
||||
"activityId": None,
|
||||
"averageStress": 15.5,
|
||||
"stressValuesArray": [[1689811800000, 12]],
|
||||
"bodyBatteryValuesArray": [[1689811800000, "charging", 45, 1.0]],
|
||||
}
|
||||
)
|
||||
|
||||
mock_client.connectapi.return_value = [mock_response_item]
|
||||
|
||||
result = BodyBatteryData.get("2023-07-20", client=mock_client)
|
||||
# Should handle unexpected errors and return empty list
|
||||
assert result == []
|
||||
@@ -1,25 +0,0 @@
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
|
||||
from garth import HRVData
|
||||
from garth.http import Client
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_hrv_data_get(authed_client: Client):
|
||||
hrv_data = HRVData.get("2023-07-20", client=authed_client)
|
||||
assert hrv_data
|
||||
assert hrv_data.user_profile_pk
|
||||
assert hrv_data.hrv_summary.calendar_date == date(2023, 7, 20)
|
||||
|
||||
assert HRVData.get("2021-07-20", client=authed_client) is None
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_hrv_data_list(authed_client: Client):
|
||||
days = 2
|
||||
end = date(2023, 7, 20)
|
||||
hrv_data = HRVData.list(end, days, client=authed_client, max_workers=1)
|
||||
assert len(hrv_data) == days
|
||||
assert hrv_data[-1].hrv_summary.calendar_date == end
|
||||
@@ -1,24 +0,0 @@
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
|
||||
from garth import SleepData
|
||||
from garth.http import Client
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_sleep_data_get(authed_client: Client):
|
||||
sleep_data = SleepData.get("2021-07-20", client=authed_client)
|
||||
assert sleep_data
|
||||
assert sleep_data.daily_sleep_dto.calendar_date == date(2021, 7, 20)
|
||||
assert sleep_data.daily_sleep_dto.sleep_start
|
||||
assert sleep_data.daily_sleep_dto.sleep_end
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_sleep_data_list(authed_client: Client):
|
||||
end = date(2021, 7, 20)
|
||||
days = 20
|
||||
sleep_data = SleepData.list(end, days, client=authed_client, max_workers=1)
|
||||
assert sleep_data[-1].daily_sleep_dto.calendar_date == end
|
||||
assert len(sleep_data) == days
|
||||
@@ -1,74 +0,0 @@
|
||||
from datetime import date, timedelta, timezone
|
||||
|
||||
import pytest
|
||||
|
||||
from garth.data import WeightData
|
||||
from garth.http import Client
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_get_daily_weight_data(authed_client: Client):
|
||||
weight_data = WeightData.get(date(2025, 6, 15), client=authed_client)
|
||||
assert weight_data is not None
|
||||
assert weight_data.source_type == "INDEX_SCALE"
|
||||
assert weight_data.weight is not None
|
||||
assert weight_data.bmi is not None
|
||||
assert weight_data.body_fat is not None
|
||||
assert weight_data.body_water is not None
|
||||
assert weight_data.bone_mass is not None
|
||||
assert weight_data.muscle_mass is not None
|
||||
# Timezone should match your account settings, my case is -6
|
||||
assert weight_data.datetime_local.tzinfo == timezone(timedelta(hours=-6))
|
||||
assert weight_data.datetime_utc.tzinfo == timezone.utc
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_get_manual_weight_data(authed_client: Client):
|
||||
weight_data = WeightData.get(date(2025, 6, 14), client=authed_client)
|
||||
assert weight_data is not None
|
||||
assert weight_data.source_type == "MANUAL"
|
||||
assert weight_data.weight is not None
|
||||
assert weight_data.bmi is None
|
||||
assert weight_data.body_fat is None
|
||||
assert weight_data.body_water is None
|
||||
assert weight_data.bone_mass is None
|
||||
assert weight_data.muscle_mass is None
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_get_nonexistent_weight_data(authed_client: Client):
|
||||
weight_data = WeightData.get(date(2020, 1, 1), client=authed_client)
|
||||
assert weight_data is None
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_weight_data_list(authed_client: Client):
|
||||
end = date(2025, 6, 15)
|
||||
days = 15
|
||||
weight_data = WeightData.list(end, days, client=authed_client)
|
||||
|
||||
# Only 4 weight entries recorded at time of test
|
||||
assert len(weight_data) == 4
|
||||
assert all(isinstance(data, WeightData) for data in weight_data)
|
||||
assert all(
|
||||
weight_data[i].datetime_utc <= weight_data[i + 1].datetime_utc
|
||||
for i in range(len(weight_data) - 1)
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_weight_data_list_single_day(authed_client: Client):
|
||||
end = date(2025, 6, 14)
|
||||
weight_data = WeightData.list(end, client=authed_client)
|
||||
assert len(weight_data) == 2
|
||||
assert all(isinstance(data, WeightData) for data in weight_data)
|
||||
assert weight_data[0].source_type == "INDEX_SCALE"
|
||||
assert weight_data[1].source_type == "MANUAL"
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_weight_data_list_empty(authed_client: Client):
|
||||
end = date(2020, 1, 1)
|
||||
days = 15
|
||||
weight_data = WeightData.list(end, days, client=authed_client)
|
||||
assert len(weight_data) == 0
|
||||
@@ -1,128 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/daily/2023-07-01/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '{"hrvSummaries": [{"calendarDate": "2023-07-01", "weeklyAvg": 43, "lastNightAvg":
|
||||
43, "lastNight5MinHigh": 60, "baseline": {"lowUpper": 35, "balancedLow": 38,
|
||||
"balancedUpper": 52, "markerValue": 0.42855835}, "status": "BALANCED", "feedbackPhrase":
|
||||
"HRV_BALANCED_8", "createTimeStamp": "2023-07-01T12:27:14.85"}, {"calendarDate":
|
||||
"2023-07-02", "weeklyAvg": 43, "lastNightAvg": 44, "lastNight5MinHigh": 63,
|
||||
"baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 51, "markerValue":
|
||||
0.44230652}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp":
|
||||
"2023-07-02T11:54:17.128"}, {"calendarDate": "2023-07-03", "weeklyAvg": 43,
|
||||
"lastNightAvg": 48, "lastNight5MinHigh": 82, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.42855835}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp": "2023-07-03T12:41:20.280"},
|
||||
{"calendarDate": "2023-07-04", "weeklyAvg": 43, "lastNightAvg": 40, "lastNight5MinHigh":
|
||||
80, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp":
|
||||
"2023-07-04T11:41:59.456"}, {"calendarDate": "2023-07-05", "weeklyAvg": 43,
|
||||
"lastNightAvg": 40, "lastNight5MinHigh": 67, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.42855835}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp": "2023-07-05T12:46:25.805"},
|
||||
{"calendarDate": "2023-07-06", "weeklyAvg": 43, "lastNightAvg": 46, "lastNight5MinHigh":
|
||||
58, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp":
|
||||
"2023-07-06T17:20:46.196"}, {"calendarDate": "2023-07-07", "weeklyAvg": 44,
|
||||
"lastNightAvg": 44, "lastNight5MinHigh": 85, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.46427917}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp": "2023-07-07T12:15:26.744"},
|
||||
{"calendarDate": "2023-07-08", "weeklyAvg": 43, "lastNightAvg": 40, "lastNight5MinHigh":
|
||||
63, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp":
|
||||
"2023-07-09T01:57:41.693"}, {"calendarDate": "2023-07-09", "weeklyAvg": 43,
|
||||
"lastNightAvg": 43, "lastNight5MinHigh": 66, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.42855835}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp": "2023-07-09T14:15:53.403"},
|
||||
{"calendarDate": "2023-07-10", "weeklyAvg": 42, "lastNightAvg": 41, "lastNight5MinHigh":
|
||||
62, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.3653717}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp":
|
||||
"2023-07-10T12:43:37.356"}, {"calendarDate": "2023-07-11", "weeklyAvg": 43,
|
||||
"lastNightAvg": 46, "lastNight5MinHigh": 67, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.4038391}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp": "2023-07-11T12:42:55.467"},
|
||||
{"calendarDate": "2023-07-12", "weeklyAvg": 42, "lastNightAvg": 38, "lastNight5MinHigh":
|
||||
56, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.3653717}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp":
|
||||
"2023-07-12T10:08:55.474"}, {"calendarDate": "2023-07-13", "weeklyAvg": 42,
|
||||
"lastNightAvg": 41, "lastNight5MinHigh": 66, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.3653717}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp": "2023-07-13T12:59:44.753"},
|
||||
{"calendarDate": "2023-07-14", "weeklyAvg": 41, "lastNightAvg": 37, "lastNight5MinHigh":
|
||||
57, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.32691956}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp":
|
||||
"2023-07-14T12:16:07.618"}, {"calendarDate": "2023-07-15", "weeklyAvg": 40,
|
||||
"lastNightAvg": 37, "lastNight5MinHigh": 54, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.28845215}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp": "2023-07-15T18:18:32.522"},
|
||||
{"calendarDate": "2023-07-16", "weeklyAvg": 39, "lastNightAvg": 37, "lastNight5MinHigh":
|
||||
64, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.25}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp":
|
||||
"2023-07-17T03:13:54.585"}, {"calendarDate": "2023-07-17", "weeklyAvg": 39,
|
||||
"lastNightAvg": 41, "lastNight5MinHigh": 65, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.25}, "status": "BALANCED",
|
||||
"feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp": "2023-07-17T11:58:26.731"},
|
||||
{"calendarDate": "2023-07-18", "weeklyAvg": 39, "lastNightAvg": 40, "lastNight5MinHigh":
|
||||
72, "baseline": {"lowUpper": 36, "balancedLow": 40, "balancedUpper": 52, "markerValue":
|
||||
0.22801208}, "status": "UNBALANCED", "feedbackPhrase": "HRV_UNBALANCED_12",
|
||||
"createTimeStamp": "2023-07-18T13:45:54.638"}, {"calendarDate": "2023-07-19",
|
||||
"weeklyAvg": 39, "lastNightAvg": 43, "lastNight5MinHigh": 60, "baseline":
|
||||
{"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue": 0.25},
|
||||
"status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_4", "createTimeStamp":
|
||||
"2023-07-19T14:43:16.394"}, {"calendarDate": "2023-07-20", "weeklyAvg": 39,
|
||||
"lastNightAvg": 42, "lastNight5MinHigh": 66, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.25}, "status": "BALANCED",
|
||||
"feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp": "2023-07-20T12:14:11.898"}],
|
||||
"userProfilePk": 2591602}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12cffb1bf04740-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:51:31 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=FwXXbkT4TDPL0xwdyj0pemCK5IZtMhJ0cEJStvFh9rhUuwEgA9nPQyW5%2F78guNWU4c0CMB5arBD5aYFCFwrJ0S9cXV%2BHnxbblaMvHkHhr3XZNcHySwLfohsTZBtkWiUT4iZVWVGDgg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,54 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/daily/1990-06-23/1990-07-20
|
||||
response:
|
||||
body:
|
||||
string: ''
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12cfff895a46e6-DFW
|
||||
Connection:
|
||||
- keep-alive
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:51:32 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=c5M1eFSWXRssBQjJffsEsd2fyEVImSUgt64bWpiVisHYL7YajNn2yfJIhcd6yueOyfUrDXvCDZJiZ9%2BVQfAAHMEaRxu%2B8ZZj7iPBiNff%2Fl9O9KJ6SIX1qHMttNFKtEcxoc5Vl0E5Gw%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 204
|
||||
message: No Content
|
||||
version: 1
|
||||
@@ -1,256 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/daily/2023-06-23/2023-07-20
|
||||
response:
|
||||
body:
|
||||
string: '{"hrvSummaries": [{"calendarDate": "2023-06-23", "weeklyAvg": 40, "lastNightAvg":
|
||||
42, "lastNight5MinHigh": 54, "baseline": {"lowUpper": 35, "balancedLow": 38,
|
||||
"balancedUpper": 52, "markerValue": 0.3214264}, "status": "BALANCED", "feedbackPhrase":
|
||||
"HRV_BALANCED_8", "createTimeStamp": "2023-06-25T04:55:32.475"}, {"calendarDate":
|
||||
"2023-06-24", "weeklyAvg": 41, "lastNightAvg": 43, "lastNight5MinHigh": 69,
|
||||
"baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.35713196}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp":
|
||||
"2023-06-25T04:56:02.128"}, {"calendarDate": "2023-06-25", "weeklyAvg": 41,
|
||||
"lastNightAvg": 41, "lastNight5MinHigh": 63, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 51, "markerValue": 0.3653717}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp": "2023-06-25T12:30:49.823"},
|
||||
{"calendarDate": "2023-06-26", "weeklyAvg": 42, "lastNightAvg": 50, "lastNight5MinHigh":
|
||||
113, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52,
|
||||
"markerValue": 0.39285278}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_7",
|
||||
"createTimeStamp": "2023-06-26T15:16:53.873"}, {"calendarDate": "2023-06-27",
|
||||
"weeklyAvg": 41, "lastNightAvg": 39, "lastNight5MinHigh": 63, "baseline":
|
||||
{"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue": 0.35713196},
|
||||
"status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp":
|
||||
"2023-06-27T12:38:37.557"}, {"calendarDate": "2023-06-28", "weeklyAvg": 42,
|
||||
"lastNightAvg": 39, "lastNight5MinHigh": 63, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.39285278}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp": "2023-06-28T12:44:11.280"},
|
||||
{"calendarDate": "2023-06-29", "weeklyAvg": 43, "lastNightAvg": 47, "lastNight5MinHigh":
|
||||
78, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp":
|
||||
"2023-06-29T13:30:15.112"}, {"calendarDate": "2023-06-30", "weeklyAvg": 43,
|
||||
"lastNightAvg": 40, "lastNight5MinHigh": 65, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.42855835}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp": "2023-06-30T14:19:24.203"},
|
||||
{"calendarDate": "2023-07-01", "weeklyAvg": 43, "lastNightAvg": 43, "lastNight5MinHigh":
|
||||
60, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp":
|
||||
"2023-07-01T12:27:14.85"}, {"calendarDate": "2023-07-02", "weeklyAvg": 43,
|
||||
"lastNightAvg": 44, "lastNight5MinHigh": 63, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 51, "markerValue": 0.44230652}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp": "2023-07-02T11:54:17.128"},
|
||||
{"calendarDate": "2023-07-03", "weeklyAvg": 43, "lastNightAvg": 48, "lastNight5MinHigh":
|
||||
82, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp":
|
||||
"2023-07-03T12:41:20.280"}, {"calendarDate": "2023-07-04", "weeklyAvg": 43,
|
||||
"lastNightAvg": 40, "lastNight5MinHigh": 80, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.42855835}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp": "2023-07-04T11:41:59.456"},
|
||||
{"calendarDate": "2023-07-05", "weeklyAvg": 43, "lastNightAvg": 40, "lastNight5MinHigh":
|
||||
67, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp":
|
||||
"2023-07-05T12:46:25.805"}, {"calendarDate": "2023-07-06", "weeklyAvg": 43,
|
||||
"lastNightAvg": 46, "lastNight5MinHigh": 58, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.42855835}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp": "2023-07-06T17:20:46.196"},
|
||||
{"calendarDate": "2023-07-07", "weeklyAvg": 44, "lastNightAvg": 44, "lastNight5MinHigh":
|
||||
85, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.46427917}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp":
|
||||
"2023-07-07T12:15:26.744"}, {"calendarDate": "2023-07-08", "weeklyAvg": 43,
|
||||
"lastNightAvg": 40, "lastNight5MinHigh": 63, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.42855835}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp": "2023-07-09T01:57:41.693"},
|
||||
{"calendarDate": "2023-07-09", "weeklyAvg": 43, "lastNightAvg": 43, "lastNight5MinHigh":
|
||||
66, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.42855835}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp":
|
||||
"2023-07-09T14:15:53.403"}, {"calendarDate": "2023-07-10", "weeklyAvg": 42,
|
||||
"lastNightAvg": 41, "lastNight5MinHigh": 62, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.3653717}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp": "2023-07-10T12:43:37.356"},
|
||||
{"calendarDate": "2023-07-11", "weeklyAvg": 43, "lastNightAvg": 46, "lastNight5MinHigh":
|
||||
67, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.4038391}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp":
|
||||
"2023-07-11T12:42:55.467"}, {"calendarDate": "2023-07-12", "weeklyAvg": 42,
|
||||
"lastNightAvg": 38, "lastNight5MinHigh": 56, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.3653717}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp": "2023-07-12T10:08:55.474"},
|
||||
{"calendarDate": "2023-07-13", "weeklyAvg": 42, "lastNightAvg": 41, "lastNight5MinHigh":
|
||||
66, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.3653717}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp":
|
||||
"2023-07-13T12:59:44.753"}, {"calendarDate": "2023-07-14", "weeklyAvg": 41,
|
||||
"lastNightAvg": 37, "lastNight5MinHigh": 57, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.32691956}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp": "2023-07-14T12:16:07.618"},
|
||||
{"calendarDate": "2023-07-15", "weeklyAvg": 40, "lastNightAvg": 37, "lastNight5MinHigh":
|
||||
54, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.28845215}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp":
|
||||
"2023-07-15T18:18:32.522"}, {"calendarDate": "2023-07-16", "weeklyAvg": 39,
|
||||
"lastNightAvg": 37, "lastNight5MinHigh": 64, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.25}, "status": "BALANCED",
|
||||
"feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp": "2023-07-17T03:13:54.585"},
|
||||
{"calendarDate": "2023-07-17", "weeklyAvg": 39, "lastNightAvg": 41, "lastNight5MinHigh":
|
||||
65, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.25}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp":
|
||||
"2023-07-17T11:58:26.731"}, {"calendarDate": "2023-07-18", "weeklyAvg": 39,
|
||||
"lastNightAvg": 40, "lastNight5MinHigh": 72, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 40, "balancedUpper": 52, "markerValue": 0.22801208}, "status":
|
||||
"UNBALANCED", "feedbackPhrase": "HRV_UNBALANCED_12", "createTimeStamp": "2023-07-18T13:45:54.638"},
|
||||
{"calendarDate": "2023-07-19", "weeklyAvg": 39, "lastNightAvg": 43, "lastNight5MinHigh":
|
||||
60, "baseline": {"lowUpper": 36, "balancedLow": 39, "balancedUpper": 52, "markerValue":
|
||||
0.25}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_4", "createTimeStamp":
|
||||
"2023-07-19T14:43:16.394"}, {"calendarDate": "2023-07-20", "weeklyAvg": 39,
|
||||
"lastNightAvg": 42, "lastNight5MinHigh": 66, "baseline": {"lowUpper": 36,
|
||||
"balancedLow": 39, "balancedUpper": 52, "markerValue": 0.25}, "status": "BALANCED",
|
||||
"feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp": "2023-07-20T12:14:11.898"}],
|
||||
"userProfilePk": 2591602}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12cffc4ea3b6e1-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:51:31 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=2qwUnXfm51mWjJY2ho0q0lhgcjKqNZIHMND%2F3pcFJs8BsJFIXzgvLZIVnVro%2Fl1%2BmXxg4txzEdRTUKUbedJs19kiYjjaUqbGOdl%2FA7w3NYWk3hlzD5bzjzJzovpCZi3rG9ckt3TzyQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
Cookie:
|
||||
- _cfuvid=SANITIZED; ADRUM_BT1=SANITIZED; ADRUM_BTa=SANITIZED; SameSite=SANITIZED
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/daily/2023-06-11/2023-06-22
|
||||
response:
|
||||
body:
|
||||
string: '{"hrvSummaries": [{"calendarDate": "2023-06-11", "weeklyAvg": 43, "lastNightAvg":
|
||||
71, "lastNight5MinHigh": 115, "baseline": {"lowUpper": 35, "balancedLow":
|
||||
38, "balancedUpper": 51, "markerValue": 0.44230652}, "status": "BALANCED",
|
||||
"feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp": "2023-06-11T14:17:59.319"},
|
||||
{"calendarDate": "2023-06-12", "weeklyAvg": 45, "lastNightAvg": 51, "lastNight5MinHigh":
|
||||
89, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 51, "markerValue":
|
||||
0.5192261}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp":
|
||||
"2023-06-12T12:50:20.861"}, {"calendarDate": "2023-06-13", "weeklyAvg": 45,
|
||||
"lastNightAvg": 44, "lastNight5MinHigh": 68, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 51, "markerValue": 0.5192261}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp": "2023-06-13T13:55:03.624"},
|
||||
{"calendarDate": "2023-06-14", "weeklyAvg": 47, "lastNightAvg": 49, "lastNight5MinHigh":
|
||||
83, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 51, "markerValue":
|
||||
0.59614563}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp":
|
||||
"2023-06-14T13:36:05.184"}, {"calendarDate": "2023-06-15", "weeklyAvg": 46,
|
||||
"lastNightAvg": 39, "lastNight5MinHigh": 77, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 51, "markerValue": 0.5576782}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp": "2023-06-15T11:50:18.949"},
|
||||
{"calendarDate": "2023-06-16", "weeklyAvg": 45, "lastNightAvg": 34, "lastNight5MinHigh":
|
||||
54, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 51, "markerValue":
|
||||
0.5192261}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp":
|
||||
"2023-06-16T12:40:24.953"}, {"calendarDate": "2023-06-17", "weeklyAvg": 46,
|
||||
"lastNightAvg": 42, "lastNight5MinHigh": 97, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 51, "markerValue": 0.5576782}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_6", "createTimeStamp": "2023-06-17T14:05:55.936"},
|
||||
{"calendarDate": "2023-06-18", "weeklyAvg": 42, "lastNightAvg": 39, "lastNight5MinHigh":
|
||||
71, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.39285278}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp":
|
||||
"2023-06-18T13:32:40.883"}, {"calendarDate": "2023-06-19", "weeklyAvg": 41,
|
||||
"lastNightAvg": 40, "lastNight5MinHigh": 66, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.35713196}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_8", "createTimeStamp": "2023-06-19T14:15:45.918"},
|
||||
{"calendarDate": "2023-06-20", "weeklyAvg": 41, "lastNightAvg": 45, "lastNight5MinHigh":
|
||||
76, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.35713196}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_5", "createTimeStamp":
|
||||
"2023-06-20T12:57:59.375"}, {"calendarDate": "2023-06-21", "weeklyAvg": 39,
|
||||
"lastNightAvg": 36, "lastNight5MinHigh": 55, "baseline": {"lowUpper": 35,
|
||||
"balancedLow": 38, "balancedUpper": 52, "markerValue": 0.28570557}, "status":
|
||||
"BALANCED", "feedbackPhrase": "HRV_BALANCED_3", "createTimeStamp": "2023-06-21T12:07:13.299"},
|
||||
{"calendarDate": "2023-06-22", "weeklyAvg": 39, "lastNightAvg": 40, "lastNight5MinHigh":
|
||||
66, "baseline": {"lowUpper": 35, "balancedLow": 38, "balancedUpper": 52, "markerValue":
|
||||
0.28570557}, "status": "BALANCED", "feedbackPhrase": "HRV_BALANCED_7", "createTimeStamp":
|
||||
"2023-06-22T15:07:52.527"}], "userProfilePk": 2591602}'
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12cffd58bdb6e1-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:51:32 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=0NCR775bJt1JRqheSkoCuFTz1b0iStwJxkS5KYP46xKe8WcWO56WI81lN9h62gaiKEiVtpV1Mrlkr4oRqMEm8XwiPMrJ8kF6OFxD8%2F6t%2B7DK0QOI6An3R2EzrBEfW40UaG6qbLitvg%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -1,54 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- Mozilla/5.0 (iPhone; CPU iPhone OS 16_5 like Mac OS X) AppleWebKit/605.1.15
|
||||
(KHTML, like Gecko) Mobile/15E148
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/hrv-service/hrv/daily/1990-06-23/1990-07-20
|
||||
response:
|
||||
body:
|
||||
string: ''
|
||||
headers:
|
||||
CF-Cache-Status:
|
||||
- DYNAMIC
|
||||
CF-RAY:
|
||||
- 7f12d0009fb71556-QRO
|
||||
Connection:
|
||||
- keep-alive
|
||||
Date:
|
||||
- Fri, 04 Aug 2023 00:51:32 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=Rtks48zaXzNg0K9c8L5w7UaDVLx4fUwxanI2aMQtUuzIq7%2FEg%2F3tYRlfBLxbkZgQptFoiz3CS%2B8rKHWzqq7ayFvLe0k2kEynQKwSjY5I%2FDlesB7kjUKuXxwh%2B3qW7JMMoW6BK9ybRQ%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cache-control:
|
||||
- no-cache, no-store, private
|
||||
pragma:
|
||||
- no-cache
|
||||
set-cookie:
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BTa=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- SameSite=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED;
|
||||
Secure
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- ADRUM_BT1=SANITIZED; Max-Age=SANITIZED; Expires=SANITIZED; Path=SANITIZED
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
status:
|
||||
code: 204
|
||||
message: No Content
|
||||
version: 1
|
||||
@@ -1,50 +0,0 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Authorization:
|
||||
- Bearer SANITIZED
|
||||
Connection:
|
||||
- keep-alive
|
||||
User-Agent:
|
||||
- GCM-iOS-5.7.2.1
|
||||
method: GET
|
||||
uri: https://connectapi.garmin.com/usersummary-service/stats/hydration/daily/2024-06-29/2024-06-29
|
||||
response:
|
||||
body:
|
||||
string: '[{"calendarDate": "2024-06-29", "valueInML": 1750.0, "goalInML": 2800.0}]'
|
||||
headers:
|
||||
CF-RAY:
|
||||
- 94b18a3ecfb934a7-QRO
|
||||
Cache-Control:
|
||||
- no-cache, no-store, private
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Thu, 05 Jun 2025 17:55:17 GMT
|
||||
NEL:
|
||||
- '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}'
|
||||
Report-To:
|
||||
- '{"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v4?s=Fj%2FXgrWJs%2FS1mgUePurhEKyb3GueFKdLEDdkAVqNKT%2ByACTJn5%2Fi%2B2%2FsDOOh95cibWQYcDIAGM40K0XxrSBItFfY5ZW24CwXjHLIg%2FkvAB1JJwMiyAdhLIpXjUfVdyXoQ4tdKQcy0Q%3D%3D"}],"group":"cf-nel","max_age":604800}'
|
||||
Server:
|
||||
- cloudflare
|
||||
Set-Cookie:
|
||||
- _cfuvid=SANITIZED; path=SANITIZED; domain=SANITIZED; HttpOnly; Secure; SameSite=SANITIZED
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
alt-svc:
|
||||
- h3=":443"; ma=86400
|
||||
cf-cache-status:
|
||||
- DYNAMIC
|
||||
pragma:
|
||||
- no-cache
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user