将设置饼干字符串转换为以 F# 方式记录



我有以下Cookie记录。

type Cookie = {
    NameValue : string * string;
    Domain : string option;
    Path : string option;
    Expires : string option;
    MaxAge : string;
    Secure : bool; // ? no associated value, anything better than bool
    HttpOnly : bool; // ? no associated value, anything better than bool
    }

我需要将set-cookie字符串转换为CookieAttricute list.

let GetCookie str =
    let (|ParseRegex|_|) regex str =
       let m = Regex(regex, RegexOptions.IgnoreCase).Match(str)
       if m.Success
       then Some (List.tail [ for x in m.Groups -> x.Value ])
       else None
    match str with
    | ParseRegex @"(.+?)(?:=(.+?))?(?:;|$|,(?!s))" [name; value] -> 
        .... // How to construct a Cookie here?
    | _ -> None

例如,给定以下字符串。

"ObSSOCookie=93KRPo;secure; httponly; path=/; domain=.xyz.com"

该函数应返回

{ NameValue = ("ObSSOCookie", "93KRPo"); 
  Secure = true; 
  HttpOnly = true; 
  Path = Some("/"); 
  Domain = Some(".xyz.com");
  MaxAge = None;
  Expires = None }

首先,我会使用 String.Split 而不是用正则表达式使其过于复杂。然后,我将为属性构建一个Map<string, string>。像这样:

let GetCookie (str: string) =
    let allkeyvalues =
        str.Split ';'
        |> Array.map (fun str ->
            match str.Split '=' with
            | [| key |] -> (key, "")
            | [| key; value |] -> (key, value)
            | _ -> (* there's more than one '='; the format is incorrect. *))
    let namevalue = allkeyvalues.[0]
    let attributes =
        Seq.skip 1 allkeyvalues
        |> Seq.map (fun (key, value) ->
            (key.ToLower(), value)) // attribute names are case-insensitive
        |> Map.ofSeq
    {
        NameValue = namevalue
        Secure = Map.containsKey "secure" attributes
        Path = Map.tryFind "path" attributes
        // etc...
    }

最新更新