
Nfhttp: A cross platform C++ HTTP library natively interfacing to platforms - starbugs
https://github.com/spotify/NFHTTP
======
AndrewStephens
This is a great idea. A lot of people are going to say "why not use libcurl
like everyone else?". Curl is great but this project is a better idea for
client-side code.

libcurl is easy to integrate into C++ but hard to get right (this is not
curl's fault). I see a lot of bad example code around the web that works(tm)
but is not robust. I've seen so much bad curl code that I was moved to
write[0] about some of the problems.

libcurl doesn't use OS-level features. It doesn't pick up the users proxy
settings or use the cache or cookie store. This is sometimes what you want but
for standard client apps Nfhttp's approach is better.

[0]
[https://sheep.horse/2019/3/using_libcurl_effectively_and_saf...](https://sheep.horse/2019/3/using_libcurl_effectively_and_safely_in_c%2B%2B.html)

~~~
deeringc
I agree in general that using native HTTP stacks is a good idea for all sorts
of reasons, but it's worth calling out that NFHTTP is actually using CURL
under the hood on Linux & Android platforms so this just ultimately wraps the
CURL C API in a C++ API. On OSX it is using NSURL which is great, and on
Windows it's using Microsoft's cpprestsdk library in order to talk with
WinHTTP and UWP.

~~~
rhodysurf
Honestly the biggest gain by using the platform API is that you get SSL
support for free. Otherwise you have to cross compile OpenSSL for every
android target you want to support and for a fat universal lib for iOS. Its a
giant pain.

~~~
benibela
That was the reason I used the platform APIs in one app, and it is an awful
mess.

Then people use Android 4.0 or Windows 2000/XP, and complain they cannot use
TLS1.2. And you cannot use the platform defaults, or Android 4.x fails with
TLS1.2, because it is not enabled in the defaults, despite being supported. So
you enable TLS1.2 and all ciphers, and then Android 8 fails on TLS1.3 due to a
trapdoor cipher. Every device trusts different CAs, so you cannot know if
https will work, unless you include all the needed certs rather than using the
platform certs. Or the platform API is just completely removed like Apache
HttpComponents from Android, and you need to rewrite it.

------
Klonoar
I've been pointing out to people for some time now that Apple has docs
(buried, of course, because it's Apple...) that outright indicate they do
things behind the scenes with NSURLSession & co to make battery/radio
management better. The effect of people dodging it in cross-platform
frameworks has been something I've long wondered about.

~~~
saagarjha
This library seems to use platform APIs under the hood, so it might end up
performing similarly.

~~~
deeringc
It uses CURL on Android.

~~~
pjmlp
There are no platform APIs for networking exposed on the NDK, beyond plain old
POSIX sockets.

The alternative would be some JNI boilerplate to access Android Framework
networking APIs.

------
bsenftner
First time I've seen JSON for Modern C++
[https://nlohmann.github.io/json/](https://nlohmann.github.io/json/) Anyone
have an use likes/dislikes?

~~~
deeringc
Probably one of the best C++ libraries out there. Can't recommend this highly
enough.

------
profquail
How does this compare to cpprestsdk?

[https://github.com/Microsoft/cpprestsdk](https://github.com/Microsoft/cpprestsdk)

~~~
deeringc
This interested me too so I looked through the source to find out. NFHTTP
seems to add 2 clients of its own, one that uses NSURL (for Apple) and another
that uses CURL (for Linux). Everything else (WinHTTP, UWP, and the fallback
Boost Asio client) simply call down and use the cpprestsdk implementations
directly.

Seems like this library offers less itself than it says on the tin, given that
3/5 of its native impls just call down to cpprestsdk. It's a pity that spotify
didn't simply add CURL and NSURL clients to cppressdk - that would have been
far more useful IMO.

------
bsenftner
FWIW, I use Restbed for this type of work.
[https://github.com/Corvusoft/restbed](https://github.com/Corvusoft/restbed)

------
benibela
I made such a library for FreePascal
([http://benibela.de/sources_en.html#internettools](http://benibela.de/sources_en.html#internettools))

Windows WinINet, Android JNI for Apache HttpComponents or OkHttp, Linux
OpenSSL through another FreePascal library

------
rapsey
It mentions UWP support in readme, but that is wrong. WinHTTP C++ APIs are not
present in UWP apps.

~~~
deeringc
This library seems to add a HTTP client impl built on top of NSURL, and
another on top of CURL. It looks to me like everything else here is provided
by Microsoft's CPPRestSDK - WinHTTP, UWP & Boost Asio based clients simply use
the CppRestSDK impls under the hood.

~~~
rapsey
It says winhttp is used on windows...

~~~
deeringc
Edit: Sorry, I misread your post. To add, cpprestsdk has 2 impls for Windows -
one based on top of WinHTTP and the other based on WinRT APIs. On UWP,
cpprestsdk uses the WinRT APIs and by extension so does NFHTTP.

------
adgasf
This code is a great example of how awkward it is to glue CMake projects
together.

~~~
mises
What would you suggest instead? This is honest, not sarcastic. Cmake can be
very powerful, and I don't know of a better option. For instance, it can even
be set up to download the latest binary dependencies, which is very useful.

~~~
adgasf
Downloading the latest binary dependencies is (IMO) not a good idea. You
should download a known working version with a fixed hash. This will avoid
unexpected version mismatches in production. When you want to upgrade, make it
explicit.

As for a better alternative, I would suggest Bazel or Buck.

~~~
mises
I meant the latest I have pushed to a specific server I run. This means I can
push up and everyone working on the project can fetch them easily. It requires
intervention, and I wouldn't push until I've tested thoroughly and made
necessary changes.

I appreciate the recommendation, though it seems that bazel is heavily focused
on java.

~~~
adgasf
That approach has a scaling problem because it requires the central server not
to forget to verify the new version against all of the users. Instead, I think
that upgrades should be decided on the user side. That is where the tests etc.
live.

Bazel is a multi-language system whose focus is actually on C++. This is
because other languages have much simpler compilation models.

I don't see why it would be a downside to have additional language support in
your C++ build-system. For example, what happens when you want to do Android?

~~~
mises
Upgrades are basically decided by the user by updating their cmake config. It
can check a specific page on the server and compare with a page in the repo to
see if an update is necessary. The central server doesn't have to do anything,
it's just dumb file hosting.

I've got nothing against additional language support, though having to install
java to use it is a bit painful. I'll take a look at it; I appreciate the
recommendation.

You originally commented that cmake was awkward and required "gluing
together". I'll agree that the syntax is a little alien to those of us with a
background in c-like syntax, but it's never seemed that clunky. Any reason
why?

~~~
adgasf
> Upgrades are basically decided by the user by updating their cmake config.

So why not hash the remote file to ensure integrity, and make the server an
immutable store?

> I've got nothing against additional language support, though having to
> install java to use it is a bit painful. I'll take a look at it; I
> appreciate the recommendation.

I would prefer if they did not use Java also. However, you do not need to
install a JVM to use Bazel since it ships with one internally. To the end
user, Java is just an implementation detail.

> I'll agree that the syntax is a little alien to those of us with a
> background in c-like syntax, but it's never seemed that clunky.

This was all I was trying to say really :)

Looking at the repo, I think it would be considerable tweaking to take a
dependency on Nfhttp when you already depend on some of its dependencies. With
Bazel (and similar) you have a clear way to glue things together
("workspaces") so you would just ensure that all dependencies take the same
workspace.

CMake ergonomics is death by a 1000 cuts. The syntax is unpleasant and the
error messages are very poor.

------
anon4242
Hehe, seeing this I thought "Cool, this is exactly how Spotify handles
separation between the GUI frontend and the backend in the Spotify app" and
then I saw the organization name in the URL.. doh!

------
happyweasel
How does this lib handle proxy settings? Does it provide an API to the current
proxy settings on the supported platforms ? And an ability to use or not use
the proxy per request?

------
geezerjay
How does Nfhttp compare with POCO?

[https://pocoproject.org/](https://pocoproject.org/)

