Coder Social home page Coder Social logo

fshttp's Introduction

FsHttp

FsHttp is a convenient library for consuming HTTP/REST endpoints via F#. It is based on System.Net.Http.

NuGet Badge Build Status

The goal of FsHttp is to provide ways for describing HTTP requests in a convenient way, and it is inspired by the RestClient VSCode extension. It can be used in production code, in tests, and in F# interactive.

Parts of the code is taken from the HTTP utilities of FSharp.Data.

FsHttp comes in 2 'flavours' that can be used to describe HTTP requests. Although it is a good thing to have 1 solution for a problem instead of 2, it's up to you which style you prefer.

Sources and Demos

Have a look at these files for more use cases:

Setup (including FSI)

// Inside F# Interactive, load the FsHttp script instead of referencing the dll.
// This will register pretty output printers for HTTP requests and responses.
#load @"../FsHttp/bin/Debug/netstandard2.0/FsHttp.fsx"

open FsHttp

// Choose your style (here: Computation Expression)
open FsHttp.DslCE

Getting Started: Build up a GET request

Hint: The request will be sent immediately and synchronous.

http {
    GET "https://reqres.in/api/users"
}

add a header...

http {
    GET "https://reqres.in/api/users"
    CacheControl "no-cache"
}

Here is an example of a POST with JSON as body:

http {
    POST "https://reqres.in/api/users"
    CacheControl "no-cache"
    body
    json """
    {
        "name": "morpheus",
        "job": "leader"
    }
    """
}

FSI Request/Response Formatting

When you work in FSI, you can control the output formatting with special keywords.

Some predefined printers are defined in ./src/FsHttp/DslCE.fs, module Fsi

2 most common printers are:

  • 'go' (alias: 'preview'): This will render a small part of the response content.
  • 'exp' (alias: 'expand'): This will render the whole response content.
http {
    GET "https://reqres.in/api/users"
    CacheControl "no-cache"
    exp
}

Verb-First Requests (Syntax)

Alternatively, you can write the verb first. Note that computation expressions must not be empty, so you have to write at lease something, like 'id', 'go', 'exp', etc.

Have a look at: ./src/FsHttp/DslCE.fs, module Shortcuts

get "https://reqres.in/api/users" { exp }

Inside the { }, you can place headers as usual...

get "https://reqres.in/api/users" {
    CacheControl "no-cache"
    exp
}

URL Formatting (Line Breaks and Comments)

You can split URL query parameters or comment lines out by using F# line-comment syntax. Line breaks and trailing or leading spaces will be removed:

get "https://reqres.in/api/users
            ?page=2
            //&skip=5
            &delay=3"
            { go }

Response Content Transformations

There are several ways transforming the content of the returned response to something like text or JSON:

See also: ./src/FsHttp/ResponseHandling.fs

http {
    POST "https://reqres.in/api/users"
    CacheControl "no-cache"
    body
    json """
    {
        "name": "morpheus",
        "job": "leader"
    }
    """
}
|> toJson

Works of course also like this:

post "https://reqres.in/api/users" {
    CacheControl "no-cache"
    body
    json """
    {
        "name": "morpheus",
        "job": "leader"
    }
    """
}
|> toJson

Use FSharp.Data.JsonExtensions to do JSON stuff:

open FSharp.Data
open FSharp.Data.JsonExtensions

http {
    GET @"https://reqres.in/api/users?page=2&delay=3"
}
|> toJson
|> fun json -> json?page.AsInteger()

Configuration: Timeouts, etc.

You can specify a timeout:

// should throw because it's very short
http {
    GET "http://www.google.de"
    timeoutInSeconds 0.1
}

You can also set config values globally (inherited when requests are created):

FsHttp.Config.setTimeout (System.TimeSpan.FromSeconds 15.0)

Access HttpClient and HttpMessage

Transform underlying http client and do whatever you feel you gave to do:

http {
    GET @"https://reqres.in/api/users?page=2&delay=3"
    transformHttpClient (fun httpClient ->
        // this will cause a timeout exception
        httpClient.Timeout <- System.TimeSpan.FromMilliseconds 1.0
        httpClient)
}

Transform underlying http request message:

http {
    GET @"https://reqres.in/api/users?page=2&delay=3"
    transformHttpRequestMessage (fun msg ->
        printfn "HTTP message: %A" msg
        msg)
}

Lazy Evaluation / Chaining Builders

Hint: Have a look at: ./src/FsHttp/DslCE.fs, module Fsi'

There is not only the immediate + synchronous way of specifying requests. It's also possible to simply build a request, pass it around and send it later or to warp it in async.

Chaining builders together: First, use a httpLazy to create a 'HeaderContext'

Hint: httpLazy { ... } is just a shortcut for httpRequest StartingContext { ... }

let postOnly =
    httpLazy {
        POST "https://reqres.in/api/users"
    }

Add some HTTP headers to the context:

let postWithCacheControlBut =
    httpRequest postOnly {
        CacheControl "no-cache"
    }

Transform the HeaderContext to a BodyContext and add JSON content:

let finalPostWithBody =
    httpRequest postWithCacheControlBut {
        body
        json """
        {
            "name": "morpheus",
            "job": "leader"
        }
        """
    }

Finally, send the request (sync or async):

let finalPostResponse = finalPostWithBody |> send
let finalPostResponseAsync = finalPostWithBody |> sendAsync

Async Builder

HTTP in an async context:

let pageAsync =
    async {
        let! response = 
            httpAsync {
                GET "https://reqres.in/api/users?page=2&delay=3"
            }
        let page =
            response
            |> toJson
            |> fun json -> json?page.AsInteger()
        return page
    }

fshttp's People

Contributors

maxdeg avatar vilinski avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.