HTTP request in flutter - android

I am using Retrofit for Android. It is easy to retrieve and upload JSON via a REST based web service. Can we get any library which is equivalent to Retrofit for web services in Flutter?

Update
Originally I wrote the answer here first, but I ended up writing a more detailed post later:
How to make HTTP requests in Flutter
The full source code is there, too.
How to make HTTP requests in Flutter
This answer tells how to make HTTP requests using the http package by the Dart team. If more advanced functionality is needed, check out the Dio package mentioned in the comments.
We will be using JSONPlaceholder as a target for our API examples below.
GET /posts
GET /posts/1
GET /posts/1/comments
GET /comments?postId=1
GET /posts?userId=1
POST /posts
PUT /posts/1
PATCH /posts/1
DELETE /posts/1
Setup
Add the http package dependency in pubspec.yaml.
dependencies:
http: ^0.12.0+1
GET requests
_makeGetRequest() async {
// make request
final response = await get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
// sample info available in response
final statusCode = response.statusCode;
final headers = response.headers;
final contentType = headers['content-type'];
final json = response.body;
// TODO convert json to object...
}
Replace /posts with /posts/1 and the other GET requests mentioned above. Using posts returns an array of JSON objects while /posts/1 returns a single JSON object. You can use dart:convert to convert the raw JSON string to objects.
POST request
_makePostRequest() async {
// set up POST request arguments
final url = Uri.parse('https://jsonplaceholder.typicode.com/posts');
final headers = {"Content-type": "application/json"};
final json = '{"title": "Hello", "body": "body text", "userId": 1}';
// make POST request
final response = await post(url, headers: headers, body: json);
// check the status code for the result
final statusCode = response.statusCode;
// this API passes back the id of the new item added to the body
final body = response.body;
// {
// "title": "Hello",
// "body": "body text",
// "userId": 1,
// "id": 101
// }
}
PUT request
A PUT request is meant to replace a resource or create it if it doesn't exist.
_makePutRequest() async {
// set up PUT request arguments
final url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
final headers = {"Content-type": "application/json"};
final json = '{"title": "Hello", "body": "body text", "userId": 1}';
// make PUT request
final response = await put(url, headers: headers, body: json);
// check the status code for the result
final statusCode = response.statusCode;
// this API passes back the updated item with the id added
final body = response.body;
// {
// "title": "Hello",
// "body": "body text",
// "userId": 1,
// "id": 1
// }
}
PATCH request
A PATCH request is meant to modify a existing resource.
_makePatchRequest() async {
// set up PATCH request arguments
final url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
final headers = {"Content-type": "application/json"};
final json = '{"title": "Hello"}';
// make PATCH request
final response = await patch(url, headers: headers, body: json);
// check the status code for the result
final statusCode = response.statusCode;
// only the title is updated
final body = response.body;
// {
// "userId": 1,
// "id": 1
// "title": "Hello",
// "body": "quia et suscipit\nsuscipit recusandae... (old body text not changed)",
// }
}
Notice that the JSON string that is passed in only includes the title, not the other parts like in the PUT example.
DELETE request
_makeDeleteRequest() async {
// post 1
final url = Uri.parse('https://jsonplaceholder.typicode.com/posts/1');
// make DELETE request
final response = await delete(url);
// check the status code for the result
final statusCode = response.statusCode;
}
Authentication
Although the demo site we used above did not require it, if you need to include authentication headers, you can do it like this:
Basic Authentication
// import 'dart:convert'
final username = 'username';
final password = 'password';
final credentials = '$username:$password';
final stringToBase64Url = utf8.fuse(base64Url);
final encodedCredentials = stringToBase64Url.encode(credentials);
final headers = {
HttpHeaders.contentTypeHeader: "application/json", // or whatever
HttpHeaders.authorizationHeader: "Basic $encodedCredentials",
};
Bearer (token) Authentication
// import 'dart:io';
final token = 'WIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpv';
final headers = {
HttpHeaders.contentTypeHeader: "application/json", // or whatever
HttpHeaders.authorizationHeader: "Bearer $token",
};
Related
What is the difference between PUT, POST and PATCH?

