How to write REST client code with cpprest
Agenda
- Brief introduction to cpprest sdk
- Play with the sample code
- Task based asynchronous programming
- Practice - writing rest client code with cpprest
Brief introduction to cpprest sdk
What is cpprest sdk
- Microsoft open-source project
- https://github.com/Microsoft/cpprestsdk
- Support Windows, Linux, MAC OS, iOS, Android
-
Modern asynchronous C++ API design
- Help C++ developers connect to and interact with service
Why we'd like to talk about this today
- Our product is being designed/re-designed with the micro-service architecture.
- Server needs to provide REST services to the clients.
- On the other hand, server also needs to talk to other service provider as a client.
Play with the sample code
Task based asynchronous programming
What is task
- A task is a unit of work that performs a specific job and typically runs in parallel with other tasks.
- .NET has had them for a while. Knowns as concurrency::task in <ppltasks.h>.
- In order to make cpprest usable also with Visual Studio and on other non-Windows platforms, cpprest have built a special version of PPL, which is placed in a different namespace, pplx.
Create a task
// create task
pplx::task<int> lIntTask1([]
{
return 1;
});
auto lIntTask2 = pplx::create_task([]
{
return 2;
});Interaction with the asynchronous task
-
To check if the task is finished or not, we can use 'bool pplx::task<T>::is_done()'.
-
To block until the task finishes, use 'void pplx::task<T>::wait()'.
-
To block until the task finishes and fetch the result of the task, use 'T pplx::task<T>::get()'.
if (lIntTask1.is_done())
{
cout << lIntTask1.get() << endl;
}
lIntTask2.wait();
cout << lIntTask2.get() << endl;Create task's continuations
You can use the task::then to compose tasks into a set of dependent operations. This composition model is supported by the notion of continuations.
Value-Based Versus Task-Based Continuations
- A value-based continuation is scheduled for execution when the antecedent task completes without error and is not canceled.
- A task-based continuation is always scheduled for execution when the antecedent task finishes, even when the antecedent task is canceled or throws an exception.
// create task continuation
pplx::task<void> lIntContinuation1 = lIntTask1.then([](int iNumber)
{
cout << iNumber << endl;
});
auto lIntContinuation2 = lIntTask2.then([](pplx::task<int> iTask)
{
cout << iTask.get() << endl;
});Error/exception handling
cout << "running a task..." << endl;
auto t = pplx::create_task([]() -> int
{
throw exception();
return 1;
});
// value-based continuation.
auto c1 = t.then([](int n)
{
// we don't expect to get here because the antecedent task always throws.
cout << "received " << n << "from C1" << endl;
});
// Task-based continuation.
auto c2 = t.then([](pplx::task<int> previousTask)
{
// We do expect to get here because task-based continuations are scheduled even when the antecedent task throws.
try
{
cout << "received " << previousTask.get() << "from C2" << endl;
}
catch (const exception& e)
{
cout << "caught exception from previous task" << endl;
}
});
// wait for the continuations to finish.
try
{
cout << "waiting for tasks to finish..." << endl;
(c1 && c2).wait();
}
catch (const exception& e)
{
cout << "caught exception while waiting for all tasks to finish." << endl;
}Practice - writing rest client code with cpprest
Implement one GET task to fetch the index document
To recap
-
Set up the URL/URI.
-
Create and sent the http request.
-
When the response header arrives, extract the data from the body and do the business logic to process the data.
-
Error/exception handling.
-
If you need the return value of the asynchronous tasks. Then use task::get or task::wait to wait for all asynchronous tasks to complete and handle all possible exception.
-
Otherwise, add a task based continuation to handle all possible exceptions.
-
THE END
For more details, you may visit this confluence page.
Cpprest
By bawu
Cpprest
- 6