抱歉,如果这个问题太基础了,但我是 flutter 的新手,最近找不到在 HTTP 请求中设置默认标头的好方法我可以扩展该类或为其包装一个函数,但不应该有一种内置的简单方法,但我在文档中找不到它。
这可以很容易地用 Dio 包制作。
https://pub.dartlang.org/packages/dio
更新
基于新的 Dio API:
var dio = Dio();
dio.interceptors.add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
var customHeaders = {
'content-type': 'application/json'
// other headers
};
options.headers.addAll(customHeaders);
return options;
}));
Response response = await dio.get("url");
print(response.data.toString());
有关详细信息,请参阅文档。
import 'package:http/http.dart' as http;
class MyClient extends http.BaseClient{
http.Client _httpClient = new http.Client();
MyClient(Map defaultHeaders);
@override
Future<http.StreamedResponse> send(http.BaseRequest request) {
request.headers.addAll(defaultHeaders);
return _httpClient.send(request);
}
}
Dart 允许注册一个工厂来创建一个
HttpClient
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext context) {
return new MyHttpClient(super.createHttpClient(context));
}
}
void main() {
HttpOverrides.global = new MyHttpOverrides();
runApp(MyApp());
}
实现这样的自定义
HttpClient
似乎过于复杂,但也许有更好的方法。
该类从
HttpClient
及其所有抽象类中实现dart:io
。
方法
get(...)
和getUrl(...)
被自定义为使用_updateHeaders(...)
添加自定义标题。您需要将其扩展到所有其他方法,例如 head
、headUrl
、open
、post
、...
import 'dart:io';
class MyHttpClient implements HttpClient {
HttpClient _realClient;
MyHttpClient(this._realClient);
@override
bool get autoUncompress => _realClient.autoUncompress;
@override
set autoUncompress(bool value) => _realClient.autoUncompress = value;
@override
Duration get connectionTimeout => _realClient.connectionTimeout;
@override
set connectionTimeout(Duration value) =>
_realClient.connectionTimeout = value;
@override
Duration get idleTimeout => _realClient.idleTimeout;
@override
set idleTimeout(Duration value) => _realClient.idleTimeout = value;
@override
int get maxConnectionsPerHost => _realClient.maxConnectionsPerHost;
@override
set maxConnectionsPerHost(int value) =>
_realClient.maxConnectionsPerHost = value;
@override
String get userAgent => _realClient.userAgent;
@override
set userAgent(String value) => _realClient.userAgent = value;
@override
void addCredentials(
Uri url, String realm, HttpClientCredentials credentials) =>
_realClient.addCredentials(url, realm, credentials);
@override
void addProxyCredentials(String host, int port, String realm,
HttpClientCredentials credentials) =>
_realClient.addProxyCredentials(host, port, realm, credentials);
@override
void set authenticate(
Future<bool> Function(Uri url, String scheme, String realm) f) =>
_realClient.authenticate = f;
@override
void set authenticateProxy(
Future<bool> Function(
String host, int port, String scheme, String realm)
f) =>
_realClient.authenticateProxy = f;
@override
void set badCertificateCallback(
bool Function(X509Certificate cert, String host, int port)
callback) =>
_realClient.badCertificateCallback = callback;
@override
void close({bool force = false}) => _realClient.close(force: force);
@override
Future<HttpClientRequest> delete(String host, int port, String path) =>
_realClient.delete(host, port, path);
@override
Future<HttpClientRequest> deleteUrl(Uri url) => _realClient.deleteUrl(url);
@override
void set findProxy(String Function(Uri url) f) => _realClient.findProxy = f;
@override
Future<HttpClientRequest> get(String host, int port, String path) =>
_updateHeaders(_realClient.get(host, port, path));
Future<HttpClientRequest> _updateHeaders(
Future<HttpClientRequest> httpClientRequest) async {
return (await httpClientRequest)..headers.add('foo', 'bar');
}
@override
Future<HttpClientRequest> getUrl(Uri url) =>
_updateHeaders(_realClient.getUrl(url.replace(path: url.path)));
@override
Future<HttpClientRequest> head(String host, int port, String path) =>
_realClient.head(host, port, path);
@override
Future<HttpClientRequest> headUrl(Uri url) => _realClient.headUrl(url);
@override
Future<HttpClientRequest> open(
String method, String host, int port, String path) =>
_realClient.open(method, host, port, path);
@override
Future<HttpClientRequest> openUrl(String method, Uri url) =>
_realClient.openUrl(method, url);
@override
Future<HttpClientRequest> patch(String host, int port, String path) =>
_realClient.patch(host, port, path);
@override
Future<HttpClientRequest> patchUrl(Uri url) => _realClient.patchUrl(url);
@override
Future<HttpClientRequest> post(String host, int port, String path) =>
_realClient.post(host, port, path);
@override
Future<HttpClientRequest> postUrl(Uri url) => _realClient.postUrl(url);
@override
Future<HttpClientRequest> put(String host, int port, String path) =>
_realClient.put(host, port, path);
@override
Future<HttpClientRequest> putUrl(Uri url) => _realClient.putUrl(url);
}
这个简单易行的方法对我有用
var _dio = Dio();
_dio.options.headers= {"Authorization" : token};
只是扩展@Radek Manasek 的自定义想法
Client
,我正在覆盖所有方法,因此您不必再次编写它们。
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:http/http.dart';
class MyClient extends http.BaseClient {
final Map<String, String> _defaultHeaders;
http.Client _httpClient = http.Client();
MyClient(this._defaultHeaders);
@override
Future<http.StreamedResponse> send(http.BaseRequest request) {
return _httpClient.send(request);
}
@override
Future<Response> get(url, {Map<String, String> headers}) {
return _httpClient.get(url, headers: _mergedHeaders(headers));
}
@override
Future<Response> post(url, {Map<String, String> headers, dynamic body, Encoding encoding}) {
return _httpClient.post(url, headers: _mergedHeaders(headers), body: body, encoding: encoding);
}
@override
Future<Response> patch(url, {Map<String, String> headers, dynamic body, Encoding encoding}) {
return _httpClient.patch(url, headers: _mergedHeaders(headers), body: body, encoding: encoding);
}
@override
Future<Response> put(url, {Map<String, String> headers, dynamic body, Encoding encoding}) {
return _httpClient.put(url, headers: _mergedHeaders(headers), body: body, encoding: encoding);
}
@override
Future<Response> head(url, {Map<String, String> headers}) {
return _httpClient.head(url, headers: _mergedHeaders(headers));
}
@override
Future<Response> delete(url, {Map<String, String> headers}) {
return _httpClient.delete(url, headers: _mergedHeaders(headers));
}
Map<String, String> _mergedHeaders(Map<String, String> headers) =>
{...?_defaultHeaders, ...?headers};
}
我正在创建一个单例类并在其中初始化 dio 并在我所有需要执行 http 请求的控制器中使用它。
首先有两种方法可以在 dio 客户端中添加标头
_dio.interceptors.addAll([
InterceptorsWrapper(
onRequest: (options, handler) {
options.headers.addAll({'authorization': 'Bearer $_authToken'});
handler.next(options);
},
),
CustomInterceptors(), // your other interceptors
]);
第二个是这样的
void setAuthToken(String token) {
_authToken = token;
_dio.options.headers['authorization'] = 'Bearer $token';
}
第一种方法会在发出每个请求之前添加标头,因此我们可以根据我们的业务逻辑添加条件。所以第一种方法比第二种方法好得多。
在@Radek 和@vovahost 上的扩展使它们的实现适用于库更新,并添加了检查状态代码和在某些响应中抛出错误的功能。
import 'dart:async';
import 'dart:convert';
import 'package:http/http.dart';
import 'package:http/http.dart' as http;
class BaseNetworkClient extends http.BaseClient {
Map<String, String> _defaultHeaders = {
'Content-Type': 'application/json',
};
final http.Client _httpClient = http.Client();
addTokenToHeader(String token) {
_mergedHeaders({"auth_token": token});
}
Map<String, String> _mergedHeaders(Map<String, String> headers) =>
{...?_defaultHeaders, ...?headers};
@override
Future<http.StreamedResponse> send(http.BaseRequest request) {
return _httpClient.send(request).then((response) async {
_checkError( await http.Response.fromStream(response));
return response;
});
}
@override
Future<Response> get(url, {Map<String, String>? headers}) {
return _httpClient
.get(url,
headers:
headers != null ? _mergedHeaders(headers) : _defaultHeaders)
.then(_checkError);
}
@override
Future<Response> post(url,
{Map<String, String>? headers, dynamic body, Encoding? encoding}) {
return _httpClient
.post(url,
headers:
headers != null ? _mergedHeaders(headers) : _defaultHeaders,
body: body,
encoding: encoding)
.then(_checkError);
}
@override
Future<Response> patch(url,
{Map<String, String>? headers, dynamic body, Encoding? encoding}) {
return _httpClient
.patch(url,
headers:
headers != null ? _mergedHeaders(headers) : _defaultHeaders,
body: body,
encoding: encoding)
.then(_checkError);
}
@override
Future<Response> put(url,
{Map<String, String>? headers, dynamic body, Encoding? encoding}) {
return _httpClient
.put(url,
headers:
headers != null ? _mergedHeaders(headers) : _defaultHeaders,
body: body,
encoding: encoding)
.then(_checkError);
}
@override
Future<Response> head(url, {Map<String, String>? headers}) {
return _httpClient
.head(url,
headers:
headers != null ? _mergedHeaders(headers) : _defaultHeaders)
.then(_checkError);
}
@override
Future<Response> delete(url,
{Map<String, String>? headers, Object? body, Encoding? encoding}) {
return _httpClient
.delete(url,
headers:
headers != null ? _mergedHeaders(headers) : _defaultHeaders)
.then(_checkError);
}
Response _checkError(Response response) {
final int? statusCode = response.statusCode;
if (statusCode == null) {
throw //Todoo: add custom exception don't expect response.body
} else if (statusCode < 200 || statusCode > 400) {
throw //Todoo: add custom exception
}
return response;
}
}