How to make Get/Post/Put/Delete request using crow ?
I would like to make an api call inside the project. And response of that call will be used as for some other work.
Here is the equivalent curl request is given
curl -XGET 'https://domainName/pathToApi?v=78854&q="Txn%20of%20INR%20535.74%20made' \
-H 'Authorization: Bearer Server Access Token'
Building on the params example from example_with_all.cpp, something like this might be what you're looking for.
CROW_ROUTE(app, "/pathToApi/<int>")
.methods("GET"_method, "POST"_method, "DELETE"_method)
([](const request& req, const int& id) {
if (req.method == "GET"_method)
{
if ((req.url_params.get("v") != nullptr) & (req.url_params.get("q") != nullptr))
{
// ...
}
// handle get
}
else if (req.method == "POST"_method)
{
// handle post
}
else if (req.method == "DELETE"_method)
{
// handle delete
}
else
{
return crow::response(404);
}
});
@andrewmfiorillo : I too have see that file, but didn't get much idea from it. Could you please provide me a real time example. I might help me better to understand.
@Shravan40 : This is a more complete example.
// file: multi-method-example.cpp
#include "crow.h"
using namespace crow;
int main()
{
SimpleApp app;
CROW_ROUTE(app, "/pathToApi/<int>")
.methods("GET"_method, "POST"_method, "DELETE"_method)
([](const request& req, const int& id) {
if (req.method == "GET"_method)
{
if ((req.url_params.get("v") != nullptr) & (req.url_params.get("q") != nullptr))
{
// ...
}
return response(200, "You used GET");
}
else if (req.method == "POST"_method)
{
return response(200, "You used POST");
}
else if (req.method == "DELETE"_method)
{
return response(200, "You used DELETE");
}
else
{
return response(404);
}
});
app.port(18080).multithreaded().run();
}
To compile with gcc, I think you could call
gcc multi-method-example.cpp -I<path/to/crow>
but I can't confirm on my work machine. I'll test at home.
@andrewmfiorillo : I think you didn't get my question.
I am asking here is that, I would like to write a post method api call using crow.
CROW_ROUTE(app,"/monthlyContributionGoal")
.methods("POST"_method)
([](const crow::request& req) {
string input_error;
auto x = Json::parse(req.body, input_error);
if (x == nullptr)
return crow::response(400);
auto userId = x["user_id"].int_value();
// Now here i want to call an external api, which response will used for some calculation over here.
// External api method can be post,get and delete.
// Do something something based on above external api response.
//return crow response.
});
Ahh! I did not understand your question initially.
Crow is an HTTP serving library, but it does not have facilities to act as an HTTP client. It does, however, use boost.asio which could be coaxed into making such requests like this example. If you're not opposed to introducing additional dependencies, you could use something like libcurl and cpr, though there are probably many other options out there.
@andrewmfiorillo What if one requests with CORS error ? using Ajax, getting preflight errors
Hey @GuacheSuede, are you including the CORS header in the server responses? This website has pretty useful info on enabling CORS.
@andrewmfiorillo Thanks for the reply, I am trying to enable CORS headers Allows-Cross-Origin on Crow, cannot seem to find any docs about it
Hey @GuacheSuede, it'll take me a little while to setup a project to test a solution, but my impression is to add the header to the response object before returning it. If I remember right, there's some headers attribute, or some method attached to the object which lets you add a key/value pair to the header. The pair you want to add is:
Access-Control-Allow-Origin: *
Later tonight I should be able to whip up a functional example, but hopefully that helps for now.
Thank you Andrew for the reply, my issue is finding the function to add the header
Hey @GuacheSuede, I dug up a piece of old-ish Crow code which sets the header. This is an example function which just repeats the request given, but sets the Content-Type header. You should be able to use the add_header function to add the Allow-Cross-Origin key/value pair.
response EchoRequest(const std::string& specialInformation)
{
// echo response
response resp;
resp.code = 200;
resp.add_header("Content-Type", "text/plain");
resp.write(specialInformation);
return resp;
}
This also answers, I think, #217.
Edit: I forgot the mention this is using the Crow namespace, so response is the Crow::response.
Thank you @andrewmfiorillo :)
@andrewmfiorillo I am still getting preflighted CORS error with Allow Cross origin, do you have a solution ?
I'm not sure what your context is. What is the error it gives, and/or how could you reproduce it?
One guess is that your client is calling OPTIONS on the resource as part of the preflight, but if OPTIONS isn't routed that will probably result in a preflight error. Mozilla's developer docs talks about CORS and preflighted requests.
@andrewmfiorillo Yup, fixed it !, needed an options method
I am wondering if Crow supports session. How is session handle in crow?
Often time session cookies are passed along in the headers of the requests. There are a lot of libraries for higher level HTTP servers (I'm thinking Flask in Python and Express in JS) that use those session headers for fancy things, but you would have to build all of that up from scratch. In any case, you would want to add/use the request headers to maintain session info.
@Shravan40 Did your question get answered? It looks like this thread has moved a bit off topic.
You have a point here. Thank you very much.
can crow handle post request for multipart data?
@princythomasss Unfortunately this version of crow is unmaintained. Myself and a few other people forked it here and added many new features (including multipart data support).
So to answer your question, this version of crow cannot, but the fork mentioned above can.
@The-EDev HI thankyou for the response.. im able to get the multipart post request request body, how to extract and store the files in local system? do you have any idea?
CROW_ROUTE(app, "/") .methods("GET"_method, "POST"_method) ([](const crow::request& req) { CROW_LOG_INFO << "msg from client: " << req.body; std::cout << req.body; return ""; });
@princythomasss The way I do it in my own REST API is like this (I'm pulling crow from CrowCpp/crow/master):
crow::multipart::message x(req);
std::string fileName;
std::string fileExt;
if (x.parts[0].headers[0].params.size() != 0)
{
std::string fnf(getFileNameFull(x.parts[0].headers[0].params));
int found (fnf.find('.'));
fileName = std::string(fnf.substr(0, found));
fileExt = std::string(fnf.substr(found+1));
}
mkdir("files", 0777);
std::string saveFilePath = "files/" + fileName + '.' + fileExt;
std::ofstream saveFile;
saveFile.open(saveFilePath);
saveFile << x.parts[0].body;
saveFile.close();
With the helper function being:
inline std::string getFileNameFull(std::unordered_map<std::string, std::string>& map)
{
for (auto pair : map)
{
if (pair.first == "filename")
{
return pair.second;
}
}
return "";
}
Please note that this only works on the first multipart file passed, for multiple files you'll need to loop on x.parts instead of using x.parts[0]
@The-EDev hii, I ran the code, files folders is getting created but no files are generted..
------CppRestSdkClientFA37jNCchRYdSBZA Content-Disposition: form-data; name="Filename"
modelname.txt ------CppRestSdkClientFA37jNCchRYdSBZA Content-Disposition: form-data; name="file"; filename="demo.txt" Content-Type: text/plain
data in the txt file
------CppRestSdkClientFA37jNCchRYdSBZA--
This this the response body generated.
the value in x.parts[0].headers[0].params.size() is 0
The problem is that the code I posted only takes the first part, your file is in the second part, so it's not being taken
@The-EDev I have given only one file, i have removed the first part and checked still its 0...
in your request, there is a part before demo.txt
------CppRestSdkClientFA37jNCchRYdSBZA
Content-Disposition: form-data; name="Filename"
modelname.txt
@The-EDev
------CppRestSdkClientFA37jNCchRYdSBZA Content-Disposition: form-data; name="file"; filename="demo.txt" Content-Type: text/plain
data
------CppRestSdkClientFA37jNCchRYdSBZA--
I have removed, now im getting the above response. still no file is generated
let me look into it
@The-EDev Okayy.