我想在正确处理cookie的同时向远程服务器发出http请求(例如,存储服务器发送的cookie,并在随后的请求中发送这些cookie)。保留所有cookie很好
我正在使用的http请求
static Future<Map> postData(Map data) async {
http.Response res = await http.post(url, body: data); // post api call
Map data = JSON.decode(res.body);
return data;
}
答案 0 :(得分:6)
这是一个如何获取会话cookie并在后续请求时将其返回的示例。您可以轻松调整它以返回多个cookie。制作一个Session
类,并通过它路由所有GET
和POST
。
class Session {
Map<String, String> headers = {};
Future<Map> get(String url) async {
http.Response response = await http.get(url, headers: headers);
updateCookie(response);
return json.decode(response.body);
}
Future<Map> post(String url, dynamic data) async {
http.Response response = await http.post(url, body: data, headers: headers);
updateCookie(response);
return json.decode(response.body);
}
void updateCookie(http.Response response) {
String rawCookie = response.headers['set-cookie'];
if (rawCookie != null) {
int index = rawCookie.indexOf(';');
headers['cookie'] =
(index == -1) ? rawCookie : rawCookie.substring(0, index);
}
}
}
答案 1 :(得分:1)
我改进了Richard Heap的解决方案,使其能够处理多个“ Set-cookies”和多个cookie。
在我的情况下,服务器返回多个“ Set-cookies”。 http包将所有set-cookies标头连接在一个标头中,并用逗号(',')分隔。
class NetworkService {
final JsonDecoder _decoder = new JsonDecoder();
final JsonEncoder _encoder = new JsonEncoder();
Map<String, String> headers = {"content-type": "text/json"};
Map<String, String> cookies = {};
void _updateCookie(http.Response response) {
String allSetCookie = response.headers['set-cookie'];
if (allSetCookie != null) {
var setCookies = allSetCookie.split(',');
for (var setCookie in setCookies) {
var cookies = setCookie.split(';');
for (var cookie in cookies) {
_setCookie(cookie);
}
}
headers['cookie'] = _generateCookieHeader();
}
}
void _setCookie(String rawCookie) {
if (rawCookie.length > 0) {
var keyValue = rawCookie.split('=');
if (keyValue.length == 2) {
var key = keyValue[0].trim();
var value = keyValue[1];
// ignore keys that aren't cookies
if (key == 'path' || key == 'expires')
return;
this.cookies[key] = value;
}
}
}
String _generateCookieHeader() {
String cookie = "";
for (var key in cookies.keys) {
if (cookie.length > 0)
cookie += ";";
cookie += key + "=" + cookies[key];
}
return cookie;
}
Future<dynamic> get(String url) {
return http.get(url, headers: headers).then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
_updateCookie(response);
if (statusCode < 200 || statusCode > 400 || json == null) {
throw new Exception("Error while fetching data");
}
return _decoder.convert(res);
});
}
Future<dynamic> post(String url, {body, encoding}) {
return http
.post(url, body: _encoder.convert(body), headers: headers, encoding: encoding)
.then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
_updateCookie(response);
if (statusCode < 200 || statusCode > 400 || json == null) {
throw new Exception("Error while fetching data");
}
return _decoder.convert(res);
});
}
}
答案 2 :(得分:1)
我已经发布了一个名为requests的小型flutter库,以帮助处理支持cookie的http请求。
dependencies:
requests: ^1.0.0
用法:
import 'package:requests/requests.dart';
// ...
// this will persist cookies
await Requests.post("https://example.com/api/v1/login", body: {"username":"...", "password":"..."} );
// this will re-use the persisted cookies
dynamic data = await Requests.get("https://example.com/api/v1/stuff", json: true);
答案 3 :(得分:1)
我找到了处理Cookie以便重定向的最佳解决方案
import 'dart:convert';
import 'dart:io';
class CustomHTTPClient{
final HttpClient _client = new HttpClient();
Map<String, String> _cookies = Map();
CustomHTTPClient(){
_client.connectionTimeout = Duration(seconds: 10);
}
Future<String> get(String url, {int maxRedirect = 3}) async {
final parsedUrl = Uri.parse(url);
return await _client.getUrl(parsedUrl)
.then((HttpClientRequest request) {
request.followRedirects = false;
_beforeRequest(request);
return request.close();
}).then((HttpClientResponse response) async {
_afterResponse(response);
if(response.isRedirect && maxRedirect > 0){
return await response.drain().then((value) => get(parsedUrl.resolve(response.headers.value('location')).toString(), maxRedirect: maxRedirect - 1));
}
return response.transform(utf8.decoder).join();
}).catchError((error, stack){
print(error);print(stack);
});
}
void _beforeRequest(HttpClientRequest request){
request.headers.set(HttpHeaders.acceptEncodingHeader, 'gzip, deflate, br');
// Set cookie
final String rawCookies = _cookies.keys.map((String name) => '$name=${_cookies[name]}').join('; ');
if(rawCookies.isNotEmpty) request.headers.set(HttpHeaders.cookieHeader, rawCookies);
}
void _afterResponse(HttpClientResponse response){
response.headers.forEach((String name, List<String> values){
if(name == 'set-cookie'){ // Get cookies for next request
values.forEach((String rawCookie){
try{
Cookie cookie = Cookie.fromSetCookieValue(rawCookie);
_cookies[cookie.name] = cookie.value;
} catch(e){
final List<String> cookie = rawCookie.split(';')[0].split('=');
_cookies[cookie[0]] = cookie[1];
}
});
return false;
}
});
}
}
答案 4 :(得分:0)
我将 larly's answer 迁移到了 nullsafety。 还添加了“放置”功能。
import 'dart:convert';
import 'package:http/http.dart' as http;
class NetworkService {
final JsonDecoder _decoder = const JsonDecoder();
final JsonEncoder _encoder = const JsonEncoder();
Map<String, String> headers = {"content-type": "application/json"};
Map<String, String> cookies = {};
void _updateCookie(http.Response response) {
String? allSetCookie = response.headers['set-cookie'];
if (allSetCookie != null) {
var setCookies = allSetCookie.split(',');
for (var setCookie in setCookies) {
var cookies = setCookie.split(';');
for (var cookie in cookies) {
_setCookie(cookie);
}
}
headers['cookie'] = _generateCookieHeader();
}
}
void _setCookie(String? rawCookie) {
if (rawCookie != null) {
var keyValue = rawCookie.split('=');
if (keyValue.length == 2) {
var key = keyValue[0].trim();
var value = keyValue[1];
// ignore keys that aren't cookies
if (key == 'path' || key == 'expires') return;
cookies[key] = value;
}
}
}
String _generateCookieHeader() {
String cookie = "";
for (var key in cookies.keys) {
if (cookie.isNotEmpty) cookie += ";";
cookie += key + "=" + cookies[key]!;
}
return cookie;
}
Future<dynamic> get(String url) {
return http.get(Uri.parse(url), headers: headers).then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
_updateCookie(response);
if (statusCode < 200 || statusCode > 400) {
throw Exception("Error while fetching data");
}
return _decoder.convert(res);
});
}
Future<dynamic> post(String url, {body, encoding}) {
return http.post(Uri.parse(url), body: _encoder.convert(body), headers: headers, encoding: encoding).then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
_updateCookie(response);
if (statusCode < 200 || statusCode > 400) {
throw Exception("Error while fetching data");
}
return _decoder.convert(res);
});
}
Future<dynamic> put(String url, {body, encoding}) {
return http.put(Uri.parse(url), body: _encoder.convert(body), headers: headers, encoding: encoding).then((http.Response response) {
final String res = response.body;
final int statusCode = response.statusCode;
_updateCookie(response);
if (statusCode < 200 || statusCode > 400) {
throw Exception("Error while fetching data");
}
return _decoder.convert(res);
});
}
}