Dart에서 http 라이브러리를 사용할 때 여러 set-cookie의 대응 방법

http 라이브러리에서 여러 set-cookie 반환


개시하다


고마워요, 저도요.
이번Dart言語에는HTTP通信할 때의defact 표준http[1]라이브러리에 보유한 쿠키의 문제와 잠정적인 해결 방법에 대한 기사를 썼다.
[2]

우선


이것http창고는 매우 정련되고 완성도가 높아 실현하기 쉽다HTTP通信.
예를 들어 Dart言語에서 GET通信 조작을 하려면 http로 다음과 같은 처리를 기술하면 된다.
import 'package:http/http.dart' as http;

void main() async {
    final response = await http.get(Uri.parse('https://example.com'));
}
POST通信를 생각하면 다음과 같은 느낌이 든다.
import 'package:http/http.dart' as http;

void main() async {
  final response = await http.post(Uri.parse('https://example.com'), body: {
    'name': 'doodle',
    'color': 'blue',
  });
}
깔끔하고 멋집니다.

무슨 문제라도 있습니까?


하지만 아쉬운 규격도 있다.아쉬운 방법 중 하나는 이번 기사의 주제인 쿠키의 접근법이다.http 프로그램 라이브러리HTTP通信를 사용할 때 응답 헤더에 하나set-cookie만 설정하고 돌아오면 문제가 없지만 여러 개set-cookie를 설정하면 쉼표 구분자로 결합해서 돌려줍니다.
구체적인 상황은 다음과 같다.

문제가 되는 장면.


예를 들어 다음과 같은 몇 개set-cookie가 반환된 장면이 문제가 됐다.
set-cookie: AWSALB=TEST; Expires=Tue, 03 May 2022 02:03:35 GMT; Path=/
set-cookie: AWSALBCORS=TEST; set-cookie: Expires=Tue, 03 May 2022 02:03:35 GMT; Path=/; SameSite=None; Secure
set-cookie: jwt_token=TEST; Domain=.example.com; Max-Age=31536000; Path=/; expires=Wed, 26-Apr-2023 02:03:35 GMT; SameSite=lax; Secure
set-cookie: csrf_token=TEST; Domain=.example.com; Max-Age=31536000; Path=/; expires=Wed, 26-Apr-2023 02:03:35 GMT
set-cookie: csrf_token=TEST; Domain=.example.com; Max-Age=31536000; Path=/; expires=Wed, 26-Apr-2023 02:03:35 GMT
라이브러리에서 되돌아오는 set-cookie 필드에서 여러 개http를 사용하면 이렇게 됩니다.
import 'package:http/http.dart' as http;

void main() async {
  final response = await http.get(Uri.parse('https://example.com'));

  print(response.headers['set-cookie']);
}
AWSALB=TEST; Expires=Tue, 03 May 2022 02:03:35 GMT; Path=/,AWSALBCORS=TEST; set-cookie: Expires=Tue, 03 May 2022 02:03:35 GMT; Path=/; SameSite=None; Secure,jwt_token=TEST; Domain=.example.com; Max-Age=31536000; Path=/; expires=Wed, 26-Apr-2023 02:03:35 GMT; SameSite=lax; Secure,csrf_token=TEST; Domain=.example.com; Max-Age=31536000; Path=/; expires=Wed, 26-Apr-2023 02:03:35 GMT,csrf_token=TEST; Domain=.example.com; Max-Age=31536000; Path=/; expires=Wed, 26-Apr-2023 02:03:35 GMT,
는 원래 단독headers에서 설정한 set-cookie는 쉼표 구분자로 결합된 것이다.이런 형식은 쓸 수 없기 때문에 방법을 강구해서 바꿀 필요가 있다.

잠정적 해결 방법


