Skip to content

RestControllers

Sumeet Chhetri edited this page Sep 13, 2018 · 2 revisions

REST Controller

REST Controllers provide custom execution logic for configured HTTP requests over specific HTTP methods. Request URI's and HTTP Verbs (GET,PUT,POST,DELETE etc) are mapped to configured C++ class methods.

All Serializable POCO objects can be mapped as request and response entities in a given rest controller.

We will consider a REST controller having the following functions

  1. Add 2 numbers

  2. Given base b and exponent n return the Exponentiation bn

  3. Read a vector of integers and return the same as response

  4. Read an Object and return the same

  5. Read a vector of Objects and return the same

  6. Upload a multipart form with one file and one parameter

  7. Upload a multipart form with 3 files and one parameter

  8. Upload a multipart form with a vector of files and one parameter

    Marker Based

    OneObject.h

    #ifndef OneObject_H_
    #define OneObject_H_
    #include "string"
    using namespace std;
    
    class OneObject {
    	int id;
    	string name;
    public:
    	OneObject();
    	virtual ~OneObject();
    	int getId() const;
    	void setId(int);
    	string getName() const;
    	void setName(string);
    	bool operator<(OneObject t) const;
    };
    
    #endif

    OtherObject.h

    #ifndef OtherObject_H_
    #define OtherObject_H_
    #include "string"
    using namespace std;
    class OtherObject
    {
    	public:
    		int i;
    		string j;
    		float c;
    };
    
    #endif

    YetAnotherObject.h

    #ifndef YetAnotherObject_H_
    #define YetAnotherObject_H_
    #include "OneObject.h"
    #include "vector"
    #include "OtherObject.h"
    #include "queue"
    #include "list"
    class YetAnotherObject {
    	vector<int> vpi;
    public:
    	OneObject t;
    	int y;
    	vector<int> vi;
    	vector<string> vs;
    	vector<double> vd;
    	vector<long> vl;
    	vector<bool> vb;
    	vector<short> vsh;
    	vector<OtherObject> vyo;
    	list<int> li;
    	std::queue<short> qsh;
    public:
    	void setVpi(vector<int> vpi)
    	{
    		this->vpi = vpi;
    	}
    	vector<int> getVpi()
    	{
    		return vpi;
    	}
    	YetAnotherObject();
    	virtual ~YetAnotherObject();
    };
    
    #endif

    ExampleRestController

    (Header)

    #ifndef ExampleRestController_H_
    #define ExampleRestController_H_
    
    #include <math.h>
    #include <iostream>
    #include "vector"
    #include "YetAnotherObject.h"
    #include <fstream>
    #include "CastUtil.h"
    
    #pragma @RestController path="/restful"
    class ExampleRestController {
    public:
    	#pragma @GET path="/add" statusCode="200"
    	int addNumbers(
    		#pragma @QueryParam name="a"
    		int,
    		#pragma @QueryParam name="b"
    		int);
    
    	#pragma @GET path="/{b}/power/{n}" statusCode="200"
    	double power(
    		#pragma @PathParam name="b"
    		int,
    		#pragma @PathParam name="n"
    		int);
    
    	#pragma @POST path="/vectorI" statusCode="200"
    	vector<int> testVector(
    		#pragma @Body
    		vector<int>);
    
    	#pragma @POST path="/object" statusCode="200"
    	YetAnotherObject testObject(
    		#pragma @Body
    		YetAnotherObject);
    
    	#pragma @POST path="/vectorObject" statusCode="200"
    	vector<YetAnotherObject> testVectorObject(
    		#pragma @Body
    		vector<YetAnotherObject> param);
    
    	#pragma @POST path="/uploadOne" statusCode="200"
    	string testUploadFile(
    		#pragma @MultipartContent name="file"
    		ifstream* ifs, 
    		#pragma @MultipartContent name="field"
    		string param);
    	
    	#pragma @POST path="/uploadMulti" statusCode="200"
    	string testUploadFileMulti1(
    		#pragma @MultipartContent name="file1"
    		ifstream* ifs1, 
    		#pragma @MultipartContent name="file2"
    		ifstream* ifs2, 
    		#pragma @MultipartContent name="file3"
    		ifstream* ifs3, 
    		#pragma @MultipartContent name="field"
    		string param);
    
    	#pragma @POST path="/uploadVecFiles" statusCode="200"
    	string testUploadFileMulti2(
    		#pragma @MultipartContent name="files"
    		vector<ifstream*> vifs, 
    		#pragma @MultipartContent name="field"
    		string param);
    };
    
    #endif

    (Source)

    #include "ExampleRestController.h"
    
    int ExampleRestController::addNumbers(int a, int b)
    {
    	cout << "Processed input request inside ExampleRestController for addNumbers..." << endl;
    	return a + b;
    }
    
    double ExampleRestController::power(int base, int exponent)
    {
    	cout << "Processed input request inside ExampleRestController for power..." << endl;
    	return pow((double)base, (double)exponent);
    }
    
    vector<int> ExampleRestController::testVector(vector<int> param)
    {
    	cout << "Processed input request inside ExampleRestController for testVector..." << endl;
    	return param;
    }
    
    YetAnotherObject ExampleRestController::testObject(YetAnotherObject YetAnotherObject)
    {
    	cout << "Processed input request inside ExampleRestController for testObject..." << endl;
    	return YetAnotherObject;
    }		
    
    vector<YetAnotherObject> ExampleRestController::testVectorObject(vector<YetAnotherObject> param)
    {
    	cout << "Processed input request inside ExampleRestController for testVectorObject..." << endl;
    	return param;
    }
    
    string ExampleRestController::testUploadFile(ifstream* ifs, string param)
    {
    	string vals;
    	unsigned int siz = 0;
    	if (ifs!=NULL && ifs->is_open())
    	{
    		ifs->seekg(0, ios::end);
    		siz = ifs->tellg();
    	}
    	vals = "Uploaded File Size = " + CastUtil::lexical_cast<string>(siz);
    	vals += "\nField value passed = " + param;
    	cout << "Processed input request inside ExampleRestController for testUploadFile..." << endl;
    	return vals;
    }
    
    string ExampleRestController::testUploadFileMulti1(ifstream* ifs1, ifstream* ifs2, ifstream* ifs3, string param)
    {
    	string vals;
    	unsigned int siz = 0;
    	if (ifs1!=NULL && ifs1->is_open())
    	{
    		ifs1->seekg(0, ios::end);
    		siz = ifs1->tellg();
    	}
    	vals = "Uploaded File1 Size = " + CastUtil::lexical_cast<string>(siz);
    	siz = 0;
    	if (ifs2!=NULL && ifs2->is_open())
    	{
    		ifs2->seekg(0, ios::end);
    		siz = ifs2->tellg();
    	}
    	vals += "\nUploaded File2 Size = " + CastUtil::lexical_cast<string>(siz);
    	siz = 0;
    	if (ifs3!=NULL && ifs3->is_open())
    	{
    		ifs3->seekg(0, ios::end);
    		siz = ifs3->tellg();
    	}
    	vals += "\nUploaded File3 Size = " + CastUtil::lexical_cast<string>(siz);
    	vals += "\nField value passed = " + param;
    	cout << "Processed input request inside ExampleRestController for testUploadFileMulti1..." << endl;
    	return vals;
    }
    
    string ExampleRestController::testUploadFileMulti2(vector<ifstream*> vifs, string param)
    {
    	string vals;
    	for(int i=0;i<(int)vifs.size();++i) {
    		ifstream* ifs = vifs.at(i);
    		unsigned int siz = 0;
    		if (ifs!=NULL && ifs->is_open())
    		{
    			ifs->seekg(0, ios::end);
    			siz = ifs->tellg();
    		}
    		vals += "Uploaded File" + CastUtil::lexical_cast<string>(i) + " Size = " + CastUtil::lexical_cast<string>(siz) + "\n";
    	}
    	vals += "Field value passed = " + param;
    	cout << "Processed input request inside ExampleRestController for testUploadFileMulti2..." << endl;
    	return vals;
    }

    XML Based

    (Headers)

    ExampleRestController.h

    #ifndef ExampleRestController_H_
    #define ExampleRestController_H_
    
    #include <math.h>
    #include <iostream>
    #include "vector"
    #include "YetAnotherObject.h"
    #include <fstream>
    #include "CastUtil.h"
    
    class ExampleRestController {
    public:
    	int addNumbers(int,int);
    	double power(int,int);
    	vector<int> testVector(vector<int>);
    	YetAnotherObject testObject(YetAnotherObject);
    	vector<YetAnotherObject> testVectorObject(vector<YetAnotherObject> param);
    	string testUploadFile(ifstream* ifs, string param);
    	string testUploadFileMulti1(ifstream* ifs1, ifstream* ifs2, ifstream* ifs3, string param);
    	string testUploadFileMulti2(vector<ifstream*> vifs, string param);
    };
    
    #endif

    (Source)

    Same as above

    (Configuration)

    <app>
    	<restcontrollers>
    		<restcontroller class="ExampleRestController" path="/rest/path/rest1/">
    			<restfunction name="addNumbers" path="add/{1}/{2}" meth="GET"
    				statusCode="200">
    				<param type="int" name="1" from="path" />
    				<param type="int" name="2" from="path" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/rest/reqparam/rest1/">
    			<restfunction name="addNumbers" path="add" meth="GET"
    				statusCode="200">
    				<param type="int" name="1" from="reqparam" />
    				<param type="int" name="2" from="reqparam" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/rest/postparam/rest1/">
    			<restfunction name="addNumbers" path="add" meth="POST"
    				statusCode="200">
    				<param type="int" name="1" from="postparam" />
    				<param type="int" name="2" from="postparam" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/rest/header/rest1/">
    			<restfunction name="addNumbers" path="add" meth="GET"
    				statusCode="200">
    				<param type="int" name="a" from="header" />
    				<param type="int" name="b" from="header" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/rest/path1/rest2">
    			<restfunction name="addNumbers" path="+/{1}/{2}" meth="GET"
    				statusCode="200">
    				<param type="int" name="1" from="path" />
    				<param type="int" name="2" from="path" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/rest3">
    			<restfunction name="addNumbers" path="ad/{1}/{2}" meth="GET"
    				statusCode="200">
    				<param type="int" name="1" from="path" />
    				<param type="int" name="2" from="path" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController">
    			<restfunction name="power" meth="GET"
    				path="/rest/controller/base{1}/power/exp{2}" statusCode="200">
    				<param type="int" name="1" from="path" />
    				<param type="int" name="2" from="path" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController">
    			<restfunction name="addNumbers" meth="GET"
    				path="/addNumbers/{1}/{2}" statusCode="200">
    				<param type="int" name="1" from="path" />
    				<param type="int" name="2" from="path" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restvec">
    			<restfunction name="testVector" path="tstvec" meth="POST"
    				statusCode="200">
    				<param type="vector-of-int" from="body" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restvecobj">
    			<restfunction name="testVectorObject" path="tstvecobj"
    				meth="POST" icontentType="application/json" statusCode="200">
    				<param type="vector-of-YetAnotherObject" from="body" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restobj">
    			<restfunction name="testObject" path="tstobj" meth="POST"
    				icontentType="application/json" ocontentType="application/json"
    				statusCode="200">
    				<param type="YetAnotherObject" from="body" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restvecobj">
    			<restfunction name="testVectorObject" path="tstvecobj.xml"
    				meth="POST" icontentType="application/xml" statusCode="200">
    				<param type="vector-of-YetAnotherObject" from="body" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restobj">
    			<restfunction name="testObject" path="tstobj.xml" meth="POST"
    				icontentType="application/xml" statusCode="200">
    				<param type="YetAnotherObject" from="body" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restupload">
    			<restfunction name="testUploadFile" path="uploadFile"
    				meth="POST" icontentType="multipart/form-data" statusCode="200">
    				<param type="filestream" name="file" from="multipart-content" />
    				<param type="string" name="field" from="multipart-content" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restupload">
    			<restfunction name="testUploadFileMulti1" path="uploadFileMulti1"
    				meth="POST" icontentType="multipart/form-data" statusCode="200">
    				<param type="filestream" name="file1" from="multipart-content" />
    				<param type="filestream" name="file2" from="multipart-content" />
    				<param type="filestream" name="file3" from="multipart-content" />
    				<param type="string" name="field" from="multipart-content" />
    			</restfunction>
    		</restcontroller>
    		<restcontroller class="ExampleRestController" path="/restupload">
    			<restfunction name="testUploadFileMulti2" path="uploadFileMulti2"
    				meth="POST" icontentType="multipart/form-data" statusCode="200">
    				<param type="vector-of-filestream" name="files" from="multipart-content" />
    				<param type="string" name="field" from="multipart-content" />
    			</restfunction>
    		</restcontroller>
    	</restcontrollers>
    </app>