如何在flutter上使用cookie发出http请求?

SHA*_*R S 12 cookies android http flutter

我想在正确处理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;
}
Run Code Online (Sandbox Code Playgroud)

Ric*_*eap 18

这是一个如何获取会话cookie并在后续请求中返回它的示例.您可以轻松地调整它以返回多个cookie.做一个Session类和路由所有的GETS和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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 根据 RFC,所有标头都不区分大小写,但许多服务器不兼容。为了便于比较,Dart 强制将它们全部转换为小写。 (2认同)

小智 17

我改进了 Richard Heap 的解决方案,使其能够处理多个“设置 cookie”和多个 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);
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢这对我有帮助。在“=”上拆分 rawCookie 时存在一个小错误;当分割中有空字符串时它不起作用。以下修复帮助了我。rawCookie.split('=').where((s) =&gt; s.isNotEmpty).toList(growable: false) (2认同)
  • 比较路径和过期时也忽略大小写 - if (key.toLowerCase() != 'path' &amp;&amp; key.toLowerCase() != 'expires') { return {key: value}; } (2认同)

Jos*_*ush 5

我已经发布了一个名为请求的小型flutter库,以帮助支持cookie的http请求。

dependencies:
  requests: ^3.0.1
Run Code Online (Sandbox Code Playgroud)

用法:

import 'package:requests/requests.dart';

// ...

// this will persist cookies
var r1 = await Requests.post("https://example.com/api/v1/login", json: {"username":"...", "password":"..."} ); 
r1.raiseForStatus();

// this will re-use the persisted cookies
var r2 = await Requests.get("https://example.com/api/v1/stuff"); 
r2.raiseForStatus();
print(r2.json()['id'])
Run Code Online (Sandbox Code Playgroud)

了解有关请求的更多信息


小智 5

我将拉里的答案迁移到了 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);
    });
  }
}
Run Code Online (Sandbox Code Playgroud)