Flutter response non-json structure form server getting html code - dart

when i connect to server for checking username and password like with this structure
{
"Username":"1",
"Password":"1"
}
i get 0 or 1, without any json format, first letters of username and password are Capital letters, Username,Password,
now i want to get this response with flutter and post http verb
UserInformation class
class UserInformation {
String Username;
String Password;
UserInformation(this.Username, this.Password);
Map<String, dynamic> toJson() {
final Map<String, dynamic> json = new Map<String, dynamic>();
json['Username'] = this.Username;
json['Password'] = this.Password;
return json;
}
}
LoginRepository class:
class LoginRepository {
Future<int> authenticate(
{#required String username, #required String password}) async {
UserInformation userInformation = UserInformation(username, password);
/*this line print {Username: 1, Password: 1}*/
print(userInformation.toJson().toString());
final response = await http.post(
Constants.loginApi, body: userInformation.toJson());
final responseString = jsonDecode(response.body);
if (response.statusCode == 200) {
return responseString;
} else {
throw Exception('fail to get response');
}
}
}
and then this output is response from server:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: FormatException: Unexpected character (at character 1)
<?xml version="1.0" encoding="utf-8"?>

First: Check for statusCode before accessing response.body. If the call fails, response.body will be an empty String and jsonDecode will fail.
Second: Since you don't get a json formated answer, there is no need to call jsonDecode with the response. final int responseInt = response.body should be enough (maybe you will need int.parse(response.body); needs to be tested.

Related

How to auth in SignalR wih token in Dart?

How to get access token in SignalR package?
I get access token doing POST request and after that I get the access token. I have a model where I have parsed JSON and have token field.
Auth authFromJson(String str) => Auth.fromJson(json.decode(str));
String authToJson(Auth data) => json.encode(data.toJson());
class Auth {
Auth({
this.token,
this.user,
});
final String? token;
final User? user;
POST request to API to get accesss token which I got succesfully:
Future<Auth> getToken() async {
String _email = "admin";
String _password = "admin";
Map<String, String> headers = {
'Content-Type': 'application/json',
'accept': ' */*'
};
final body = {
'username': _email,
'password': _password,
};
var response = await http.post(
Uri.parse("http://******/login"),
headers: headers,
body: jsonEncode(body),
);
print(response.body);
print(response.statusCode);
var jsonResponse = jsonDecode(response.body);
return Auth.fromJson(jsonResponse);
}
What I have in print in my console:
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA","user":{}}
After all this stuff I opened docs and found out how SignalR package handle token auth and did the same thing:
Future<List> fetchLists() async {
final httpConnectionOptions = HttpConnectionOptions(
accessTokenFactory: () => getToken().then((value) => value.token ?? ''),
);
final hubConnection = HubConnectionBuilder()
.withUrl('http://*****/hub',
options: httpConnectionOptions)
.build();
await hubConnection.start();
So after all of this I got this error [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: 302: Found
it means what I should add access token to each of requests and I do, but still get this error. How can i solve it or may be there is anoher way to add token in HubConnectionBuild?
There is parameter in accessTokenFactory which accept a function and have return type String so make a function which return token .
below attached code for your reference-
_hubConnection = HubConnectionBuilder()
.withUrl(chaturl,
options: HttpConnectionOptions(
headers: defaultHeaders,
accessTokenFactory: () async => await getToken() //define a function which return token
))
withAutomaticReconnect(retryDelays: [
20000,
]
).build();
//get token method
Future<dynamic> getToken() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
if (sharedPreferences.containsKey("token")) {
print(sharedPreferences.getString("token"));
return sharedPreferences.getString("token");
} else {
return null;
}
}

Unhandled Exception: Bad state: No serializer for 'SignIn'

I was trying to serialize a json response using built_value.
I have created this classes:
1.- SigIn class.
2.- SigninDataSource.
3.- Serializer.
The service is working well and i get that response:
{"status": 200,
"user_id": "****",
"id_token": "****",
"refresh_token": "****",
"expires_in": 3600 }
The problem is when I try to serialize the response.body.
when I try to do that I get this error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: Bad state: No serializer for 'SignIn'
This is the code that I am using:
1.- SignIn
abstract class SignIn implements Built<SignIn, SignInBuilder>{
static Serializer<SignIn> get serializer => _$signInSerializer;
#nullable
int get status;
#BuiltValueField(wireName: 'user_id')
String get userId;
#BuiltValueField(wireName: 'id_token')
String get idToken;
#BuiltValueField(wireName: 'refresh_token')
String get refreshToken;
SignIn._();
factory SignIn([updates(SignInBuilder b)]) = _$SignIn;
static SignIn fromJson(String jsonString) {
return serializers.deserializeWith(SignIn.serializer,
json.decode(jsonString));
}
}
2.- Serializer
part 'serializers.g.dart';
#SerializersFor(const [SignIn,])
final Serializers serializers =
(_$serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build();
3.- SigninDataSource
class SigninDataSource {
Future<SignIn> signIn ({
String email = '***#hotmail.com',
String apiKey = '****',
String password = '****',
}) async {
var url = "https://api-dev.com/signin";
var body = json.decode('{"email": "$email", "password":
"$password"}');
http.post(url, body: json.encode(body),
headers: {
"x-api-key": apiKey,
"content-type" : "application/json",})
.then((response) {
print("Response status: ${response.statusCode}");
print("Response body: ${response.body}");
return SignIn.fromJson(response.body);
}
);
}
}
I would like that someone can help with this problem.

How to pass data from an utility class to main class in dart

I am creating login view in flutter.I created utility class to handle all the api calling.On Tap am able to make the Api call and also getting the response
successfully.Now the problem is i want to send the response to the main class so that i can parse the data.
Utility.dart:
Future<dynamic> postRequest(String methodName, var body) async{
return await http
.post(Uri.encodeFull(BASE_URL + methodName), body: body, headers: {"Accept":"application/json"})
.then((http.Response response) {
print(response.body);
final int statusCode = response.statusCode;
print("Response obj: ${response.body}");
return response.body;
});
LoginClass.dart:
void _validateInputs() {
if (_email.isNotEmpty && _passWord.isNotEmpty) {
if(_connectionStatus!="ConnectivityResult.none"){
setState(() {
var stringParams = {"Email": _email, "Password": _passWord};
Future<User> response = Utility().postRequest(
"Account/login", stringParams);
if(reponse.statusCode==200){
// Push view to home screen
}
});
}else{
Utility.showAlertPopup(context, "No Internet", "Please check internet connectivity");
}
}
}
class User {
final int UserID;
final int UserName;
User({this.UserID, this.UserName});
factory User.fromJson(Map<String, dynamic> json) {
return User(
UserID: json['userID'],
UserName: json['UserName'],
);
}
M not getting the response back to the login class. What will be the best way to achieve the result.
you should use await in order to wait for the response to return, so your _validateInputs() method should be as follows, and you need to add the setState after you get the response:
void _validateInputs() async{
if (_email.isNotEmpty && _passWord.isNotEmpty) {
if(_connectionStatus!="ConnectivityResult.none"){
var stringParams = {"Email": _email, "Password": _passWord};
Future<User> response = await Utility().postRequest(
"Account/login", stringParams);
setState((){
//add your setState code here, for example remove the loader or something like that
});
if(reponse.statusCode==200){
// Push view to home screen
}
}else{
Utility.showAlertPopup(context, "No Internet", "Please check internet connectivity");
}
}
}

Error in parsing nested JSON list in flutter

Calling API but showing error, I'm unable to parse data in the bean class.
My Response:
{
"error":"0",
"status":200,
"deliveryCharge":"14.00",
"image_base_url":"http:\/\/xxxxx.tk\/assets\/event\/image\/",
"image_logo_url":"http:\/\/xxxxx.tk\/assets\/event\/logo\/",
"eventList":[
{
"event_id":"1",
"event_name":"Syscraft Premier League",
"event_location":"12 ny valleys",
"event_type_id":"15",
"start_date":"2019-01-10 03:21:00",
"end_date":"2019-01-26 16:10:00",
"event_logo":"f4f0bfc168a3816891e2749232c5243f.jpg"
},
{
"event_id":"3",
"event_name":"Republic Day Event 2019",
"event_location":"AH-654 Villa No. 42 New Township New Township",
"event_type_id":"1",
"start_date":"2019-01-26 00:00:00",
"end_date":"2019-01-26 11:55:00",
"event_logo":"3a4a7fabbbd7ed8febf67bacda71ae48.jpg"
}
]
}
Calling Api
Future<List<EventResponse>> fetchEvent( ) async {
String url='http://xxxxxxxxxxxxxxx.tk/api/userapp/event/lists';
var headers = new Map();
headers['Auth-Key'] = 'OCDOC#2018';
headers['End-Client'] = 'OCDOC';
var body = new Map();
headers['schedule'] = 'present';
http.Response res = await http.post(url,headers: headers, body: body);
final Map<String,dynamic> parsed=json.decode(res.body); // post api call
print("Reposnce Event:---"+parsed.toString());}
My Bean class
class EventResponse{
String error;
int status;
String deliveryCharges;
String imageBaseUrl;
String imageLogoUrl;
List<Event> eventList;
EventResponse({
this.error,
this.status,
this.deliveryCharges,
this.imageBaseUrl,
this.imageLogoUrl,
this.eventList
});
factory EventResponse.convertEventResponse(Map<String,dynamic> json){
return EventResponse(
error: json['error'],
status: json['status'],
deliveryCharges: json['deliveryCharge'],
imageBaseUrl: json['image_base_url'],
imageLogoUrl: json['image_logo_url'],
eventList: json['eventList']);
}}
class Event{
String eventId;
String eventName;
String location;
String event_logo;
Event({
this.eventId,
this.eventName,
this.location,
this.event_logo,
});
factory Event.convertEvent(Map<String,dynamic> json){
return Event(
eventId: json['event_id'],
eventName: json['event_name'],
location: json['event_location'],
event_logo: json['event_logo'],
);}}
Showing Error
_InternalLinkedHashMap<dynamic, dynamic> is not a subtype of type Map<String, String>
Rewrite EventResponse like this:
class EventResponse {
String error;
int status;
String deliveryCharges;
String imageBaseUrl;
String imageLogoUrl;
List<Event> eventList;
EventResponse(
{this.error,
this.status,
this.deliveryCharges,
this.imageBaseUrl,
this.imageLogoUrl,
this.eventList});
factory EventResponse.convertEventResponse(Map<String, dynamic> json) {
List<dynamic> events = json['eventList'];
List<Event> eventList = events.map((e) => Event.convertEvent(e)).toList();
return EventResponse(
error: json['error'],
status: json['status'],
deliveryCharges: json['deliveryCharge'],
imageBaseUrl: json['image_base_url'],
imageLogoUrl: json['image_logo_url'],
eventList: eventList,
);
}
}
I have changed EventResponse as #Richard Heap did.
factory EventResponse.convertEventResponse(Map<String, dynamic> json) {
List<dynamic> events = json['eventList'];
List<Event> eventList = events.map((e) => Event.convertEvent(e)).toList();
return EventResponse(
error: json['error'],
status: json['status'],
deliveryCharges: json['deliveryCharge'],
imageBaseUrl: json['image_base_url'],
imageLogoUrl: json['image_logo_url'],
eventList: eventList,
);
}
}
One more thing I need to change is when I post parameters and headers need to define their Map() to Map<String,String>().
Future<EventResponse> fetchEvent( ) async { // here i change Future type
String url='http://xxxxxxx-oceanapparel.tk/api/userapp/event/lists';
var headers = new Map<String, String>(); //here i defined Map type
headers['Auth-Key'] = 'OCDOC#2018';
headers['End-Client'] = 'OCDOC';
var body = new Map<String, String>(); //here i defined Map type
headers['schedule'] = 'present';
http.Response res = await http.post(url,headers: headers, body: body);
print("Reposnce Event:---"+res.body);
}

Get an OAuth2 access token failed with error message "HTTP/1.1 401 Unauthorized"

I am writing OAuth client in JAVA to acquire OAuth token from Central Authentication Service (PingFederate). As this client is standalone utility, there is no application server behind it.
I am trying to achieve : A standalone JAVA client should acquire OAuth token from PingFederate it should allow for some scope, ex. TEST_READ. Once I have access token, I will pass it to resource provider.
So, as per the PingFederate document such standalone client should use the Grant Type=Resource Owner Password Credentials and to acquire Oauth token POST request should contains username/password and client id and secret.
When I attempted the same, I received error in response:
HTTP/1.1 401 Unauthorized [Date: Tue, 28 Aug 2018 09:04:50 GMT, Content-Security-Policy: referrer origin, X-Frame-Options: SAMEORIGIN, Cache-Control: no-cache, no-store, Pragma: no-cache, Expires: Thu, 01 Jan 1970 00:00:00 GMT, Content-Type: application/json;charset=utf-8, WWW-Authenticate: basic realm="PF AS Token Endpoints", Set-Cookie: PF=zVXrZpsAmWwrrVkzgltJZ4;Path=/;Secure;HttpOnly, Transfer-Encoding: chunked] org.apache.http.conn.BasicManagedEntity#68c9133c
To dig more into it, I checked PingFederate audit.log where I found the log: AS| failure| | invalid_client: client_id value doesn't match HTTP Basic username value| 0
Here is my JAVA client code
package com.auth;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.json.simple.parser.JSONParser;
public class OAuth2Client {
public static final String GRANT_TYPE = "grant_type";
public static final String CLIENT_ID = "client_id";
public static final String CLIENT_SECRET = "client_secret";
private static final String AUTHORIZATION = "Authorization";
public static final String BASIC = "Basic";
public static final String ACCESS_TOKEN = "access_token";
public static final String SCOPE = "scope";
public static void main(String[] args) {
System.out.println(getAccessToken());
}
public static String getAccessToken() {
HttpPost post = new HttpPost(
"https://localhost:9031/as/token.oauth2");
String clientId = "OAUTH-CLIENT-TEST";
String clientSecret = "OAUTH-CLIENT-TEST-SECRET";
String scope = "TEST_READ";
String username = "testuser";
String password = "test#001Pass";
List<BasicNameValuePair> parametersBody = new ArrayList<BasicNameValuePair>();
parametersBody.add(new BasicNameValuePair(GRANT_TYPE, "password"));
parametersBody.add(new BasicNameValuePair(CLIENT_ID, clientId));
parametersBody.add(new BasicNameValuePair(CLIENT_SECRET, clientSecret));
parametersBody.add(new BasicNameValuePair(SCOPE, scope));
DefaultHttpClient client = new DefaultHttpClient();
HttpResponse response = null;
String accessToken = null;
try {
//post.setEntity(new UrlEncodedFormEntity(parametersBody, HTTP.UTF_8));
post.setEntity(new UrlEncodedFormEntity(parametersBody));
post.addHeader(AUTHORIZATION,
BASIC + " " + encodeCredentials(username, password));
post.addHeader("Content-Type", "application/x-www-form-urlencoded");
response = client.execute(post);
int code = response.getStatusLine().getStatusCode();
if (code >= 400) {
throw new RuntimeException(
"Could not retrieve access token for user: " + username);
}
Map<String, String> map = handleJsonResponse(response);
accessToken = map.get(ACCESS_TOKEN);
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return accessToken;
}
public static String encodeCredentials(String username, String password) {
String cred = username + ":" + password;
String encodedValue = null;
byte[] encodedBytes = Base64.encodeBase64(cred.getBytes());
encodedValue = new String(encodedBytes);
System.out.println("encodedBytes " + new String(encodedBytes));
byte[] decodedBytes = Base64.decodeBase64(encodedBytes);
System.out.println("decodedBytes " + new String(decodedBytes));
return encodedValue;
}
public static Map handleJsonResponse(HttpResponse response) {
Map<String, String> responseMap = null;
String contentType = response.getEntity().getContentType().getValue();
try {
responseMap = (Map<String, String>) new JSONParser()
.parse(EntityUtils.toString(response.getEntity()));
} catch (ParseException e) {
e.printStackTrace();
throw new RuntimeException();
} catch (org.json.simple.parser.ParseException e) {
e.printStackTrace();
throw new RuntimeException();
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
} catch (RuntimeException e) {
System.out.println("Could not parse JSON response");
throw e;
}
System.out.println();
System.out.println("********** Response Received **********");
for (Map.Entry<String, String> entry : responseMap.entrySet()) {
System.out.println(String.format(" %s = %s", entry.getKey(),
entry.getValue()));
}
return responseMap;
}
}
The grant type "password" requires the user's (or: Resource Owner's) credentials to be passed in the POST parameters (username and password) instead of the Authorization: basic header.

Resources