All Projects → ronaldschlenker → Fshttp

ronaldschlenker / Fshttp

Licence: apache-2.0
A lightweight F# HTTP library.

Programming Languages

fsharp
127 projects

Projects that are alternatives of or similar to Fshttp

Requester
Powerful, modern HTTP/REST client built on top of the Requests library
Stars: ✭ 273 (+50.83%)
Mutual labels:  rest, rest-client, http-client
Restclient Cpp
C++ client for making HTTP/REST requests
Stars: ✭ 1,206 (+566.3%)
Mutual labels:  rest, rest-client, http-client
Fluentlyhttpclient
Http Client for .NET Standard with fluent APIs which are intuitive, easy to use and also highly extensible.
Stars: ✭ 73 (-59.67%)
Mutual labels:  rest, rest-client, http-client
Restc Cpp
Modern C++ REST Client library
Stars: ✭ 371 (+104.97%)
Mutual labels:  rest, rest-client, http-client
Vscode Restclient
REST Client Extension for Visual Studio Code
Stars: ✭ 3,289 (+1717.13%)
Mutual labels:  rest, rest-client, http-client
Restclient
🦄 Simple HTTP and REST client for Unity based on Promises, also supports Callbacks! 🎮
Stars: ✭ 675 (+272.93%)
Mutual labels:  rest, rest-client, http-client
Crest
HTTP and REST client for Crystal
Stars: ✭ 174 (-3.87%)
Mutual labels:  rest-client, http-client
Github3.py
Hi, I'm a library for interacting with GItHub's REST API in a convenient and ergonomic way. I work on Python 3.6+.
Stars: ✭ 1,029 (+468.51%)
Mutual labels:  rest, rest-client
Openapi Generator
OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
Stars: ✭ 10,634 (+5775.14%)
Mutual labels:  rest, rest-client
Hoodie
Hoodie is a type safe wrapper around jersey http client
Stars: ✭ 22 (-87.85%)
Mutual labels:  rest-client, http-client
Flogo Contrib
Flogo Contribution repo. Contains activities, triggers, models and actions.
Stars: ✭ 60 (-66.85%)
Mutual labels:  rest, http-client
Rest Client
A tool for automated testing REST API, generating exquisite testing report and REST API documentation.
Stars: ✭ 1,181 (+552.49%)
Mutual labels:  rest-client, http-client
Restful.js
A pure JS client for interacting with server-side RESTful resources. Think Restangular without Angular.
Stars: ✭ 977 (+439.78%)
Mutual labels:  rest, http-client
Apipie
Transform api declaration to js object for frontend. Inspired by VueRouter, koa-middleware and axios.
Stars: ✭ 29 (-83.98%)
Mutual labels:  rest, rest-client
Json Api Dart
JSON:API client for Dart/Flutter
Stars: ✭ 53 (-70.72%)
Mutual labels:  rest, http-client
Yet Another Rest Client
YARC (Yet Another REST Client) is an easy-to-use REST Client for Google Chrome.
Stars: ✭ 23 (-87.29%)
Mutual labels:  rest, rest-client
Frequest
FRequest - A fast, lightweight and opensource desktop application to make HTTP(s) requests
Stars: ✭ 130 (-28.18%)
Mutual labels:  rest-client, http-client
Snug
Write reusable web API interactions
Stars: ✭ 108 (-40.33%)
Mutual labels:  rest, http-client
Python Simple Rest Client
Simple REST client for python 3.6+
Stars: ✭ 143 (-20.99%)
Mutual labels:  rest-client, http-client
Vue Chimera
VueJS reactive RESTful API
Stars: ✭ 160 (-11.6%)
Mutual labels:  rest, rest-client

FsHttp

TODO: Document % operator

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.

Building

You need to have dotnet SDK 3.1.202 installed (as specified in global.json).

Sources and Demos

Have a look at these files for more use cases:

Setup (including FSI)

#r @"../FsHttp/bin/Debug/netstandard2.0/FsHttp.dll"

open FsHttp

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

Getting Started: Build up a GET request

Hint: The request built in this way 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:

  • 'prv' (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" { send }

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" {
    send }

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"
    }
    """
}
|> Response.toJson

Works of course also like this:

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

Use FSharp.Data.JsonExtensions to do JSON processing:

open FSharp.Data
open FSharp.Data.JsonExtensions

http {
    GET @"https://reqres.in/api/users?page=2&delay=3"
}
|> Response.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.setDefaultConfig (fun config ->
    { config with timeout = 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 =
    postOnly {
        CacheControl "no-cache"
    }

Transform the HeaderContext to a BodyContext and add JSON content:

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

Finally, send the request (sync or async):

let finalPostResponse = finalPostWithBody |> Request.send
let finalPostResponseAsync = finalPostWithBody |> Request.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
            |> Response.toJson
            |> fun json -> json?page.AsInteger()
        return page
    }


// TODO Document naming conventions according to: https://github.com/ronaldschlenker/FsHttp/issues/48

Naming Conventions

Names for naming conventions according to: https://en.wikipedia.org/wiki/Naming_convention_(programming)#Lisp

  • Naming of HTTP methods inside of a builder are upper flat case (following https://tools.ietf.org/html/rfc7231#section-4).

    Example:

    http {
        GET "http://www.whatever.com"
    }
    
  • Naming of HTTP methods used outside of a builder follow the F# naming convention and are flat case.

    Example:

    let request = get "http://www.whatever.com"
    
  • Naming of HTTP headers inside of a builder are PascalCase. Even though they should be named train case (according to https://tools.ietf.org/html/rfc7231#section-5), it would require a double backtic using it in F#, which might be uncomfortable.

    Example:

    http {
        // ...
        CacheControl "no-cache"
    }
    
  • Naming of all other constructs are lower camel case. This applies to:

    • config methods
    • type transformer (like "body")
    • content annotations (like "json" or "text")
    • FSI print modifiers like "expand" or "preview"
    • invocations like "send"

    Example:

    http {
        // ...
        timeoutInSeconds 10.0
        body
        json """ { ... } """
        expand
    }
    

Examples for building, chaining and sending requests

let getUsers1 : LazyHttpBuilder<HeaderContext> = get "https://reqres.in/api/users"
let getUsers2 : LazyHttpBuilder<HeaderContext> = httpLazy { GET "https://reqres.in/api/users" }
let _ : Response = getUsers1 { send }
let _ : Response = get "https://reqres.in/api/users" { send }
let _ : Response = getUsers1 |> Request.send
let _ : Response = http { GET "https://reqres.in/api/users" }
let _ : Async<Response> = httpAsync { GET "https://reqres.in/api/users" }
let _ : Response =
    httpLazy {
        GET "https://reqres.in/api/users"
        send
    }
let _ : Async<Response> =
    httpLazy {
        GET "https://reqres.in/api/users"
        sendAsync
    }

// FSI
let _ : Response =
    http {
        GET "https://reqres.in/api/users"
        CacheControl "no-cache"
        exp
    }

let _ : Response =
    get "https://reqres.in/api/users" {
        CacheControl "no-cache"
        exp
        send
    }
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].