• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wger-project / flutter / 30854254088

03 Aug 2026 09:21PM UTC coverage: 40.895% (-15.0%) from 55.93%
30854254088

Pull #1260

github

web-flow
Merge d93794de5 into e3affdd4f
Pull Request #1260: WIP: health sync

9980 of 24404 relevant lines covered (40.89%)

1.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

80.0
/lib/core/exceptions/http_exception.dart
1
/*
2
 * This file is part of wger Workout Manager <https://github.com/wger-project>.
3
 * Copyright (c) 2020 - 2026 wger Team
4
 *
5
 * wger Workout Manager is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU Affero General Public License as published by
7
 * the Free Software Foundation, either version 3 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU Affero General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU Affero General Public License
16
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
 */
18

19
import 'dart:convert';
20
import 'dart:io';
21

22
import 'package:http/http.dart';
23

24
enum ErrorType {
25
  json,
26
  html,
27
  text,
28
}
29

30
/// Where an exception originated, so the error handler can route and present
31
/// it differently (a plain API validation error vs a PowerSync upload
32
/// rejection worth reporting).
33
enum ExceptionSource { api, powersync, flutter }
34

35
const HTML_ERROR_KEY = 'html_error';
36

37
class WgerHttpException implements Exception {
38
  Map<String, dynamic> errors = {};
39

40
  /// The exception type. While the majority will be json, it is possible that
41
  /// the server will return HTML, e.g. if there has been an internal server error
42
  /// or similar.
43
  late ErrorType type;
44

45
  /// Where the exception came from (drives routing and presentation).
46
  final ExceptionSource source;
47

48
  /// The HTTP status code, when built from a [Response].
49
  final int? statusCode;
50

51
  /// Optional structured context for diagnostics (e.g. the PowerSync table/op).
52
  final Map<String, dynamic>? context;
53

54
  /// Custom http exception
55
  WgerHttpException(
6✔
56
    Response response, {
57
    this.source = ExceptionSource.api,
58
    this.context,
59
  }) : statusCode = response.statusCode {
6✔
60
    type = ErrorType.json;
6✔
61
    final dynamic responseBody = response.body;
6✔
62

63
    final contentType = response.headers[HttpHeaders.contentTypeHeader];
12✔
64
    if ((contentType != null && contentType.contains('text/html')) ||
1✔
65
        responseBody.toString().contains('<html')) {
10✔
66
      type = ErrorType.html;
1✔
67
    }
68

69
    if (responseBody == null) {
70
      errors = {'unknown_error': 'An unknown error occurred, no further information available'};
×
71
    } else {
72
      try {
73
        if (type == ErrorType.json) {
12✔
74
          final response = json.decode(responseBody);
5✔
75
          errors = (response is Map ? response : {'unknown_error': response})
8✔
76
              .cast<String, dynamic>();
4✔
77
        } else if (type == ErrorType.html) {
2✔
78
          errors = {HTML_ERROR_KEY: responseBody.toString()};
3✔
79
        } else {
80
          errors = {'text_error': responseBody.toString()};
×
81
        }
82
      } catch (e) {
83
        errors = {'unknown_error': responseBody};
4✔
84
      }
85
    }
86
  }
87

88
  WgerHttpException.fromMap(
3✔
89
    Map<String, dynamic> map, {
90
    this.source = ExceptionSource.api,
91
    this.statusCode,
92
    this.context,
93
  }) : type = ErrorType.json {
94
    errors = map;
3✔
95
  }
96

97
  String get htmlError {
1✔
98
    if (type != ErrorType.html) {
2✔
99
      return '';
100
    }
101

102
    return errors[HTML_ERROR_KEY] ?? '';
2✔
103
  }
104

105
  @override
×
106
  String toString() {
107
    final ctxStr = context == null ? '' : ', context: $context';
×
108
    return 'WgerHttpException(${source.name}, status ${statusCode ?? '-'}, $type): $errors$ctxStr';
×
109
  }
110
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc