how to PUT multiple query parameter in REST web service - web-services

Do anyone know how to PUT multiple query parameter in REST web service?
I have write using java.My curl sample is like this:
curl -X PUT http://localhost:8080/project/resources/user/directory/sub-directory?name=shareuser&type=Read -v
My program is :
#PUT
#Path("{user}/{directory:.+}")
public Response doshare(#PathParam("user")String name,
#PathParam("directory")String dir,
#QueryParam("name")String sharename,
#QueryParam("type")String type){
mongoDAOImpl impl=new mongoDAOImpl();
Mongo mongo=impl.getConnection("127.0.0.1","27017");
DB db=impl.getDataBase(mongo,"public");
DBCollection coll=impl.getColl(db,name);
DBCollection coll2=impl.getColl(db,"sharedb");
shareDTO sharedto=new shareDTO();
String authority=type.toLowerCase();
if(authority.equals("rd")){
sharedto.setAuthority("4");
}else if(authority.equals("rw")){
sharedto.setAuthority("12");
}
sharedto.setTargetuser(sharename);
sharedto.setRealURI("/home/public/"+name+"/"+dir);
sharedto.setIdentifier(name);
sharedto.setParentURI("/home/public/"+sharename);
boolean bool = false;
sharefun=new sharefunction();
if(sharefun.checksubfoldershared(coll, coll2, sharedto)){
bool=sharefun.sharefiles(coll, coll2, sharedto);
}else{
System.out.println("Error");
}
// ...
But I only get the name query parameter.How to get or how to type in curl command in order to get all query parameter?

Your code is fine - the problem is with the way you're invoking curl. When passing a URL to curl that contains a '&', you have to put quotes around the URL. Otherwise, the shell will interpret the stuff after the '&' as a separate command.
EDIT: My text is getting munged when I submit it as a comment. Here's what you need to do:
curl -X PUT 'http://localhost:8080/project/resources/user/directory/sub-directory?name=shareuser&type=Read' -v

Have you tried using the -d option? e.g.
curl -X PUT -d "name=shareuser&type=Read" http://locahost:8080/project/resources/user/directory/sub-directory -v

You could try handling this all as a multipart upload (the server-side details aren't standardized and you didn't say what framework you're using so I can't give more clues) but I question why you're having the user and permissions set (via any parameters) in the first place. Surely you'd be better off deriving the user to store as through inspecting the user's login credentials and using a default set of permissions that they can change later on? Nearly as cheap, and enormously simpler.

Related

Why am I getting CURLE_NOT_BUILT_IN when using libcurl with CURLOPT_PROXY?

I'm debugging some HTTP request, using a proxy (Burp).
Let's say we have this command, running OK. Burp is capturing everything:
curl --proxy localhost:8080 -k https://www.ipchicken.com/
Now I'm trying to do the same, programmatically:
CURL *curlHandle;
CURLcode curlErrorCode;
curlHandle=curl_easy_init();
curlErrorCode=curl_easy_setopt(curlHandle,CURLOPT_URL,"https://www.ipchicken.com/");
curlErrorCode=curl_easy_setopt(curlHandle,CURLOPT_PROXY,"https://127.0.0.1:8080");
curlErrorCode=curl_easy_setopt(curlHandle,CURLOPT_SSL_VERIFYPEER,0);
curlErrorCode=curl_easy_setopt(curlHandle,CURLOPT_HTTPGET,1L);
// ...
curlErrorCode=curl_easy_perform(curlHandle);
// ...
curl_easy_cleanup(curlHandle);
All the curl_easy_setopt() calls return CURLE_OK. But curl_easy_perform() is returning CURLE_NOT_BUILT_IN.
This does not make sense, since the curl executable was made in the same build as the library I'm using.
Any idea about what could be happening?
Thanks.
I had to replace https:// with http:// for the CURLOPT_PROXY option:
curlErrorCode=curl_easy_setopt(curlHandle,CURLOPT_PROXY,"http://127.0.0.1:8080");
It works now.
For the record, even building libcurl with all features/packages did not allow me to use HTTPS for the proxy type.

How to specify the database in an ArangoDb AQL query?

If have multiple databases defined on a particular ArangoDB server, how do I specify the database I'd like an AQL query to run against?
Running the query through the REST endpoint that includes the db name (substituted into [DBNAME] below) ie:
/_db/[DBNAME]/_api/cursor
doesn't seem to work. The error message says 'unknown path /_db/[DBNAME]/_api/cursor'
Is this something I have to specify in the query itself?
Also: The query I'm trying to run is:
FOR col in COLLECTIONS() RETURN col.name
Fwiw, I haven't found a way to set the "current" database through the REST API. Also, I'm accessing the REST API from C++ using fuerte.
Tom Regner deserves primary credit here for prompting the enquiry that produced this answer. I am posting my findings here as an answer to help others who might run into this.
I don't know if this is a fuerte bug, shortcoming or just an api caveat that wasn't clear to me... BUT...
In order for the '/_db/[DBNAME/' prefix in an endpoint (eg full endpoint '/_db/[DBNAME/_api/cursor') to be registered and used in the header of a ::arangodb::fuerte::Request, it is NOT sufficient (as of arangodb 3.5.3 and the fuerte version available at the time of this answer) to simply call:
std::unique_ptr<fuerte::Request> request;
const char *endpoint = "/_db/[DBNAME/_api/cursor";
request = fuerte::createRequest(fuerte::RestVerb::Post,endpoint);
// and adding any arguments to the request using a VPackBuilder...
// in this case the query (omitted)
To have the database name included as part of such a request, you must additionally call the following:
request->header.parseArangoPath(endpoint);
Failure to do so seems to result in an error about an 'unknown path'.
Note 1: Simply setting the database member variable, ie
request->header.database = "[DBNAME]";
does not work.
Note 2: that operations without the leading '/_db/[DBNAME]/' prefix, seem to work fine using the 'current' database. (which at least for me, seems to be stuck at '_system' since as far as I can tell, there doesn't seem to be an endpoint to change this via the HTTP REST Api.)
The docs aren't very helpful right now, so just incase someone is looking for a more complete example, then please consider the following code.
EventLoopService eventLoopService;
// adjust the connection for your environment!
std::shared_ptr<Connection> conn = ConnectionBuilder().endpoint("http://localhost:8529")
.authenticationType(AuthenticationType::Basic)
.user(?) // enter a user with access
.password(?) // enter the password
.connect(eventLoopService);
// create the request
std::unique_ptr<Request> request = createRequest(RestVerb::Post, ContentType::VPack);
// enter the database name (ensure the user has access)
request->header.database = ?;
// API endpoint to submit AQL queries
request->header.path = "/_api/cursor";
// Create a payload to be submitted to the API endpoint
VPackBuilder builder;
builder.openObject();
// here is your query
builder.add("query", VPackValue("for col in collections() return col.name"));
builder.close();
// add the payload to the request
request->addVPack(builder.slice());
// send the request (blocking)
std::unique_ptr<Response> response = conn->sendRequest(std::move(request));
// check the response code - it should be 201
unsigned int statusCode = response->statusCode();
// slice has the response data
VPackSlice slice = response->slices().front();
std::cout << slice.get("result").toJson() << std::endl;

GET request with body timing out with URLSession and Alamofire

I'm working with a slightly unconventional API that is expecting a JSON body with a GET request and I have no control over this. Unfortunately, every time I attempt to make the request, it seems to completely disappear and never make it to the API. I originally wrote the request using a standard URLSession and then switched to try Alamofire in an attempt to fix it but ended with the same result. My request looks like this:
Alamofire.request("http://192.168.1.1:8000/connect/", method: .get, parameters: ["test": "test"], encoding: JSONEncoding.default)
.responseJSON { response in
let body = response.request?.httpBody
guard response.result.isSuccess else {
onCompletion(nil)
return
}
onCompletion(response.result.value as! [String : Any]?)
}
This exact code works for a different request where there is no JSON in the body, but seemingly the moment I add it, it just times out. This has already been discussed on the alamofire github repo (https://github.com/Alamofire/Alamofire/issues/1819) but the final comment with what should be working code isn't really any different to mine, so doesn't provide any help, nor do the other linked issues.
Printing the request with debugPrint gives me this curl command
$ curl -i \
-H "Content-Type: application/json" \
-d "{\"test\":\"test\"}" \
"http://192.168.1.1:8000/connect/"
Which is missing the -X GET flag, but when I add that in, the request works as expected and the server responds, so I know the API itself is working and is happy processing the JSON in the body, so I'm at a loss as to what's going on.
I've installed Timberjack to attempt to trace things, which didn't give me any more info at all, just what I already knew
Request: GET http://192.168.1.1:8000/connect/
Headers: [
Content-Type : application/json
Content-Length : 24
]
Although I'm not sure if it's supposed to be showing me the body as well which it isn't?
In both cases (URLSession and Alamofire) the request gives the following output which I don't see at any other time:
2017-01-22 23:31:09.797453 my-app[3755:1349066] [] nw_endpoint_flow_service_writes [2 192.168.1.1:8000 ready socket-flow (satisfied)] Write request has 4294967295 frame count, 0 byte count
2017-01-22 23:32:04.484182 my-app[3755:1349066] [] __tcp_connection_write_eof_block_invoke Write close callback received error: [89] Operation canceled
Anyone have any ideas on what's going on as I'm completely at a loss at this point.
Update
I've done some more digging. If I change the endpoint to https://httpbin.org/get then the request goes through just fine and I get a response. Whilst this kind of suggests the API server is refusing to process the request, it's still working with the cURL command so that can't really be the issue.
I also forgot to mention (although not sure it should make a difference) that the API I'm trying to communicate with is connected via an ad-hoc wifi. Other requests to it work just fine though so I can definitely communicate with it.
Update 2
So I've been able to switch the server to using POST instead of GET and unsurprisingly it now works, however I would still love to know of a solution to the original problem
URLSession and CFHTTPMessage cannot send a message body for a GET request. They send the content length for the body, but do not send the body itself. This results in a timeout.
In order to resolve this issue I've used libcurl to handle the GET requests which have a message body to my project. I use URLSession everywhere else. When you add a body to a request using libcurl it changes the request to a POST, but that can be changed back to a GET after setting the body and before submitting the request.

Facebook Messenger bot error: The parameter recipient is required

the bash command I used to connect the bot is: curl -ik -X POST 'https://graph.facebook.com/v2.6/me/messages?access_token=#AccessToken'
My error message is:
{"error":{"message":"(#100) The parameter recipient is
required","type":"OAuthException","code":100,"fbtrace_id":"EFqWAGq2ABs"}}
Do anyone how to solve it ?
Just in case anyone missed this, I encountered this issue when I accidentally use the wrong content type - I was using application/x-www-form-urlencoded instead of application/json
So my advise overall is,
Check if you are indeed passing the parameter
Double check the characters and encoding
Make sure to use the correct endpoint
and Make sure to use the correct content type when posting the JSON Request.
You need to send the recipient id param. Try:
curl -X POST -H "Content-Type: application/json" -d '{ "recipient":{"id":"YOUR RECIPIENT ID" }, "message":{ "text":"hello from bot" }}' "https://graph.facebook.com/v2.6/me/messages?access_token=YOUR_ACCESSTOKEN"
Best regards.
There is another reason for this error message: when you send incorrect characters (like a -tab-) Facebook return this error as well so check your return text on special chars.
Please use the "thread_settings" endpoint "https://graph.facebook.com/v2.6/me/thread_settings" as your API endpoint.
You are using the messages endpoint.
It comes down to the logic of your bot. I got this error as well just recently and it took me days to debug it. The problem for me was I called the callSendAPI(messageData) method outside of the function that compiled the messageData object.
Obviously, passing messageData outside of the function that compiles it sends an empty object instead of the compiled one. Thus the error message (#100) The parameter recipient is required. Simply because the empty object doesn't have any receipientId defined.
Please check your code's logic to ensure you didn't do the same mistake as I. Hope this helps :) Happy programming.
The endpoint is wrong. Instead of https://graph.facebook.com/v2.6/me/messages?access_token=#AccessToken, use this endpoint
https://graph.facebook.com/v2.6/me/messenger_profile?access_token=<PAGE_ACCESS_TOKEN>
This happens when we do not read the documentation., the info is right here https://developers.facebook.com/docs/messenger-platform/discovery/welcome-screen#,
right under the "Setting the Get Started Button Postback".
I got similar error some time back. Try using Postman. I tried the same request and replaced the user id and the page access token. It works fine.
Click on the Import button on the top and paste your curl request under raw. Then try running the call. If you get the same error, go to the body and modify it. Make sure you put this in the body part of the Postman request. Replace the recipient id with yours.
{
"recipient":
{
"id":"123456789"
},
"message":
{
"text":"hello, world!"
}
}
This is the full cURL call : Change Recipient ID and Page Access Token
curl -X POST -H "Content-Type: application/json" -d '{ "recipient":{"id":"1234567" }, "message":{ "text":"hello from bot" }}' "https://graph.facebook.com/v2.6/me/messages?access_token=PASTETHETOKENHERE"
This issue may also occur when you have an error in your code (syntax or logic error). In my case, I had this part in my code in webhook.php (which is my registered callback page in Facebook)
$message = $input['entry'][0]['messaging'][0]['message']['text'];
"message":{
"text":"Sorry, we currently do not have an article related to "'.$message.'"."
}
By the time I registered https://domain.com/webhook.php as callback, it wouldn't receive any $message yet so it causes an error and wouldn't accept my callback url.
Check your code and make sure you echo only the challenge.
$challenge = $_REQUEST['hub_challenge'];
$verify_token = $_REQUEST['hub_verify_token'];
if ($verify_token === 'verify_token') {
echo $challenge;
}

Trying to communicate with a REST service with NSIS

All I am trying to do is send an HTTP GET with Querystring or HTTP POST to a web service from within a custom page in an NSIS installer.
The problem is that most plugins can upload/download files, but not simply call a service and return the response. The recommend plugin to use is NsisUrlLib. I tried this, and while it works with simple GET requests, it fails and throws an error if you have querystring parameters in the URL, such as:
NsisUrlLib::UrlOpen /NOUNLOAD "http://tc.hwidev.com?var=value"
Pop $connectResult
NSISdl,INetC, and other plugins work with querystrings but can only be used to upload/download files.
I tried using the ExecDos plugin to call cURL.exe from the command line like so:
ExecDos::exec /TOSTACK "curl" "http://tc.hwidev.com"
Pop $connectResult
But I can't figure out how to get the data returned from the URL passed back to NSIS. The above code just returns an integer into $connectResult which probably represents the return code from CURL. How do I get the actual HTML returned from the URL onto the NSIS stack or into a variable?
Alternatively, can anyone recommend a better way to accomplish this? Calling a webservice seems so basic that thousands of people should have already figured this out.
NSISdl, Inetc etc, aren't just for uploading/downloading files. I think you are misunderstanding this point. You can use them to call REST apis, but you'll need to save the answer to a local file, and then parse it.
Example: Calling to an REST api that answers XML:
# Call to REST API
NSISdl::download_quiet "http://remotesite?restparams" "$TEMP/result.xml"
# Parse answer
nsisXML::create
nsisXML::load "$TEMP/result.xml"
nsisXML::select "/response/status"
# Clean
delete "$TEMP/result.xml"
That's it.
NSISdl::download_quiet "http://127.0.0.1/vid.php?vid=1" "$TEMP/checkvid.txt"
FileOpen $0 $TEMP\checkvid.txt r
FileRead $0 $1
DetailPrint $1
FileClose $0
${If} $1 == "vidNTYE1203"
MessageBox MB_OK "video found"
Delete "$TEMP\checkvid.txt"
${Else}
MessageBox MB_OK "bye bye"
Delete "$TEMP\checkvid.txt"
Quit
${EndIf}
This is my work snippet for production.Working good,for me.Pay attention for 'Delete' command and '\' slash .
I would recommend INetC over NsisUrlLib, the older firefox installer used it with much success.