Well for me at least you will need 3 packages.
json_serializable
Dio Http Client
retrofit for dart
I have tried chopper but I prefer the dio way of doing things. it is closer and more flexible.

get to the location of pubspac.yaml run cmd
> flutter pub get
> flutter packages get
add
http: ^0.11.3+16
in pubspac.yaml
get dependencies.
try to import library, hopes this helps!

Just simple use this plug and little code for GET http url
add this plugin from here httppackage
http: ^0.12.0+2
USAGE
final uri = Constants.BASE_URL + 'endpoint';
final headers = {'Content-Type': 'application/x-www-form-urlencoded'};//if required
Response getResponse = await get(uri, headers: headers);
int statusCode = getResponse.statusCode;
String responseBody = getResponse.body;
print('response----' + responseBody);

similar to android we do have a flutter retrofit package https://pub.dev/packages/retrofit
but in flutter http package used very widely.
To use this
Add dependency to pubspec.yaml
dependencies:
http: ^0.13.1
Note: Always use latest dependency
Usage:
import 'package:http/http.dart' as http;
void main() async {
print("main Method");
String url =
"https://5f383e6541c94900169bfd42.mockapi.io/api/v1/user_details";
final response = await http.get(Uri.parse(url));
print(response.body);
}
This package provides easy options to add headers and body while get/post data

Related

Why am I getting 413 request entity too large error when I make post request in flutter?

Im trying to make post request in flutter as shown below
uploadImage() async {
print('inside uploadimage function');
WidgetsBinding.instance.addPostFrameCallback((_) => setState((){isLoading = true;} ));
final request = http.MultipartRequest(
"POST", Uri.parse('http://server/upload'));
final headers = {"Content-type":"multipart/form-data"};
request.files.add( http.MultipartFile('image1',
widget.imagefile1!.readAsBytes().asStream(),widget.imagefile1!.lengthSync(),
filename: widget.imagefile1!.path.split("/").last));
request.files.add(http.MultipartFile('image2',
imageFile!.readAsBytes().asStream(),imageFile!.lengthSync(),
filename: imageFile!.path.split("/").last));
request.headers.addAll(headers);
final response = await request.send();
http.Response res = await http.Response.fromStream(response);
print('statuscode:');
print(response.statusCode);
print(response.reasonPhrase);
}
as a response I get error 413 request entity too large but when I make a request through POSTMAN i can successfully make a request with status 200 OK. as shown below
I'm not able to figureout why this happening any help or suggestion on how to solve this will be highly appreciated thanks

XF 504 on Get request when using Android HttpClient implementation

In my Xamarin Forms app I have a very basic GET request that results in a 504 'Method not allowed' on Android.
This is the controller that I am calling:
[AllowAnonymous]
[HttpGet]
[Route("api/system/backendversion")]
public int GetBackendVersion()
{
return 20200924;
}
This is the code that performs the request
var _client = new HttpClient();
var content = new StringContent(json, Encoding.UTF8, "application/json");
var httpRequest = new HttpRequestMessage(httpMethod, url)
{
Content = content,
Version = HttpVersion.Version10
};
var response = await _client.SendAsync(httpRequest);
The problem disappears when I change the HttpClient implementation from "Android" to "Managed".
Also the webrequest works fine in the XF.UWP version of my app.
I believe I put it on Android for a reason, but I'm unsure what the reason was (probably speed). I'm curious what goes wrong here.
Apperantly it breaks because the content (header?) is set to json when there is no json.
I fixed it like this:
var httpRequest = new HttpRequestMessage(httpMethod, url)
{
Version = HttpVersion.Version10
};
if (!string.IsNullOrWhiteSpace(json))
{
httpRequest.Content = new StringContent(json, Encoding.UTF8, "application/json");
}
var response = await _client.SendAsync(httpRequest);
this error is similar to iOS where you get an error if you put json body in a get request
if (httpMethod == HttpMethod.Get && !string.IsNullOrWhiteSpace(json))
{
Debugger.Break();//a get request with a body is not allowed on iOS and results in a error https://stackoverflow.com/questions/56955595/1103-error-domain-nsurlerrordomain-code-1103-resource-exceeds-maximum-size-i
}