문제의 쉼표 구분자로 바꾸는 Cookie은 일반적인 방법이 아니다.쉼표 구분자로 연결하면 쉼표로 나누면 되지 않겠느냐는 생각도 들겠지만set-cookie 각 필드에 쉼표가 있기 때문에 효과적인 수단이 아니다.
따라서 잠정적인 해결 방법으로서 현황은 다음과 같은 두 가지 선택이 있다.

  • 정규 표현식으로 분할
  • 내가 만든 라이브러리 사용
  • 둘 다 근본적인 해결책은 아니지만, 움직임이 확인된 잠정적 해결책으로 차례로 소개된다.

    솔루션 1: 정규 표현식으로 분할


    개발된 앱과 포장에 대한 의존성을 키우고 싶지 않은 사람에게는 정규적 표현으로 분할하는 것이 가장 적합한 수단이다.
    구체적으로 다음 설치에 문제가 있는 결합Cookie을 분리해서 사용할 수 있다.
    import 'dart:io';
    
    import 'package:http/http.dart' as http;
    
    /// 結合されたset-cookieを分割する正規表現
    final _regexSplitSetCookies = RegExp(',(?=[^ ])');
    
    void main() async {
      final response = await http.get(Uri.parse('https://example.com',));
    
      final List<Cookie> cookies = [];
    
      final setCookie = _getSetCookie(response.headers);
      if (setCookie.isNotEmpty) {
        for (final cookie in setCookie.split(_regexSplitSetCookies)) {
          cookies.add(Cookie.fromSetCookieValue(cookie));
        }
      }
    
      // 結合されたset-cookieが個別のset-cookieに分割されているのを確認できます。
      print(cookies);
    }
    
    String _getSetCookie(final Map<String, dynamic> headers) {
      for (final key in headers.keys) {
        // システムによって返却される "set-cookie" のケースはバラバラです。
        if (key.toLowerCase() == 'set-cookie') {
          return headers[key] as String;
        }
      }
    
      return '';
    }
    

    솔루션 2: 라이브러리 사용


    의존 라이브러리를 늘리는 것도 선택 항목 중 하나입니다. 제가 과거에 만든 라이브러리를 사용할 수 있습니다.
    https://pub.dev/packages/http
    프로그램 라이브러리에서 실행되는 처리는 이전에 소개한 정규 표현식의 분할 방법과 완전히 같다.
    예를 들어 다음과 같이 사용할 수 있다.
    import 'package:http/http.dart' as http;
    import 'package:sweet_cookie_jar/sweet_cookie_jar.dart';
    
    void main() async {
      final response = await http.get(Uri.parse('https://example.com'));
    
      // やることはResponseオブジェクトを渡すだけです。
      final cookieJar = SweetCookieJar.from(response: response);
    
      print(cookieJar.find(name: 'csrf_token'));
    }
    

    Dart Development 팀에 요청을 보냈습니다.


    이 문제를 해결하는 가장 좋은 방법은 set-cookie 프로그램 라이브러리 자체의 처리를 수정하여 이 어려움을 해결하는 것이다.
    지금까지 몇 가지 잠정적인 해결 방안을 열거했지만, 모든 사람의 실제 옷차림으로 창고의 좋지 않은 부분을 보완하는 것은 현명하지 못하다.오랫동안 사랑받아온 프로그램 라이브러리이기 때문에 개발자들이 쉽게 사용할 수 있는 기능을 제공해야 한다.
    그래서 제가 앞서 소개한 http의 일부 알고리즘을 SweetCookieJar 라이브러리에 이식하여 연기 요청을 보냈고 지금은 http와 협의하여 합병하고 있습니다.
    https://pub.dev/packages/sweet_cookie_jar

    공헌자 모집


    이 기사와 달리 저는 Dart開発チーム제 작업 스케줄링 프레임워크 Batch입니다.데이터를 개발 중입니다.
    Batch.dart는 개방원이기 때문에 누구든지 개발에 기여할 수 있습니다.창고를 개발하는 통용어는 영어이며 일본인들도 환영하니 마음대로 만들어주세요Dart言語Issue.
    또한Pull RequestIssue난이도가 높지만기여하고자하는사람은Pull Request의개발창고에스타를설치하거나설치GitHub하는좋은가격을 고려해보자.Batch입니다.dart의 개발 커뮤니티를 활성화시키는 데 큰 의미가 있습니다.
    https://github.com/dart-lang/http/pull/688
    https://github.com/batch-dart/batch.dart
    Batch.dart에 대해 과거에 다음과 같은 글을 쓴 적이 있으니 참고하세요.
    https://pub.dev/packages/batch

    스폰서 모집


    국내외를 막론하고 개방원 개발을 지원하는 스폰서를 모집하고 있다.소액 기부도 가능하니 아래 링크로 지원해주세요.
    https://zenn.dev/kato_shinya/articles/what-is-batch-dart
    또 이 기사에 배지를 선물해도 지원받을 수 있다.
    각주
    https://github.com/sponsors/myconsciousness Hypertext Transfer Protocol
    ↩︎ Pub.dev - http

    좋은 웹페이지 즐겨찾기