如何在Flutter中发出HTTP请求

发布于2/1/2020 来自:「前端知否」微信公众号

在这篇文章中,我会介绍Dart如何使用http包发出HTTP请求。

我们将使用JSONPlaceholder作为下面我们的API示例的数据提供者。

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

起步

在pubspec.yaml中添加http包依赖项。

dependencies:
http: ^0.12.0+4

导入库:

import 'package:http/http.dart';

GET 请求

_makeGetRequest() async {  

// 发起 GET 请求
String url = 'https://jsonplaceholder.typicode.com/posts';
Response response = await get(url);

// 响应信息
int statusCode = response.statusCode;
Map<String, String> headers = response.headers;
String contentType = headers['content-type'];
String json = response.body;

// TODO 把json数据转换为对象...

}

现在,在网址中将/posts替换为/posts /1。使用/ posts返回JSON对象数组,而/posts /1返回单个JSON对象,其中1是您要获取的帖子的ID。

您可以使用dart:convert将原始JSON字符串转换为对象。

POST请求

POST请求用于创建新资源。

_makePostRequest() async {  
// 创建 POST 请求参数
String url = 'https://jsonplaceholder.typicode.com/posts';

Map<String, String> headers = {"Content-type": "application/json"};

String json = '{"title": "Hello", "body": "body text", "userId": 1}';

// 发起 POST 请求
Response response = await post(url, headers: headers, body: json);

// 检查响应结果状态码
int statusCode = response.statusCode;

// API返回新添加的对象数据
String body = response.body;
// {
// "title": "Hello",
// "body": "body text",
// "userId": 1,
// "id": 101
// }
}

PUT请求

PUT请求旨在替换或创建资源(如果资源不存在)。

_makePutRequest() async {  
// 创建 PUT 请求参数
String url = 'https://jsonplaceholder.typicode.com/posts/1';

Map<String, String> headers = {"Content-type": "application/json"};

String json = '{"title": "Hello", "body": "body text", "userId": 1}';

// 发起 PUT 请求
Response response = await put(url, headers: headers, body: json);

// 检查响应结果状态码
int statusCode = response.statusCode;

// API返回更新后的项目
String body = response.body;
// {
// "title": "Hello",
// "body": "body text",
// "userId": 1,
// "id": 1
// }
}

PATCH请求

PATCH请求旨在修改现有资源。

_makePatchRequest() async {  

// 创建 PATCH 请求参数
String url = 'https://jsonplaceholder.typicode.com/posts/1';

Map<String, String> headers = {"Content-type": "application/json"};

String json = '{"title": "Hello"}';

// 发起 PATCH 请求
Response response = await patch(url, headers: headers, body: json);

// 检查响应结果状态码
int statusCode = response.statusCode;

// 只有title更新了
String body = response.body;
// {
// "userId": 1,
// "id": 1
// "title": "Hello",
// "body": "quia et suscipit\nsuscipit recusandae... (old body text not changed)",
// }
}

请注意,传入参数中的JSON字符串仅包含标题,而不包括PUT示例中的其他部分。

DELETE请求

DELETE请求当然是用于删除资源的。

_makeDeleteRequest() async {  

// 帖子1
String url = 'https://jsonplaceholder.typicode.com/posts/1';

// 发起 DELETE 请求
Response response = await delete(url);

// 检查响应结果状态码
int statusCode = response.statusCode;
}

授权认证

尽管我们上面使用的示例不需要它,但在现实生活中,您需要使用身份验证请求头,尤其是在执行GET请求以外的操作时。您可以将请求头添加到任何请求,尽管通常将基本凭据(用户名和密码)添加到初始POST请求(用来登录),然后将返回的令牌用于后续请求。

基本认证

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

final username = 'username';
final password = 'password';
final credentials = '$username:$password';
final stringToBase64 = utf8.fuse(base64);
final encodedCredentials = stringToBase64.encode(credentials);

Map<String, String> headers = {
HttpHeaders.contentTypeHeader: "application/json", // 或者其他
HttpHeaders.authorizationHeader: "Basic $encodedCredentials",
};

在OAuth设置中,您可以将客户端ID和密码放在auth请求头中,并将用户名和密码放在正文中。

请注意,我在这里使用了HttpHeaders常量,这需要导入dart:io。随意使用字符串"content-type"和"authorization"

Bearer (token) 认证

final token = 'WIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ikpv';

Map<String, String> headers = {
HttpHeaders.contentTypeHeader: "application/json", // 或者其他
HttpHeaders.authorizationHeader: "Bearer $token",
};