GithubHelp home page GithubHelp logo

isabella232 / nfhttp Goto Github PK

View Code? Open in Web Editor NEW

This project forked from nativeformat/nfhttp

0.0 0.0 0.0 2.08 MB

A cross platform C++ HTTP library that interfaces natively to other platforms.

License: Apache License 2.0

CMake 0.87% Python 0.68% Shell 0.06% PowerShell 0.01% C++ 1.69% C 96.55% Objective-C++ 0.13%

nfhttp's Introduction

NFHTTP

CircleCI License Spotify FOSS Slack Readme Score

A cross platform C++ HTTP framework.

Raison D'Γͺtre πŸ’­

At Spotify we have performed studies that show the efficacy of using native backed solutions for interfacing to backends, especially when it came to the battery life of certain devices. In order to carry this forward in the cross-platform C++ world, we created this library that provides a common interface to many of the system level HTTP interfaces, and predictable caching and request hooking. We found that many of the current solutions that claimed to do this lacked key supports for many kinds of platforms, and ended up being libraries that heavily favoured 1 platform and gave the other platforms a generic implementation. We also wanted to provide a caching layer that was consistent across all platforms in our layered architecture.

Architecture πŸ“

NFHTTP is designed as a common C++ interface to communicate with different systems over HTTP! The API allows you to create objects to make Requests and read Responses. To initiate, send and receive messages you create and use a Client object. This is a layered architecture where requests and responses can pass through multiple places in the stack and get decorated or have actions taken upon them.

The layer design is as follows:

  • The Modification layer, which takes requests and responses, performs any modifications on them that might be required by the functions provided to the factory, and forwards them on.
  • The Multi-Request Layer, which takes a request, determines if the same request is currently being executed, then ties the response to that request with the response currently coming in from the previously sent request.
  • The Caching Layer, which takes a request, determines whether it is cached and if so sends a response immediately, if not forwards the request, and when it receives the response stores the response in its cache.
  • The Native Layer, which takes a request and converts it to a system level call depending on the system the user is using, then converts the response back to an NFHTTP response and sends the response back up the chain.

Our support table looks like so:

OS Underlying Framework Status
iOS NSURLSession Stable
OSX NSURLSession Stable
Linux curl Stable
Android curl Beta
Windows WinHTTP Alpha

In addition to this, it is also possible to use curl on any of the above platforms or boost ASIO (provided by CPP REST SDK).

Dependencies 🌐

Installation πŸ“₯

NFHTTP is a Cmake project, while you are free to download the prebuilt static libraries it is recommended to use Cmake to install this project into your wider project. In order to add this into a wider Cmake project (who needs monorepos anyway?), simply add the following lines to your CMakeLists.txt file:

add_subdirectory(NFHTTP)

# Link NFHTTP to your executables or target libs
target_link_libraries(your_target_lib_or_executable NFHTTP)

For iOS/OSX

Generate an Xcode project from the Cmake project like so:

$ git submodule update --init --recursive
$ mkdir build
$ cd build
$ cmake .. -GXcode

For linux

Generate a Ninja project from the Cmake project like so:

$ git submodule update --init --recursive
$ mkdir build
$ cd build
$ cmake .. -GNinja

For Android

Use gradle

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.spotify.nfhttptest_android"
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        externalNativeBuild {
            cmake {
                cppFlags ""
                arguments "-DANDROID_APP=1 -DANDROID=1"
            }
        }
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/cpp']
        }
    }

    externalNativeBuild {
        cmake {
            path "../CMakeLists.txt"
        }
    }
}

For Windows

Generate a Visual Studio project from the Cmake project like so:

$ mkdir build
$ cd build
$ cmake .. -G "Visual Studio 12 2013 Win64"

Usage example πŸ‘€

In order to execute HTTP requests, you must first create a client like so:

auto client = nativeformat::http::createClient(nativeformat::http::standardCacheLocation(),
                                               "NFHTTP-" + nativeformat::http::version());

It is wise to only create one client per application instance, in reality you will only need one (unless you need to separate the caching mechanism for your own reasons). After you have done this you can proceed to creating request objects like so:

const std::string url = "http://localhost:6582/world";
auto request = nativeformat::http::createRequest(url, std::unordered_map<std::string, std::string>());

This will create a GET request with no added headers to send to the localhost:682/world location. This does not mean other headers will not be added, we have multiple layers that will add caching requirement headers, language headers, content size headers and the native layer can also add headers as it sees fit. After we have created our request we can then execute it:

auto token = client->performRequest(request, [](const std::shared_ptr<nativeformat::http::Response> &response) {
    printf("Received Response: %s\n", response->data());
});

The callback will be called asynchronously in whatever thread the native libraries post the response on, so watch out for thread safety within this callback. In order to execute requests synchronously on whatever thread you happen to be on, you can perform the follow actions:

auto response = client->performSynchronousRequest(request);
printf("Received Response: %s\n", response->data());

You might wonder how you can hook requests and responses, this can be done when creating the client, for example:

auto client = nativeformat::http::createClient(nativeformat::http::standardCacheLocation(),
                                               "NFHTTP-" + nativeformat::http::version(),
                                               [](std::function<void(const std::shared_ptr<nativeformat::http::Request> &request)> callback,
                                                  const std::shared_ptr<nativeformat::http::Request> &request) {
                                                 printf("Request URL: %s\n", request->url().c_str());
                                                 callback(request);
                                               },
                                               [](std::function<void(const std::shared_ptr<nativeformat::http::Response> &response, bool retry)> callback,
                                                  const std::shared_ptr<nativeformat::http::Response> &response) {
                                                 printf("Response URL: %s\n", response->request()->url().c_str());
                                                 callback(response, false);
                                               });

Here we have hooked the client up to receive requests and responses via the hook functions. Because we are now part of the layered architecture, we can perform any changes we want on the requests or responses, such as decorating with OAuth tokens, redirecting to other URLs, retrying responses or even cancelling responses altogether. If you are interested in the concept of cache pinning, it can be done like so:

client->pinResponse(response, "my-offlined-entity-token");

This will then ensure that the response is in the cache until it is explicitly removed, and ignore all backend caching directives.

Contributing πŸ“¬

Contributions are welcomed, have a look at the CONTRIBUTING.md document for more information.

License πŸ“

The project is available under the Apache 2.0 license.

Acknowledgements

  • Icon in readme banner is β€œDownload” by romzicon from the Noun Project.

Contributors

nfhttp's People

Contributors

8w9ag avatar astrocox avatar drubinstein avatar gazzyt avatar kebbbnnn avatar kirbysayshi 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.