1

Just started implementing API(get, post mostly) in Flutter. I was getting the post API response well but for GET API, I am getting 401. The code is given below:

import 'package:http/http.dart' as http;

String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjgiLCJVc2VyRGV2aWNlSWQiOiI0NTVENDY3Rjc4MjI0QjlDOERFN0JDMjFFNjREQjVEQyIsIkZ1bGxOYW1lIjoiQW5keSBNZW1iZXIiLCJQaG9uZSI6IjA0MjM5OTkzMzMiLCJlbWFpbCI6Im1rYWJpckBmYXFpLmNvbS5hdSIsInN1YiI6IjA0MjM5OTkzMzMiLCJqdGkiOiJkZGY3NDM4OC03YzE4LTQyZjktODdkMC0yMGQzY2NjNDE2ZGIiLCJuYmYiOjE2MjQ5NDIxNzAsImV4cCI6MTYyNDk2Mzc3MCwiaWF0IjoxNjI0OTQyMTcwfQ.I9pR2HZbKlOwl_9Z5O5AE8kZh0o5SdTOxsvTsY28SUk";
var headers = {
'AuthToken': token,
  'accept': 'application/json',
};

 final response = await http.get('http://api.orca.faqdev.com.au/api/account/Dashboard' , headers: headers);

Two things regarding the API :

  1. It is working from the postman
  2. It is working from iOS Swift code.

Anyone can guess what happens here in Flutter? BTW, I am new in Flutter.

9
  • is headers param and value you used are same with Postman ? Commented Jun 27, 2021 at 6:27
  • Are you sure the website is up or API working? maybe problem on site side, or check your API token again. Commented Jun 27, 2021 at 7:15
  • the same token is using postamn! Commented Jun 27, 2021 at 8:48
  • There will almost certainly be a discrepancy between the headers Postman/Swift/Flutter implementations are using, perhaps because each is making different assumptions about Content-Type etc. Take a good look at the full set of headers each is sending, and compare them. Commented Jun 27, 2021 at 10:09
  • 1
    Okay, so running that code, (after fixing the issue with get needing Uri, not String), I can see that Dart sends the following headers: user-agent: Dart/2.13 (dart:io), accept: application/json, accept-encoding: gzip, authtoken: <token>, content-length: 0 If the API needs more than that, you'll need to add them in as part of the headers argument for get. Commented Jun 29, 2021 at 6:07

1 Answer 1

2

Fundamentally, this comes down to HTTP header names not being case sensitive, and the API server not respecting this.

The header at issue is AuthToken; if sent through verbatim, the server will accept it but if not, the server will reject it. The Dart http package sends through the header in lower case (authtoken) whereas Swift sends through the header maintaining the case (though noting that the names are case insensitive).

Compare:

curl \
  --header 'AuthToken: <redacted>' \
  --silent \
  --verbose \
  http://api.orca.faqdev.com.au/api/account/Dashboard > /dev/null
*   Trying 52.63.81.235...
* TCP_NODELAY set
* Connected to api.orca.faqdev.com.au (52.63.81.235) port 80 (#0)
> GET /api/account/Dashboard HTTP/1.1
> Host: api.orca.faqdev.com.au
> User-Agent: curl/7.64.1
> Accept: */*
> AuthToken: <redacted>
> 
< HTTP/1.1 200 OK
< Content-Type: application/json; charset=utf-8
< Server: Microsoft-IIS/10.0
< X-Powered-By: ASP.NET
< Date: Tue, 29 Jun 2021 06:53:33 GMT
< Content-Length: 1697
< 
{ [1697 bytes data]
* Connection #0 to host api.orca.faqdev.com.au left intact
* Closing connection 0

vs:

curl \
  --header 'authtoken: <redacted>' \
  --silent \
  --verbose \
  http://api.orca.faqdev.com.au/api/account/Dashboard > /dev/null
*   Trying 52.63.81.235...
* TCP_NODELAY set
* Connected to api.orca.faqdev.com.au (52.63.81.235) port 80 (#0)
> GET /api/account/Dashboard HTTP/1.1
> Host: api.orca.faqdev.com.au
> User-Agent: curl/7.64.1
> Accept: */*
> authtoken: <redacted>
> 
< HTTP/1.1 401 Unauthorized
< Transfer-Encoding: chunked
< Server: Microsoft-IIS/10.0
< X-Powered-By: ASP.NET
< Date: Tue, 29 Jun 2021 06:54:42 GMT
< 
{ [5 bytes data]
* Connection #0 to host api.orca.faqdev.com.au left intact
* Closing connection 0

The best solution is to configure the API server to treat all headers as case insensitive (as per the spec), then it will work for all clients.

If you absolutely positively can't do that, there is an option to use the HttpClient provided by dart:io, and in that scenario your implementation would end up something like:

import 'dart:convert';
import 'dart:io';

...

final client = HttpClient();
final request = await client
    .getUrl(Uri.parse('http://api.orca.faqdev.com.au/api/account/Dashboard'));
request.headers.set('AuthToken', '<redacted>', preserveHeaderCase: true);
final response = await request.close();
final chunks = await response.transform(utf8.decoder).toList();
final body = chunks.join('');
client.close();
// handle the response
print(body);

Note the use of preserveHeaderCase on the HttpHeaders.set method

Sign up to request clarification or add additional context in comments.

2 Comments

Thought the same, but was not known about the preserveHeaderCase. Awesome job dear @msbit.
Happy to help, @JamshedAlam. I would like to stress again, that if you are developing the API also, set it up such that the case of headers doesn't matter, it will save you possible heartache in future too :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.