diff --git a/links/gql_http_link/lib/src/link.dart b/links/gql_http_link/lib/src/link.dart index 4890394e..8b7e13f2 100644 --- a/links/gql_http_link/lib/src/link.dart +++ b/links/gql_http_link/lib/src/link.dart @@ -66,6 +66,9 @@ class HttpLink extends Link { /// Default HTTP headers final Map defaultHeaders; + /// set to `false` to throw exceptions on redirects in request chain, defaults to true + final bool followRedirects; + /// set to `true` to use the HTTP `GET` method for queries (but not for mutations) final bool useGETForQueries; @@ -104,6 +107,7 @@ class HttpLink extends Link { this.serializer = const RequestSerializer(), this.parser = const ResponseParser(), this.httpResponseDecoder = _defaultHttpResponseDecoder, + this.followRedirects = true, }) : uri = Uri.parse(uri) { _httpClient = httpClient ?? http.Client(); } @@ -116,8 +120,9 @@ class HttpLink extends Link { final httpResponse = await _executeRequest(request); final response = await _parseHttpResponse(httpResponse); + final maxStatusCode = followRedirects ? 400 : 300; - if (httpResponse.statusCode >= 300 || + if (httpResponse.statusCode >= maxStatusCode || (response.data == null && response.errors == null)) { throw HttpLinkServerException( response: httpResponse, @@ -156,6 +161,17 @@ class HttpLink extends Link { try { final responseBody = await httpResponseDecoder(httpResponse); return parser.parseResponse(responseBody!); + } on FormatException { + if (!followRedirects && + (httpResponse.statusCode == 301 || httpResponse.statusCode == 302)) { + rethrow; + } + + // Empty data object sent to bypass HttpLinkServerException in subsequent request() invocation + return Response( + data: const {}, + response: const {}, + ); } catch (e, stackTrace) { throw HttpLinkParserException( originalException: e, @@ -207,7 +223,9 @@ class HttpLink extends Link { _encodeAsUriParams, )(body), ), - )..headers.addAll(headers); + ) + ..headers.addAll(headers) + ..followRedirects = followRedirects; } final httpBody = _encodeAttempter( @@ -223,11 +241,13 @@ class HttpLink extends Link { return http.MultipartRequest("POST", uri) ..body = httpBody ..addAllFiles(fileMap) - ..headers.addAll(headers); + ..headers.addAll(headers) + ..followRedirects = followRedirects; } return http.Request("POST", uri) ..body = httpBody - ..headers.addAll(headers); + ..headers.addAll(headers) + ..followRedirects = followRedirects; } /// wrap an encoding transform in exception handling