将Set-Cookie字符串转换为以F#方式记录?

时间:2014-01-17 22:59:54

标签: cookies 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 }

1 个答案:

答案 0 :(得分:1)

首先,我会使用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...
    }