I am working on Embedded Linux and I want Restful web services to run on my Linux Custom Board.
My objective is to send/receive data (in JSON format) to/from web server (httpd server).
Also, I want to create that Restful Web services using C++ language.
Please see below idea about need of Restful Web Services for my Linux Custom Board.
First, I will send HTTP request with JSON format data through httpd server which is running on my linux board.
Then, I want to create one binary or server which implements this Restful Web Services in c++ language which is used to handle HTTP request.
Then, This C++ binary will send response back to httpd server for display purpose over web browser.
Does anyone have idea or example about how to create Restful Web Services using C++ language?
Any help on Restful is welcome.
Does any one has idea about ffead and its functionalities which fulfills my Restful Web Services or not?
Restbed can address your requirements with the exception of a JSON parser. However, combining a solution with one of the many C++ JSON implementations already available requires very little work.
#include <memory>
#include <string>
#include <cstdlib>
#include <sstream>
#include <jsonbox.h>
#include <restbed>
using namespace std;
using namespace restbed;
void get_method_handler( const shared_ptr< Session > session )
{
const auto request = session->get_request( );
size_t content_length = request->get_header( "Content-Length", 0 );
session->fetch( content_length, [ ]( const shared_ptr< Session >& session, const Bytes& body )
{
JsonBox::Value json;
json.loadFromString( string( body.begin( ), body.end( ) ) );
//perform awesome solutions logic...
stringstream stream;
json.writeToStream( stream );
string response_body = stream.str( );
session->close( OK, response_body, { { "Content-Length", ::to_string( response_body.length( ) }, { "Content-Type": "application/json" } } );
} );
}
int main( const int, const char** )
{
auto resource = make_shared< Resource >( );
resource->set_path( "/resource" );
resource->set_method_handler( "GET", get_method_handler );
auto settings = make_shared< Settings >( );
settings->set_port( 1984 );
settings->set_default_header( "Connection", "close" );
Service service;
service.publish( resource );
service.start( settings );
return EXIT_SUCCESS;
}
Alternative RESTful frameworks
Casablanca C++ REST SDK (edit: project moved & renamed)
CPP-Netlib
RESTful Mapper
Simple REST (edit: no longer exist)
Google is your friend.
Alternative JSON frameworks
LibJSON
RapidJSON
JSONMe
JSON++
JSON-CPP
Google is your friend.
I know this is late, but something new has come up a year or two ago.
If you're into hardcore asynchronous programming for high-performance, you can consider boost::beast. It's a layer above boost::asio (the generic tcp/udp and i/o library) that has both http(s) and websocket servers/clients.
Keep in mind that these are ideal for performance and full freedom in multithreading (you can literally run your server on thousands of threads with almost perfect caching if you have a server that can take it), but they have a steep learning-curve. Do this only if you need to have absolute control over everything!
I'm using oatpp in combination with nlohmann JSON. Though you may get away with purely oatpp as it has built-in JSON handling features. Please, see a step by step guide.
If you are using Apache2 or Nginx as Web server and want to deploy RESTful JSON Web services on it, try ngrest. It's easy in use and fast.
To represent JSON in C++ ngrest uses standard C++ types (generic types, C++ structs, typedefs, STL containers, etc.). Access to raw JSON is possible too. Optionally you can access DBMS using ngrest-db extension.
An example of typical workflow of creating the C++ service:
1) create a service (it may be implemented as h/cpp or single hpp file):
ngrest create -d hpp Users
2) implement data structures and operations (resources). Edit users/users/src/Users.hpp like that:
// a structure to represent data in JSON
struct User {
int id;
std::string name;
std::string email;
};
// *location: /users
class Users: public ngrest::Service
{
public:
// *method: POST
int add(const User& user) {
return Db::inst().users().insert(user).lastInsertId();
}
// *location: /{id}
User get(int id) {
return Db::inst().users().selectOne("id = ?", id);
}
// *method: DELETE
void remove(int id) {
Db::inst().users().deleteWhere("id = ?", id);
}
};
3) run your service for the test:
cd users
ngrest
4) test your RESTful Web service using service tester: http://localhost:9098/ngrest/service/users
5) deploy your Web Service library to the Web Server running ngrest.
If you are building a RESTful service client, you should consider a library such as Casablanca (which is maintained by Microsoft and is a cross-platform solution for accessing RESTful APIs) https://github.com/Microsoft/cpprestsdk.
Otherwise you could also use libcurl https://curl.haxx.se/libcurl
There are C++ bindings for curl. Depending on your board, libcurl might already be installed. All you have to do would be to use the C++ bindings.
Both libraries handle http/https. libcurl does not provide a json parser but you could easily combine it with any C++ json parser available. Casablanca is complete and built on an asynchronous model. It relies however on the Boost libraries. Nevertheless I have used on an Intel Edison board with success.
For send/receive data in JSON format, try jsoncpp
Use an embedded web server, such as Mongoose, CivetWeb or NXWeb. (see this post for more details)
Generally these are trivial to embed in your application, then you only need a JSON library to parse/create JSON data in the web server route handlers. REST is, after all, only HTTP requests so this is easy to implement using one of the above.
Probably your best bet is to use FastCGI to create a module to interface with your web server. This should prevent you from having to implement your own HTTP server.
There are some frameworks like CppCMS that embed their own HTTP server, so you might not need something as heavy as Apache httpd.
I'm assuming your REST service will not be under heavy load.
Also, CppCMS supports JSON out of the box, see http://cppcms.com/wikipp/en/page/cppcms_1x_json.
The minimal web service capable of using SHTML would include Open SSL..
Here is an example of a simple C++ SHTML Server using TCP/IP calls no framework other than OpenSSL
simple C++ SHTML Web Service Server using openssl
simple C++ SHTML Web Service Client using openssl
Here is a pretty comprehensive list of Restful Frameworks by language like 300 of them..
List of Restful Web Service Frameworks
As of writing this answer searching that more comprehensive list for "C++" yields
more than 60 entries.
Related
Basically I'm just messing around with a library which should work with some API (for studying purpose). So, in order to conform OAuth protocol I need to authorize using some sort of web view and get access token. AT is passed as GET parameter after redirection. As a novice in Qt, I have no idea how to track web view state and fetch essential data.
Practically I have an auth procedure that takes a callback, which has to return access token afterwards, as a parameter.
vk_api::auth<>("123456", vk_api::scopes::friends, [this](const std::string& contents) -> std::string {
this->ui->m_webview->setHtml(QString(contents.c_str()));
...
});
Also, I do not want to block UI while calling it.
Some options you have:
Use the new Qt Network Authorization library.
If you want to do it yourself, the usual way is to let the service redirect to a localhost port, which you listen to. See QTcpServer and Network Programming with Qt for that.
Qt WebKit is deprecated, use QWebEngineView instead. You can intercept requests and look for the authorization token using a QWebEngineUrlRequestInterceptor
You can intercept requests made from Qt WebKit and look for the authorization by using a custom QNetworkAccessManager.
I have an website in Django that is using the REST framework to provide an API.
Is there a way to generate an API client that can be used to communicate with this API that provides objects mapping the contents of the API?
If you're talking about a javascript client API, I have a django management task that I use to generate a javascript library from my DRF API
using AngularJS 1.*. I'm still using DRF 2.4, for easy nested object writes, and Django 1.7. Here it is as a github gist
Take that file, stick it in <app>/management/commands/ and call it like:
python manage.py rest_framework_2_js rest_api.gen.js [base_factory_name] [server_base_url]
If your base_factory_name was foo and you had an API object at server_base_url/Bar/ named Bar, you would use it like:
foo.Bar.get(42)
.then(function(bar_inst) {
console.log(bar_inst);
bar_inst.baz = 77;
bar_inst.save()
.then(function() {
console.log('bar_inst has been saved');
});
})
or
foo.BarList.get('filter_a=5&field_filter_b=abc,d')
.then(function(data) {
console.log(data.results);
})
Each instance in the data.result will be a foo.Bar instance.
You can add callbacks before sending to the server and after retrieving from the server using foo.Bar.pre_save(function (inst) {/*callback mutator*/}) and foo.Bar.post_restore( function(inst) { /*callback mutator*/}).
Anyways, this management task is not productized and it has only one user - me, but I have been using it for 2 years and it works great for me :-) We can work to get it working in your configuration if you like. Naturally the biggest caveat is the AngularJS 1.* dependency.
Does Casablanca (Microsoft's C++ REST SDK) be used to serve web assets (html, images, js, css, etc)?
I built a REST server with Casablanca, and for the specific REST stuff it works great. But how do I serve a full site?
Do I have to run nginx/apache in parallel to my REST server to serve assets, or build some simple file webserver with boost.asio, etc?
I am targeting an embedded system and thus want to keep a low resources demand, so ideally Casablanca it self could serve my assets as well as my routes.
You probably won't want to do that with Casablanca. It's intended for use as a REST endpoint server. It's possible, but it makes more sense to use an instance of Apache/Tomcat to serve a website.
That being said, it is possible. You can give it a try by doing something like the following in your GET Handler:
void HandleGet( http_request Message) {
utility::string_t body =
"<html><body>"
"<h1>Hello World!</h1>"
"</body></html>";
Message.reply( status_codes::OK, body, L"text/html");
}
In a standalone (selfhosted) application, I would like to have an httpserver that on a single base adress can either serve simple web pages (without any serverside dynamics/scripting, it just returns the content request files) or serve RESTful webservices:
when http://localhost:8070/{filePath} is requested, it should return the content of the file (html, javascript, css, images), just like a normal simple webserver
everything behind http://localhost:8070/api/ should just act as a normal RRESTful Web API
My current approach uses ASP.NET Web API to server both the html pages and the REST APIs:
var config = new HttpSelfHostConfiguration("http://localhost:8070/");
config.Formatters.Add(new WebFormatter());
config.Routes.MapHttpRoute(
name: "Default Web",
routeTemplate: "{fileName}",
defaults: new { controller = "web", fileName = RouteParameter.Optional });
config.Routes.MapHttpRoute(
name: "Default API",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional });
The WebController is the controller that serves the web pages with this naive code:
public class WebController : ApiController
{
public HttpResponseMessage Get(string fileName = null)
{
/// ...
var filePath = Path.Combine(wwwRoot, fileName);
if (File.Exists(filePath))
{
if (HasCssExtension(filePath))
{
return this.Request.CreateResponse(
HttpStatusCode.OK,
GetFileContent(filePath),
"text/css");
}
if (HasJavaScriptExtension(filePath))
{
return this.Request.CreateResponse(
HttpStatusCode.OK,
GetFileContent(filePath),
"application/javascript");
}
return this.Request.CreateResponse(
HttpStatusCode.OK,
GetFileContent(filePath),
"text/html");
}
return this.Request.CreateResponse(
HttpStatusCode.NotFound,
this.GetFileContnet(Path.Combine(wwwRoot, "404.html")),
"text/html");
}
}
And again, for everything behind /api, controllers for normal REST APIs are used.
My question now is: Am I on the right track? I kind of feel that I am rebuilding a webserver here, reinventing the wheel. And I guess that there are probably a lot of http request web browsers could make that I do not handle correctly here.
But what other option do I have if I want to self host and at the same time server REST web APIs and web pages over the same base address?
Looks like you are trying to recreate asp.net FileHandler for self host. There is a better solution though. Using Katana(an OWIN host) as the hosting layer for web API. OWIN supports hosting multiple OWIN frameworks in the same app. In your case, you can host both web API and a file handler in the same OWIN app.
Filip has a good blog post on this to get you started here. You can use configuration code like this,
public void Configuration(IAppBuilder appBuilder)
{
// configure your web api.
var config = new HttpConfiguration();
config.Routes.MapHttpRoute("default-api", "api/{controller}");
appBuilder.UseWebApi(config);
// configure your static file handler.
appBuilder.UseStaticFiles();
}
IMO there is nothing wrong with what you are doing. I use self-host for delivering files, html docs as well as being a regular API. At the core, self-host is using HTTP.SYS just as IIS is.
As RaghuRam mentioned there are Owin hosts that have some optimizations for serving static files, but WCF selfhost is quite capable of getting decent perf for serving files.
See this link which uses a more straigftforward approach
Setting app a separate Web API project and ASP.NET app
RouteTable.Routes.IgnoreRoute(".js");
RouteTable.Routes.IgnoreRoute(".html");
I am trying to set some session information in one web method and return it in another web method, but the session data is always empty on the second web method. Here is what I tried
Web Method 1 - Sets session information
Method StartSession() As %String [WebMethod]
{
set %session.NewSession = 1
set %session.Data("key") = "dude"
Quit "Session Started"
}
Web Method 2 - Gets session information should return dude, but is returning blank
Method TestSession() As %String [WebMethod]
{
Quit $Get(%session.Data("key"))
}
To use sessions with Cache web services you need to set the SOAPSESSION class parameter of your web service class equal to 1.
Doing so will cause the web service to return a SOAP session header in the response. If you are using a client that was built to expect this header you may not need to set up anything else. Otherwise, your client application will have to read this header and include it in all further requests, so the server can know which session you are using. An example of this header given in the documentation is:
<csp:CSPCHD xmlns:csp="http://www.intersystems.com/SOAPheaders">value of
CPSCHD token</csp:CSPCHD>
Note that security is a separate issue that your example doesn't address.
Also note that Intersystems has decided that web services will continue to use a license for some period of time after the call has been made. I can't find documentation on this, and I believe it's something like a few seconds per call. I believe that this can cause license issues that would not occur if you used other software to provide web services, and had that other software call Cache via some mechanism other than web services. I believe this is true even when that other software carefully follows all the rules in the license agreement about named and anonymous users. However, I'm not certain about any of this licensing stuff. Still, you might want to do some testing before you commit to an architecture.
As an alternative to psr's answer another way to handle state is to use custom SOAP headers.
For example:
Create a class for your custom SOAP headers like below:
Class Headers.TimeStamp Extends %SOAP.Header
{
Property TimeSent As %TimeStamp;
}
In the web method do this:
set h=##class(Headers.TimeStamp).%New()
set h.TimeSent=$ZTIMESTAMP
do ..HeadersOut.SetAt(h,"Timestamp")
This will generate the following SOAP header:
<SOAP-ENV:Header>
<TimeStamp xmlns:hdr="http://www.myapp.org">
<TimeSent>60712,70996.027Z</TimeSent>
</TimeStamp>
</SOAP-ENV:Header>
This will allow state to be maintained within the SOAP headers rather than using Cache's session management.