fnc12 / embeddedRest

A little library for making url requests in C++
MIT License
43 stars 6 forks source link

HTTPS, FTP and HTTP support #4

Closed DonaldTrump88 closed 7 years ago

DonaldTrump88 commented 7 years ago

Thanks for providing this library. I am looking for a library which can communicate with server using HTTPS, FTP and HTTP protocols on iOS and Android by REST calls. Currently cURL(https://ec.haxx.se/protocols.html) is promising candidate but it is kind of overweight.

I am not sure about protocols used by this library. It will be great if you provide more information(like current support and possibility of adding them) about following questions.

  1. Protocols
  2. Authentication
  3. SSL support. LibreSSL or OpenSSL etc.
  4. Possible problems to submit the app to app stores.

There is another low level library. I am not sure if you saw it before.

fnc12 commented 7 years ago

I had already tried to use this lib for iOS and Android. Everything works fine on android but App Store rejects the app cause the lib doesn't support IPv6. The lib supports HTTP (not HTTPS) and has json interface for request body. Also I was trying to port curl to iOS and Android - this is a lot of pain. Also you can use boots::asio for url requests. I use C++ bindings for both iOS and Android. They are located here. This is a template project with C++ crossplatform framework 'Mitsoko'. Its core is located in a separate subrepo. You can make a rest request right in any presenter by including Mitsoko/Url/Request.hpp and writing a code:

using namespace Mitsoko::Url;
Request request;
request.method("POST");
request.body(json{
    { "name", "Sly Boogy" },
    { "age", 25 },
}.dump());
request.headers["Content-Type"] = "application/json";
request.performAsync([this](Response response, std::vector<char> data, Error error){
    if(response){
        if(response.statusCode() == 200){
            std::string dataString( data.begin(), data.end() );
            cout << "dataString = " << dataString << endl;
        }else{
            cout << "status code = " << response.statusCode() << endl;
        }
    }else{
        if(error){
            cout << "error = " << error.code() << " " << error.message() << endl;
        }else{
            cout << "undefined error" << endl;
        }
    }
});

Note: json is used from here

DonaldTrump88 commented 7 years ago

Thanks for the response. What is solution to make app accpeted in Apple app store? Yes, cURL is catch-all libraries. If possible, please go through lib links which I added. There is Beast(asio + C++) lib on github.

fnc12 commented 7 years ago

The solution is simple: add IPv6 implementation. Or replace it with curl. You can find static curl both for x32 and x64 architectures for iOS. I don't see the reason to add IPv6 or SSL/TLS implementation here. More simple is to drop the lib and use either bindings or curl/asio

DonaldTrump88 commented 7 years ago

Thanks for the reply. I still thinking between asio and curl. Asio is good for future because native c++ as compared to curl. But the library is pretty low level. Another problem with asio is most of its wrappers bring another boost libraries which I do not like.

The JNI binding is already done.

In future, I should use user authentication to fetch data from server. Then I need HTTPS.

fnc12 commented 7 years ago

Try Mitsoko project - this is a whole project with c++ bindings and java/objc helper classes for http(s) requests

DonaldTrump88 commented 7 years ago

Thanks. It is too late for it in current project. I shall try it in next project.

DonaldTrump88 commented 7 years ago

Which networking library do you recommend for Mobile apps(Android and iOS)? I am looking at cURL and standalone asio. It will be great if recommend something.

fnc12 commented 7 years ago

I recommend using c++ binding just like I use. Also I've used curl once. But it's not comfortable - I couldn't include it as sources. I added it as static lib both to iOS and Android. There was a lot of work: you have to add x32 and x64 static binaries to Xcode project and include headers for both architectures and switch them using #if. The can be located here. I don't remember exactly how I included curl to my android studio project but also must exist in different binaries for different architectures. Static libraries are hell cause there are about 7 active architectures for android and 2 for iOS. So I recommend using something architecture independent.

DonaldTrump88 commented 7 years ago

Thanks for advice. I am thinking to include curl or asio code in the project. It will be get compilied native library code, so it will reduce architecture problems.

The binding program find little complicated and late to use now. Do it have IPv6 problem also?

Unfortunately I do not have Mac computer now to verify correct library on both platforms.

fnc12 commented 7 years ago

Bindings don't have IPv6 problem cause bindings use native classes: NSUrlConnection for iOS and HttpURLConnection for Android

DonaldTrump88 commented 7 years ago

hmm. I have native sychronous C++ library for all non UI(database and webserver) code. App calls lib and lib does not call app. How can I fit this Mitsoko and this libbrary. Are you calling app from Mitsoko binding?

DonaldTrump88 commented 7 years ago

Did you try to abstract iOS and Android classes in C++ classes and try to program in C++?

fnc12 commented 7 years ago

Yes I call app code (objc/swift and java) from mitsoko bindings. Mitsoko have modules in core. Every module has view and presenter. View has const void *handle member which stores a pointer to view controller/activity. You can find it here. java::lang::Object(handle) creates java object with JNI functions. sendMessage function calls java function within this object. You must specify a return type and function name. java::lang::Object(handle).sendMessage<void>("showProgress"); calls void showProgress() function in my activity. To do the same thing on iOS just write NS::Object(handle).sendMessage<void>("showProgress"); and it will call - (void)showProgress; function within your controller.

fnc12 commented 7 years ago

Yes I have abstract classes for HTTP requests, table/list views, routing and other stuff right in mitsoko. Check it out in mitsoko-template. This is a program with two pages (activities/view controllers). First page has a button. On touch it requests countries from server in JSON format, parses it and opens a new page with tableView/listView that shows that countries.

DonaldTrump88 commented 7 years ago

Interesting concept.

DonaldTrump88 commented 7 years ago

How do you deal with HTTPS? As far as I know, iOS app must use HTTPS.

fnc12 commented 7 years ago

No. iOS app can use HTTP without SSL. HTTPS works fine with bindings cause native classes deal with SSL.

DonaldTrump88 commented 7 years ago

https://techcrunch.com/2016/06/14/apple-will-require-https-connections-for-ios-apps-by-the-end-of-2016/ https://9to5mac.com/2016/06/15/ats-https-ios-apps/

fnc12 commented 7 years ago

IDK. My several apps still work fine with HTTP

DonaldTrump88 commented 7 years ago

You are lucky. May be they do not know.

fnc12 commented 7 years ago

This is weird. One can even use custom binary protocol over TCP but how can HTTP be disallowed?

DonaldTrump88 commented 7 years ago

Basically they want to force everyone to use TLS to encrypt data.

DonaldTrump88 commented 7 years ago

https://stackoverflow.com/questions/38584413/openssl-existing-library-in-android

If you’re using the Android NDK in your app, don't link against cryptographic libraries that are not a part of the NDK API, such as libcrypto.so and libssl.so. These libraries are not public APIs, and may change or break without notice across releases and devices. In addition, you may expose yourself to security vulnerabilities. Instead, modify your native code to call the Java cryptography APIs via JNI or to statically link against a cryptography library of your choice.

fnc12 commented 7 years ago

That exactly what I do - bindings call java functions from c++. And I've never linked any app against librypto or libssl. Thanks

DonaldTrump88 commented 7 years ago

Yes, you are right. Do you have any plans to use TLS?

fnc12 commented 7 years ago

Didn't think about it. This is not a problem cause I use bindings and with bindings I can enable ssl just replacing 'http' to 'https' in urls. That's all

DonaldTrump88 commented 7 years ago

Yes, you are correct. This reason to use the binding project. But I need only subset of it, only networking without UI part. I need to find way to do it.

DonaldTrump88 commented 7 years ago

Is JVM in Mitsoko and mobile same? Can JVM from Mitsoko safely destroyed without affecting app?

fnc12 commented 7 years ago

JVM interface in mitsoko was built especially for dalvik using JNI API reference. It works fine in my latest several apps.

DonaldTrump88 commented 7 years ago

Good, what is minimum version of supported Android SDK? What is design rationale behind adding mapping of UI elements in native lib? I feel UI can be better handled by App side.

fnc12 commented 7 years ago

minSdkVersion 15. View in module can have 'field functions'. They are declared using FIELD_DECL macro. FIELD_DECL(UI::TableView, tableView); means you expect that your view controller has UITableView property with tableView name. In C++ code you can get table view by calling tableView() inside view. For android: FIELD_DECL(android::widget::ListView, listView); means your activity/fragment has member called listView with type android.widget.ListView. You can get your list view in C++ code by calling listView() in your view. Also you can get other widgets like UI::Label, UI::TextField, on iOS andandroid::widget::TextView,android::widget::EditTexton android. More you can find inMitsoko/AndroidUtilandMitsoko/iOSUtildirs. Also you can omitFIELD_DECLif you don't like macros. To get data from your java/objc side in C++ first create a binding object from view'shandle` like this:

std::string name;
using android::widget::EditText;
using android::app::Activity;
#ifdef __APPLE__
UI::ViewController vc(this->handle);
UI::TextField textField = vc.sendMessage<Handle>("nameTextField");   // returns @property UITextField nameTextField;
name = textField.text();
#else
Activity activity(this->handle);
auto editText = activity.getField<EditText>("nameEditText");  // returns private EditText nameEditText;
name = editText.getText().toString().c_str();
#endif
cout << "name = " << name << endl;
fnc12 commented 7 years ago

View in module has OS dependent logic. That's why view has many #ifdef __APPLE__ and #ifdef __ANDROID__ compile time conditions. Presenter has OS independent logic.

DonaldTrump88 commented 7 years ago

Good, I shall go thorugh the code over weekend.

I use app and lib based on request and response model. App sends request to lib. The lib sends response back .The request and response are in JSON format.

fnc12 commented 7 years ago

Ok. Here you can find just the same example. Service VkApi requests countries from https://api.vk.com/method/database.getCountries?lang=en and parses them to DataModel::Country objects using https://github.com/nlohmann/json lib.

DonaldTrump88 commented 7 years ago

Thanks. Can I disable all UI components and their interaction with data e.g. using preprocessor directive and access only data model?

fnc12 commented 7 years ago

Yes. Just ignore them. Or maybe you need to use djinni instead

DonaldTrump88 commented 7 years ago

I saw djinni before and do not want its features. Thanks

fnc12 commented 7 years ago

But you need UI::ViewController and android::app::Activity classes in your Core to call java/objc code from it

DonaldTrump88 commented 7 years ago

The core is present in template. I think, template is an example. For networking Mitsoko is required. am I right?

fnc12 commented 7 years ago

Yep

fnc12 commented 7 years ago

Oh no - you also need to add helper classes on objc in NI.h and NI.mm and java in kz/outlawstudio/viper/ package

DonaldTrump88 commented 7 years ago

Sorry, I did not understand you. Where are those files? and where should I add them?

fnc12 commented 7 years ago

https://github.com/fnc12/mitsoko-template/tree/master/proj.ios/mitsoko_ios/mitsoko-util - here helper objc classes. They are required for some bindings to work well. For example some of them implement delegate methods (c++ class cannot derive from objc protocol that's why objc helper classes are required). Just add them to your Xcode project and that's all. https://github.com/fnc12/mitsoko-template/tree/master/proj.android/app/src/main/java/kz/outlawstudio/viper - android helper files. Located in a single package kz.outlawstudio.viper. So just add this package (or just insert this folder to app/src/main/java dir and that's all. Network requests are built with java classes - C++ just calls them and the call back once data is received.

DonaldTrump88 commented 7 years ago

I have JNI from app to lib. I was thinking to add this Mitsoko library without disturbing old JNI. -So app will call library. Then the library will call Mitsoko for networking calls. Once the call is complete the library will return call to Mitsoko.

Will this work?

fnc12 commented 7 years ago

Yep. Try it - it's easy.

DonaldTrump88 commented 7 years ago

:)

DonaldTrump88 commented 7 years ago

My iOS application will be in Swift. Does Mitsoko force Objective C or Swift language for iOS apps?

fnc12 commented 7 years ago

Doesn't matter - one call call objc function from swift and reverse

DonaldTrump88 commented 7 years ago
  1. There is no release of created string in AndroidUtil\java\lang\String.cpp. Is it because of usage of std::move(create(p)) AndroidUtil\java\io\File.cpp ?
  2. Where is connection with HttpURLConnection?
  3. Does Mitsoko library have any dependency?
fnc12 commented 7 years ago
  1. What do you mean release of created string? Dalvik garbage collector releases all local variables once it decides to do so.
  2. Mitsoko/Url/Request
  3. Just Cocoa touch SDK and Android SDK with CrystaX NDK