How to send json using faraday - ruby

I need to consume the linode api, in the description it says I have to send the data using curl like this
curl -H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-X POST -d '{
"label": "asdfasdf"
"ssh_key": "asdfasdf"
}' \
https://api.linode.com/v4/profile/sshkeys
I tried using
http = Faraday::Connection.new 'https://api.linode.com/v4/profile/sshkeys'
http.authorization :Bearer, token
http.post('', { 'label' => 'adfadf', ..}.to_json)
But every request it says label and ssh_key required. I donĀ“t know how to send this particular request
anyone?

You need to specify the content-type as json in the header, if you're sending a json data.
http.post(
'',
{ 'label' => 'adfadf', ..}.to_json,
{ 'Content-Type' => 'application/json' }
)
Reference: https://lostisland.github.io/faraday/usage/

Related

Laravel API: validate doesn't access the PUT request data in my API

Context
I am implementing a user information update using a PUT request in Laravel 8. I use Postman to send the request and see the results.
Expected behavior
My PUT request reaches the controller's function that is censed to update the authenticated user. The latter is updated successfully. So the validate call is executed succesfully and finds the data in the request.
Actual behavior
My PUT request reaches the controller's function that is censed to update the authenticated user. The latter is not updated successfully. In fact, the validate call is executed succesfully but doesn't find the data in the request.
Instead, data validation says:
{
"message": "The given data was invalid.",
"errors": {
"email": [
"The email field is required."
],
"name": [
"The name field is required."
]
}
}
The route & The request
Postman request
curl --location --request PUT 'https://XYZ/api/set_user_data' \
--header 'X-Requested-With: XMLHttpRequest' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer 12|leRLA5yopCLIxe0oN9MMThctqD78iJDjZdZQkcgs' \
--data-urlencode 'email=XYZ#XYZ.FR' \
--data-urlencode 'name=test2'
It means in Postman terminology that no "Params" are sent, an Authorization Bearer token is sent, some Headers are sent and some Body's x-www-form-urlencoded data are sent.
API Route
In routes/api.php:
Route::put('/set_user_data', [UserController::class, 'setUserData'])->name('set_user_data');
UserController::setUserData:
public function setUserData(Request $request) {
if(!Auth::check()) {
return 'unauthenticated.';
}
$request->validate([
'email' => 'required|email',
'name' => 'required|string'
]);
// ... update user here but out of topic
}
What I tried to do... or to not do
Some Stackoverflow answers are: send a POST request and send in the body _method=PUT. I don't want to do this. I really prefer to send a PUT request. Because I am developing an API. It totally justifies the fact that I must use a PUT request and not a PUT one.
Some Stackoverflow answers are: use x-www-form-urlencoded not a simple form. It doesn't fix the problem; moreover it's already the case. Maybe it could help with images sending. (notice I don't want to send any image here).
Question
Why Laravel's validate don't find the data of my request and how to fix it?
You are sending the request as "Content-type: application/json", but you are not sending the body as valid JSON.
You are sending this:email=XYZ#XYZ.FR&name=test2
You should send this:
{"email":"XYZ#XYZ.FR", "name": "test2"}
a valid JSON object

How to pass form-data with rest-client

I am trying to translate a post request I send to a server with Postman to ruby RestClient.
In Postman, I send a (successful) POST request with a URL with params.
In my headers I have one parameter
Under Body I send more parameters under form-data. I tried adding these to the payload, which does not work:
I tried to translate it to the following call with rest-client
url = "https://..."
cookie = "..."
payload = {
payloadParam: "some param",
formDataParam: "form-data param"
}
headers = {
Cookie: cookie
}
Following their docs I then fired the following call:
data = RestClient.post(url, payload, headers)
So this doesn't pass the form-data params correctly. I have a feeling I am supposed to pass these parameters through something other than the payload, but I can't find any docs online explaining how. All I could find is a multipart example of loading an external file, but I don't have an external file.
How do I add form-data params to a POST request with Rest-Client?
My cURL structure looks like this:
curl -X POST \
'https://.../?payloadParam=xxxxxxxx' \
-H 'Accept: */*' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Cache-Control: no-cache' \
-H 'Connection: keep-alive' \
-H 'Content-Length: 55' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-H 'Cookie: xxxxxxxx' \
-H 'Host: xxxxxxxx.com' \
-H 'Postman-Token: xxxxxxxxxxxxxxx' \
-H 'User-Agent: PostmanRuntime/7.19.0' \
-H 'cache-control: no-cache' \
-d 'formDataParam=xxxxx&secondFormDataParam=yyyyy'

Ruby RestClient GET request with payload

Please help me with the following:
I have a number of application and associated records.
app with id 1 has: record1, record2 and record3.
app with id 2 has: record1 ... record1000
To filter out records for app 1 Im using curl. I can get records with the following command:
curl -i -H "accept: application/json" -H "Content-type: application/json" -X GET -d '{ "filters": { "app_id":"1" }}' http://[rails_host]/v1/records?token=[api_token]
How can I do the same but with ruby RestClient (gem 'rest-client' '1.7.2')
To get all records I do the following:
RestClient.get("http://[rails_host]/v1/records?token=[api_token]", { :content_type => 'application/json', :accept => 'application/json'})
The Problem is that app ids are not returned so I cannot parse response and take records that has app id = 1
Any ideas how can I add payload to Restclient.get to filter out records?
You can see in the docs here that the only high level helpers that accept a payload argument are POST, PATCH, and PUT. To make a GET request using a payload you will need to use RestClient::Request.execute
This would look like:
RestClient::Request.execute(
method: :get,
url: "http://[rails_host]/v1/records?token=[api_token]",
payload: '{ "filters": { "app_id":"1" } }',
headers: { content_type: 'application/json', accept: 'application/json'}
)

Sending a POST request with RestClient and Authentication headers

I have the following curl request that I would like to translate into a RestClient API request.
curl -H 'Content-Type: application/json' -H 'Accept: application/json' -H 'Authorization: Token user_token="tokenhere", email="email#myemail.com"' -X POST "https://api.myapi.io/reports?start_date=2016-05-10&end_date=2016-05-12" -v
I tried the following as a RestClient POST but I keep getting a 401. When I do the curl request I get a response.
url = "https://api.myapi.io/reports?start_date=2016-05-10&end_date=2016-05-12"
RestClient.post(url, :authorization => 'Token email="email#myemail.com" user_token="tokenhere"', :content_type => 'application/json', :accept => 'application/json')
Any ideas?
The string you're expecting is:
'Token user_token="tokenhere", email="email#myemail.com"'
The line you're sending is:
'Token email="email#myemail.com" user_token="tokenhere"'
The parameters are flipped around. :) If that doesn't work, I'd check and make sure that the curl request is expecting escaped characters. You could be effectively sending this:
"Token email=\"email#myemail.com\" user_token=\"tokenhere\""

Having problems translating a curl command to Ruby Net::HTTP

This is a call to a Usergrid-stack web app to create a new application:
curl -H "Authorization: Bearer <auth_token>" \
-H "Content-Type: application/json" \
-X POST -d '{ "name":"myapp" }' \
http://<node ip>:8080/management/orgs/<org_name>/apps
Here's my Ruby code:
uri = URI.parse("http://#{server.ipv4_address}:8080/management/orgs/#{form.org_name}/apps")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri, {'Authorization' => 'Bearer #{form.auth_token}', 'Content-Type' => 'application/json'})
request.set_form({"name" => form.app_name})
command.output.puts uri.request_uri
response = http.request(request)
Currently I'm getting this response from the server:
{\"error\":\"auth_unverified_oath\",\"timestamp\":1383613556291,\"duration\":0,\"exception\":\"org.usergrid.rest.exceptions.SecurityException\",\"error_description\":\"Unable to authenticate OAuth credentials\"}"
In this line--
request = Net::HTTP::Post.new(uri.request_uri, {'Authorization' => 'Bearer #{form.auth_token}', 'Content-Type' => 'application/json'})
Try changing that authorization string to "Bearer #{form.auth_token}"--with double quotes. String interpolation only works with double-quoted strings.

Resources