Jamshed Alam
Jamshed Alam

Reputation: 12854

Flutter http get api failed, may be for wrong header style

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.

Upvotes: 1

Views: 1103

Answers (1)

msbit
msbit

Reputation: 4320

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

Upvotes: 2

Related Questions