crow icon indicating copy to clipboard operation
crow copied to clipboard

How to make Get/Post/Put/Delete request using crow ?

Open Shravan40 opened this issue 9 years ago • 39 comments

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'

Shravan40 avatar Dec 16 '16 09:12 Shravan40

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);
        }
    });

afiorillo avatar Dec 18 '16 15:12 afiorillo

@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 avatar Dec 21 '16 22:12 Shravan40

@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.

afiorillo avatar Dec 21 '16 22:12 afiorillo

@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.
    });

Shravan40 avatar Dec 21 '16 23:12 Shravan40

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.

afiorillo avatar Dec 22 '16 14:12 afiorillo

@andrewmfiorillo What if one requests with CORS error ? using Ajax, getting preflight errors

GuacheSuede avatar Feb 25 '17 18:02 GuacheSuede

Hey @GuacheSuede, are you including the CORS header in the server responses? This website has pretty useful info on enabling CORS.

afiorillo avatar Feb 25 '17 18:02 afiorillo

@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

GuacheSuede avatar Feb 25 '17 21:02 GuacheSuede

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.

afiorillo avatar Feb 27 '17 14:02 afiorillo

Thank you Andrew for the reply, my issue is finding the function to add the header

GuacheSuede avatar Feb 27 '17 14:02 GuacheSuede

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.

afiorillo avatar Feb 27 '17 15:02 afiorillo

Thank you @andrewmfiorillo :)

GuacheSuede avatar Mar 02 '17 10:03 GuacheSuede

@andrewmfiorillo I am still getting preflighted CORS error with Allow Cross origin, do you have a solution ?

GuacheSuede avatar Mar 02 '17 20:03 GuacheSuede

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.

afiorillo avatar Mar 03 '17 19:03 afiorillo

@andrewmfiorillo Yup, fixed it !, needed an options method

GuacheSuede avatar Mar 04 '17 04:03 GuacheSuede

I am wondering if Crow supports session. How is session handle in crow?

bnlambert avatar Sep 19 '17 16:09 bnlambert

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.

afiorillo avatar Sep 20 '17 13:09 afiorillo

@Shravan40 Did your question get answered? It looks like this thread has moved a bit off topic.

afiorillo avatar Sep 20 '17 13:09 afiorillo

You have a point here. Thank you very much.

bnlambert avatar Sep 20 '17 13:09 bnlambert

can crow handle post request for multipart data?

princythomasss avatar May 13 '21 07:05 princythomasss

@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 avatar May 13 '21 10:05 The-EDev

@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 avatar May 13 '21 10:05 princythomasss

@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 avatar May 13 '21 11:05 The-EDev

@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

princythomasss avatar May 13 '21 12:05 princythomasss

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 avatar May 13 '21 13:05 The-EDev

@The-EDev I have given only one file, i have removed the first part and checked still its 0...

princythomasss avatar May 13 '21 13:05 princythomasss

in your request, there is a part before demo.txt

------CppRestSdkClientFA37jNCchRYdSBZA
Content-Disposition: form-data; name="Filename"

modelname.txt

The-EDev avatar May 13 '21 13:05 The-EDev

@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

princythomasss avatar May 13 '21 13:05 princythomasss

let me look into it

The-EDev avatar May 13 '21 13:05 The-EDev

@The-EDev Okayy.

princythomasss avatar May 13 '21 14:05 princythomasss