Accessing REST API in Flutter with HTTP package - rest

I have a REST API that I need to access from a Flutter app. It is from the Spotify Web API. The terminal command that I would use for this is
curl -X "GET" "https://api.spotify.com/v1/me/following?
type=artist&limit=50" -H "Accept: application/json" -H "Content-Type:
application/json" -H "Authorization: Bearer (ACCESS TOKEN)"
Which works. In Flutter, I have imported the import 'package:http/http.dart' as http package and import 'dart:convert'. I also have a Future that is as follows
Future<String> getData() async {
http.Response response = await http.get(
Uri.https("api.spotify.com", "v1/me/following?type=artist&limit=50"),
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization":
"Bearer (ACCESS TOKEN)"
});
Map dataMap = jsonDecode(response.body);
print(dataMap);
}
This results in {error: {status: 404, message: Service not found}} which is weird since it works perfectly in terminal. What am I doing wrong?

You need to keep it simple. There might some problem related to URL. Try this:
Future<String> getData() async {
http.Response response = await http.get(
"https://api.spotify.com/v1/me/following?type=artist&limit=50",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization":
"Bearer (ACCESS TOKEN)"
});
Map dataMap = jsonDecode(response.body);
print(dataMap);
}

NetService:
class NetService {
static Future<T?> getJson<T>(String url, {int okCode = 200, String? authKey, Map<String, String>? headers}) {
var localHeaders = <String, String>{};
localHeaders['Accept'] = 'application/json';
localHeaders['Content-Type'] = 'application/json';
if (authKey != null) localHeaders['Authorization'] = 'Bearer $authKey';
if (headers != null) localHeaders.addAll(headers);
return http.get(Uri.parse(url), headers: localHeaders)
.then((response) {
if (response.statusCode == okCode) {
return jsonDecode(response.body) as T;
}
PrintService.showDataNotOK(response);
return null;
})
.catchError((err) => PrintService.showError(err));
}
}
Main:
import 'dart:async';
import 'package:_samples2/networking.dart';
class Spotify {
static const _oAuthToken = 'XXXXYYYYYZZZZ';
static const _url = 'https://api.spotify.com/v1';
static FutureOr<void> getUsersFollowedArtists() async {
await NetService.getJson<Map<String, dynamic>>(_url + '/me/following?type=artist&limit=50', authKey: _oAuthToken)
.then((response) => print(response))
.whenComplete(() => print('\nFetching done!'));
}
}
void main(List<String> args) async {
await Spotify.getUsersFollowedArtists();
print('Done.');
}
Result:
{artists: {items: [], next: null, total: 0, cursors: {after: null}, limit: 50, href: https://api.spotify.com/v1/me/following?type=artist&limit=50}}
Fetching done!
Done.

Related

Can't get auth token stored in flutter secure storage to headers

I am making flutter app using API and I have a problem. When I want to get auth token to make request, flutter says that "Expected a value of type 'String', but got one of type '_Future'". How can I make a request with auth token without that error?
My login function, where I write the token:
loginUser() async {
final storage = new FlutterSecureStorage();
Uri uri = Uri.parse("http://127.0.0.1:8000/api/account/login");
await http
.post(uri,
headers: {"Content-Type": "application/json"},
body: jsonEncode({
"username": emailController.text,
"password": passwordController.text
}))
.then((response) async {
if (response.statusCode == 200) {
var data = json.decode(response.body);
await storage.write(key: "token", value: data["token"]);
print(data["token"]);
} else {
print(json.decode(response.body));
}
});
}
My getdata function, where i use the token:
getdata() async {
final storage = FlutterSecureStorage();
Uri uri = Uri.parse("http://127.0.0.1:8000/api/account/countries");
await http.get(uri, headers: {
"Content-Type": "application/json",
"Authorization": await storage.read(key: "token")
});
}
try this code
String token = await storage.read(key: 'token');
//make sure if there is no Bearer just token in that case just pass the token
var headers = {
'accept': 'application/json',
'Authorization': 'Bearer ${token}',
};
Uri uri = Uri.parse("http://127.0.0.1:8000/api/account/countries");
Response response = await http.get(
uri,
headers: headers
);
print (response);

Flutter - How to send a POST request using HTTP in Dart?

I am using an API that converts HTTP to JSON and to get a response from the server I need to send a post request of HTML however i'm not sure how to do that?
This is my current implementation -
Future<String> test() async {
var link =
await http.get('https://example.com');
var body = parse(link.body);
return body.outerHtml;
}
Future<Album> createAlbum(String html) async {
final http.Response response = await http.post(
'https://www.html2json.com/api/v1',
headers: <String, String>{
'Content-Type': 'text/html; charset=UTF-8',
},
body: html,
);
if (response.statusCode == 200) {
return Album.fromJson(jsonDecode(response.body));
} else {
throw Exception('Failed to create album.');
}
}
I call this is when my app starts like so,
#ovveride
void initState() {
test().then((body) => createAlbum(body)); //Output returns HTTP error 301, am I doing something wrong?
super.initState();
}
Checked the following code which worked for me.
Future<Album> createAlbum(String html) async {
final http.Response response = await http.post(
'https://www.html2json.com/api/v1',
headers: <String, String>{
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: html,
);
You need to change the Content-type to application/x-www-form-urlencoded; charset=UTF-8. This should do the trick.
Thanks to DARSH SHAH, I solved this using dio (https://pub.dev/packages/dio).
dynamic response;
Dio dio = Dio();
Future<dynamic> test() async {
dynamic link = await dio.get(
'https://example.com');
return link;
}
Future<dynamic> post(dynamic body) async {
String _baseUrl = "https://html2json.com/api/v1";
var options = Options(
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
followRedirects: false,
);
final response = await dio.post(
_baseUrl,
data: body,
options: options,
);
return response;
}
FloatingActionButton(
onPressed: () async {
dynamic responseHTML = await test();
response = await post(responseHTML.data); //This will contain the JSON response
},
);

Could not set header with dio

I ma not able to set header with dio.I am tryng to set my access token to the header.I ma trying to set header so that every request doesnt required to call it.Here is my network class where i am trying to call header with dio
My network Class:
class NetworkUtil {
Dio _dio;
String token;
getToken() async {
SharedPreferences preferences = await SharedPreferences.getInstance();
String getToken = preferences.getString(AppPrefernces.LOGIN_PREF);
return getToken;
}
NetworkUtil() {
///Create Dio Object using baseOptions set receiveTimeout,connectTimeout
BaseOptions options = BaseOptions(receiveTimeout: 5000, connectTimeout: 5000);
options.baseUrl = ApiConstants.BASE_URL;
_dio = Dio(options);
_dio.interceptors.add(InterceptorsWrapper(
onRequest: (Options option) async{
//my function to recovery token
await getToken().then((result) {
LoginResponse loginResponse = LoginResponse.fromJson(jsonDecode(result));
token = loginResponse.accessToken;
});
option.headers = {
"Authorization": "Bearer $token"
};
}
));
}
///used for calling Get Request
Future<Response> get(String url, Map<String, String> params) async {
Response response = await _dio.get(url,
queryParameters: params,
options: Options(responseType: ResponseType.json));
return response;
}
///used for calling post Request
Future<Response> post(String url, Map<String, String> params) async {
Response response = await _dio.post(url,
data: params, options: Options(responseType: ResponseType.json));
return response;
}
}
I use this setup and it works fine for me.
Future<Dio> createDioWithHeader() async {
if (_dioWithHeader != null) return _dioWithHeader;
String token = await appSharedPreferences.getToken();
String userAgent = await getUserAgent();
print('User-Agent: $userAgent');
// base config
_dioWithHeader = Dio(BaseOptions(
connectTimeout: 10000,
receiveTimeout: 10000,
baseUrl: Config.apiBaseUrl,
contentType: 'application/json',
headers: {
'Authorization': token,
'User-Agent': userAgent
}));
// setup interceptors
return addInterceptors(_dioWithHeader);
}```

How can I add request header automatically using http package

Currently I'm sending header with every request like as follow which is very repetitive.
Is there any process so that all my request will have a request header automatically ?
Or how can I avoid code repetition for the following lines:
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
String token = sharedPreferences.getString('accessToken');
headers: {
'Contet-type': 'application/json',
'Authorization': 'Bearer $token',
}
My complete API Request code:
Future<http.Response> getAUser(userId) async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
String token = sharedPreferences.getString('accessToken');
return await http.get(
'$baseUrl/user/$userId/',
headers: {
'Contet-type': 'application/json',
'Authorization': 'Bearer $token',
},
).timeout(Duration(seconds: 30));
}
Yes you can centralize the headers in a separate class!
class BaseService {
Map<String, String> baseHeaders;
Future initBaseService() async {
final preferences = await SharedPreferences.getInstance();
baseHeaders= {
"Accept": "application/json",
"Content-Type": "application/json; charset=utf-8",
"Authorization": "Bearer ${preferences.getString("TOKEN")}",
};
}
}
And then, you can inherit your class with the base class to have access to these methods.
class UserService extends BaseService {
Future<http.Response> getAUser(userId) async {
await initBaseService();
return await http
.get(
'$baseUrl/user/$userId/',
headers: baseHeaders,
)
.timeout(Duration(seconds: 30));
}
}

Http Post in Flutter not Sending Headers

I am trying to do a post request in Flutter
Below is the code
final String url = Urls.HOME_URL;
String p = 'Bearer $vAuthToken';
final Map<String, String> tokenData = {
"Content-Type": "application/x-www-form-urlencoded",
'Vauthtoken': p
};
final Map<String, String> data = {
'classId': '4',
'studentId': '5'
};
final response = await http.post(Uri.parse(url),
headers: tokenData,
body: jsonEncode(data),
encoding: Encoding.getByName("utf-8"));
if (response.statusCode == 200) {
print(response.body);
} else {
print(response.body);
}
However the header data is not working. I have the correct data and everything. This request works perfectly when done in Postman Client.
Any one has any idea what is wrong?
Any suggestion is appreciated.
Thanks