Flutter returns empty string - HTTP(S) GET request
With any HTTP request, it's a good idea to test the HTTP response code. In your case you are getting 403 Forbidden
so your credentials or API key isn't being accepted by the server.
In your first approach you are actually sending two requests to the server - one for each await. Consider changing to:
http.Response r = await fetchPost();
print(r.statusCode);
print(r.body.length);
EDIT - It's your API key that isn't being accepted by the server, which is behaving in a non-standard way.
The Dart HttpClient (which is used directly in the second approach, and indirectly in the first) happens to lower case all request headers. This is perfectly valid because RFC 7230 states "Each header field consists of a case-insensitive field name followed by a colon (":"), optional leading whitespace, the field value, and optional trailing whitespace.".
So, even though you add header "apiKey": "7856d...
, what goes out on the wire is apikey: 7856d...
But, (and this is the bit you won't like), it appears that the HTTP server is non-standard and will not accept apikey
instead of apiKey
. Try changing the Python code to use apikey
or APIKEY
and you get 403.
(Note that HTTPS makes no difference, you get the same results with HTTP.)
Looks like you need to report this as a bug to Kreta.
BoA
Updated on December 05, 2022Comments
-
BoA over 1 year
I have an HTTP(S) GET request which works fine in java (Android sdk) and Python, but when I tried to port it to flutter it returns an empty string. It should return a JSON with ~2MB of data in it.
Here is the Python code:
import http.client HOST, PORT = 'kretaglobalmobileapi.ekreta.hu', 443 headers = {"apiKey": "7856d350-1fda-45f5-822d-e1a2f3f1acf0", "Connection": "keep-alive", "Accept": "application/json", "HOST": "kretaglobalmobileapi.ekreta.hu"} conn = http.client.HTTPSConnection(host=HOST, port=PORT) conn.request("GET", "/api/v1/Institute", headers=headers) response = conn.getresponse() data = response.read() print(data) conn.close()
I have tried two different approaches for the Flutter version, none worked.
First approach:
import 'dart:async'; import 'dart:convert' show utf8, json; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; Future<http.Response> fetchPost() { return http.get( "https://kretaglobalmobileapi.ekreta.hu/api/v1/Institute", // Send authorization headers to your backend headers : {"apiKey": "7856d350-1fda-45f5-822d-e1a2f3f1acf0", "Connection": "keep-alive", "Accept": "application/json", "HOST": "kretaglobalmobileapi.ekreta.hu"} ); } void login() async { print((await fetchPost()).body); print((await fetchPost()).body.length); }
It returns:
Performing full restart... Restarted app in 3,648ms. I/flutter (18739): I/flutter (18739): 0
Second:
Future<Map<String, dynamic>> getInstitutes(HttpClient client) async { final String url = "https://kretaglobalmobileapi.ekreta.hu/api/v1/Institute"; final HttpClientRequest request = await client.getUrl(Uri.parse(url)) ..headers.add("Accept", "application/json") ..headers.add("HOST", "kretaglobalmobileapi.ekreta.hu") ..headers.add("apiKey", "7856d350-1fda-45f5-822d-e1a2f3f1acf0") ..headers.add("Connection", "keep-alive"); final HttpClientResponse response = await request.close(); print(json.decode(await response.join())); return json.decode(await response.transform(utf8.decoder).join()); }
I'm leaving out the GUI and boilerplate code here, the full code is on pastebin.
Update: The problem was, that the API I was connecting to, used outdated HTTP-standards. I told the support about this, they told me they aren't willing to fix it so I will have to create a new webserver (probably in Python) that will operate between the client and the API. Another option would be to use native Android and iOS code that will hopefully support case-sensitive headers. Huh, all this fuss is because they can't change a capital 'K' to a lowercase 'k'.
-
creativecreatorormaybenot about 6 yearsWhy are you sharing your API key?
-
BoA about 6 years@creativecreatorormaybenot So it's easier for others to help me and as far as I know it is given to the client before login so I assume it's not tied to an account.
-
Shamshun over 5 yearsWhy did the python code work then? What's different in the flutter version?
-
BoA about 5 years@Shamshun Sorry, it's a bit late for me to answer, but for future visitors of this question: It worked, because Python still supports case-sensitive headers while flutter doesn't.
-
-
BoA about 6 yearsThanks, I am getting the 403 Error code, but my API key has to be correct because the same headers are used in the Python code which works perfectly.
-
Günter Zöchbauer about 6 yearsWhat's the failure reason you get for 403?
-
BoA about 6 years@GünterZöchbauer I am getting "Forbidden"
-
Günter Zöchbauer about 6 yearsI'd say you have to fix or at least debug that on the server then. We can't know why your server responds with 403.
-
BoA about 6 yearsWell Richard Heap was right the server side headers are the problem, they are case-sensitive which is not supported by Flutter (HTTP 1.2 docs states they have to be case-insensitive), I am writing to the guys at Kréta.