Receiving a json from an API on Flutter app

I'm trying to receive the response on a http post but the response comes empty. I know its something basic but i can't make it work.
It should receive a JSON with some data, but the data doesn't come, probably its a problem on the reply part on my code.
Heres the code:
Future<void> _login2() async {
HttpClient client = new HttpClient();
client.badCertificateCallback =
((X509Certificate cert, String host, int port) => true);
String url = 'https://sistema.hutransportes.com.br/api/login.php';
Map map = {"user": "test", "pass": "123456"};
HttpClientRequest request = await client.postUrl(Uri.parse(url));
request.headers.set('content-type', 'application/json');
request.add(utf8.encode(json.encode(map)));
HttpClientResponse response = await request.close();
String reply = await response.transform(utf8.decoder).join();
print(reply); //should show the data from the http
}
I would recommend you to use the powerful library https://pub.dev/packages/dio

_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'List<Map<dynamic, dynamic>>'

void makeLoginReq() async {
String url = 'https://travel.prabidhee.com/api/login';
Map map = {
'email': email,
'password': password,
};
print(await apiRequest(url, map));
final response = await apiRequest(url, map);
print(response);
List<Map> reply = json.decode(response);
List<UserModelData> result = reply.map((item) => new UserModelData.fromJson(item)).toList();
print(result[0].accessToken);
}
Future<String> apiRequest(String url, Map jsonMap) async {
HttpClient httpClient = new HttpClient();
HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
request.headers.set('Accept', 'application/json');
request.headers.set('Content-type', 'application/json');
request.add(utf8.encode(json.encode(jsonMap)));
HttpClientResponse response = await request.close();
var reply = await response.transform(utf8.decoder).join();
httpClient.close();
print(reply);
return (reply);
}
}
This is the function for a login request in remote server. After Login json responses are decoded and stored in reply variable. Now i want to extract each elements like access_token , token_type... from the response. How can I do that ?
As the exception reads, you're problem is that you are casting a map into a list, which is not possible. Just as you can't cast a String to an integer or as you can't treat a rainworm as a horse and ride on it to the sunset.
The question of course is why that happens:
The line json.decode(response) returns a map but the variable that you want to assign this map may only store a list.
For example, if your response looks something like this:
{
"body": [
"Alisa",
"Alex",
"Boby",
"Monica"
]
}
Then your json.decode(response) is going to be Map<String, List>("body" to ["Alisa", ...]), so body is mapped to the names.
Assuming that you want to isolate the list from the other json, you can just do json.decode(response).get("body") or if youre json looks different, you can also get all values or keys in the map by calling json.decode(response).values() or json.decode(response).keys().

Xamarin android invalid uri exception

In my Xamarin android application I need to make an api call to openweathermap to get current weather data according to the user's current location.
Here is my query string code:
url = "api.openweathermap.org/data/2.5/weather?lat=" +
_currentLocation.Latitude +
"&lon=" +
_currentLocation.Longitude +
"&APPID=" + openWeatherAPIKey
+ "&units=imperial";
Now in the method FetchUrlAsync I send the web request and retrieve the response json. Below is the code of the method:
async Task<JsonValue> FetchUrlAsync(string url)
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(new System.Uri(url));
request.ContentType = "application/json";
request.Method = "GET";
using (WebResponse response = await request.GetResponseAsync())
{
// Get a stream representation of the HTTP web response:
using (System.IO.Stream stream = response.GetResponseStream())
{
// Use this stream to build a JSON document object:
JsonValue jsonDoc = await Task.Run(() => JsonObject.Load(stream));
Console.Out.WriteLine("Response: {0}", jsonDoc.ToString());
// Return the JSON document:
return jsonDoc;
}
}
}
I get a System.URIFormatException thrown on the first line of the method because the format of the uri is wrong. I checked other stack overflow questions and I think it might be because my url string does not start with a http:// or ftp. But I can't add http:// or ftp in front of the url string because that leads to an unrecognized server.
Any solution to this issue? Or does it not have to do with adding the http:// or ftp prefix?

Categories

Resources