Получил промежуточное значение в последнем связанном Option.bind? - PullRequest
0 голосов
/ 30 мая 2018

У меня есть следующий код

let getHtml location = 
    let request (url:string) = 
        let response = httpRequest (getFullUri url)
        response.Headers.TryFind "Location"

    request location  
    |> Option.bind (fun x -> request x) 
    |> Option.bind (fun x -> request x) // need the return of httpRequest inside request

Я хочу, чтобы код возвратил последний вызов httpRequest.Не возвращение request.


Обновление: пробовал следующий код.Ошибка на последнем snd.Я думаю, что я могу использовать изменяемую переменную для ее реализации.Но это идиоматический F #?

let getHtml location = 
    let request (url:string) = 
        let response = httpRequest (getFullUri url)
        match response.Headers.TryFind "Location" with 
        | Some location -> Some location, response
        | None -> None, response

    request location |> fst
    |> Option.bind (fun x -> request x |> fst) 
    |> Option.bind (fun x -> request x |> snd) // Error on snd

Использовать изменяемую переменную?

let getHtml location = 
    let mutable resp : FSharp.Data.HttpResponse = ???
    let request (url:string) = 
        let response = httpRequest (getFullUri url)
        resp <- response
        response.Headers.TryFind "Location"

    request location 
    |> Option.bind (fun x -> request x) 
    |> Option.bind (fun x -> request x)

    if not (resp = null) then Some resp else None

1 Ответ

0 голосов
/ 30 мая 2018

Я думаю, что вы хотите, чтобы на самом деле сделать getHtml рекурсивным, чтобы, когда HTTP-запрос возвращал код ответа 201 или 300-уровня, вы следовали за заголовком Location на перенаправленной странице и возвращали правильныйHTML.Вы можете сделать это с помощью простого сопоставления с шаблоном в response.StatusCode и заголовке местоположения, как показано ниже:

open FSharp.Data

// stub
let getFullUri (url: string) = 
    sprintf "%A" <| System.UriBuilder(url)

// stub
let httpRequest = Http.Request

// fetches the requested URL, following redirects as necessary
let rec getHtml location = 
    let response = httpRequest (getFullUri location)
    match response.StatusCode, response.Headers |> Map.tryFind "Location" with
    | (status, Some redirectUrl) when status = 201 || (status >= 300 && status < 400) -> 
        getHtml redirectUrl
    | _ -> 
        response

Это то, что вы хотели?Я протестировал его со следующим URL-адресом, который возвращает 302, и он получил HTML-код для страницы, на которую он был перенаправлен: https://jigsaw.w3.org/HTTP/300/302.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...