reading parameters on Sinatra post - ruby

I'm working on my first Sinatra app and I have an hard time getting parameters from a post request.
I'm using MiniTest::Spec and my spec looks like
payload = File.read("./spec/support/fixtures/payload.json")
post "/api/v1/verify_payload", { payload: payload }, { "CONTENT_TYPE" => "application/json" }
last_response.body.must_eql payload
And this is my route
namespace '/api/v1' do
post '/verify_payload' do
MultiJson.load(params[:payload])
end
end
The spec fails because last_response.body is empty.
Am I missing something here?
I also tried to return the entire params from verify_payload but also in that case it returned an empty string.
Update
curl -X POST -H "Content-Type: application/json" -d '{"payload":"xyz"}' http://localhost:9292/api/v1/verify_payload
does not return anything and no error on the server log
[2014-01-06 01:16:25] INFO WEBrick::HTTPServer#start: pid=10449 port=9292
127.0.0.1 - - [06/Jan/2014 01:16:27] "POST /api/v1/verify_payload HTTP/1.1" 200 6 0.0220
Thanks

Sinatra just doesn't parse this data, because they are not form parameters.
Form parameter would look like this
curl -X POST 127.1:4567/ -d "foo=bar"
Instead of params you can just use request.body.read or use rack contrib.
rack-contrib
Install it with gem install rack-contrib
require it
require 'rack'
require 'rack/contrib'
load it use Rack::PostBodyContentTypeParser
with this you can use params as normal for json post data. Something like this:
curl -X POST -H "Content-Type: application/json" -d '{"payload":"xyz"}' 127.1:4567/
source for this: Sinatra controller params method coming in empty on JSON post request, http://jaywiggins.com/2010/03/using-rack-middleware-to-parse-json/

Related

Laravel Form Validation Inconsistency

Laravel Version: 9.42.0
PHP Version: 8.1.13
Database Driver & Version:
Description:
Before laravel 9 update, form rules were working as I wanted. It started behaving differently after the update.
While the same code and the same request occur without an error in laravel 8, error code 422 is returned in laravel 9.
Steps To Reproduce:
Route::post('test', function (\Illuminate\Http\Request $request) {
$request->validate([
'type' => [
'bail',
'exclude_if:type,',
'in:individual,corporate',
],
'name' => [
'bail',
'exclude_if:type,',
'required_with:type',
'min:3',
'max:49',
],
'id' => [
'bail',
'exclude_if:type,',
'required_with:type',
'digits:10',
],
'tax_office' => [
'bail',
'exclude_unless:type,corporate',
'required_if:type,corporate',
'min:2',
'max:99',
],
], $request->all());
});
Request:
curl --location --request POST 'https://site.dev/api/test' \
--header 'Accept: application/json' \
--header 'X-Requested-With: XMLHttpRequest' \
--header 'Content-Type: application/json;charset=UTF-8' \
--form 'type=""' \
--form 'name=""' \
--form 'id=""' \
--form 'tax_office=""'
Laravel 8.21.0 response status code: 200
Laravel 9.42.0 response status code: 422
Error code 422 with validation in Laravel means the request didn't pass the validation. You would have to debug it further to see which field in the payload is causing the issue by inspecting response errors.
If you got code 200 in a previous version, either you are providing it with different payload which was valid, or something changed between the two versions with the types of rules you are using.
If I had to guess I would say the problem is with the payload data you are providing, and likely before when you got code 200, you were testing with different payload or alternatively maybe you weren't using CURL to test before but instead through the browser.
You can check here to see if any of these upgrades may have had an impact: https://laravel.com/docs/9.x/upgrade
Laravel sends HTTP 422 upon a validation failure ... but, which field failed validation? And, what was the message? (check the response body).
HTTP 200 means the request succeeded — since you don't specify a return or return response() in your controller, HTTP 200 is the default response.
Your usage of 'exclude_if + required_with' seems a bit weird ... perhaps in Laravel updated the logic to fix a bug? (You might try just using required vs required_with).
I'd also try loading that request (import the CURL) into some IDE to help with debugging — Postman How to import

playframework - Can't read cookie from request

How can I get the cookie from a request in playframework?
I have the following test endpoint
def home = Action.async { implicit request =>
println(request)
println(request.session)
println(request.flash)
request.session.get("session") match {
case Some(cookie) => Future(Ok(cookie))
case None =>
Future(BadRequest(Json.obj("message" -> "missing session cookie")))
}
}
When submitting the following request:
curl 'http://local.example.com:9000/home' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' --compressed -H 'Connection: keep-alive' -H 'Cookie: session=eyJhbGciOiJSUzI1NiIsImtpZCI...' -H 'Upgrade-Insecure-Requests: 1' -H 'Cache-Control: max-age=0'
I unfortunately get the "missing session cookie" response. and the following printout on the console
GET /home
Session(Map())
Flash(Map())
I don't know what I'm doing wrong. Any help is much appreciated.
Edit: I set the cookie using the following method:
def tokenLogin = Action(parse.json).async { implicit request =>
val loginRequest = request.body.validate[LoginRequest]
loginRequest.fold(
errors =>
{
println(errors)
Future(BadRequest(Json.obj("message" -> JsError.toJson(errors))))
},
request => {
println("in success")
firebaseAdminService
.createSessionCookie(request.idToken)
.map(sessionCookie =>
Ok("success")
.withNewSession
.withCookies(Cookie(name = "session", value = sessionCookie))
)
}
)
}
By default, the session cookie in Play is called "PLAY_SESSION" (configuration play.http.session.cookieName).
So, you would need to use -H "Cookie: PLAY_SESSION=..." with curl.
But note, this won't work with arbitrary data since Play uses JWT and signs the information contained in the session cookie using its crypto secret.
The only thing expected to work is using a session cookie received in a Set-Cookie header from your Play service in another request to the same service (having the same secret).
update after your edit:
When using request.session, you are accessing the session cookie, which is called PLAY_SESSION and the information stored inside it.
But, you are setting a cookie of your own. This is something else.
You can access "normal" cookies with
request.cookies.get("session")
Oh, and in case you really wanted to make use of the session cookie, you can set it like this:
Ok("success").withSession("session" -> sessionCookie)

Send custom URL in telegram button bash

I wrote this code with bash for send Messages with telegram bot, now i need send the Message with a custom URL.
This is my actual code:
sendTelegram() {
curl -s \
-X POST \
https://api.telegram.org/bot$apiToken/sendMessage \
-d text="$download" \
-d chat_id=$userChatId
}
How to I can send the Message $download in a URL Button, for example:
You need to use an inline_keyboard from reply_markup and send a POST request with a JSON content type header:
curl -d '{"chat_id":7455490, "text":"pruebax", "reply_markup": {"inline_keyboard": [[{"text":"LaResistencia.co", "url": "http://laresistencia.co"}]]} }' -H "Content-Type: application/json" -X POST https://api.telegram.org/bot$apiToken/sendMessage
Check the Telegram bot API inline_keyboard section for more info about the parameters:
https://core.telegram.org/bots/api#inlinekeyboardbutton
Please use reply_markup like this payload.

unable to make api request with http ruby gem

I am trying to translate a curl request that works in the terminal for me into ruby code using the http gem.
This is the curl request that gives me back the valid json I want:
curl -X GET --header 'Accept: application/json' --header 'api_key: somekey' --header 'authtoken: sometoken' 'https://cdn.domain.io/v3/content_types/shirts/entries?environment=dev'
With the http gem I try to do this in my ruby script:
HTTP.headers(:Accept => "application/json", :api_key => 'somekey', :authtoken => 'sometoken').get("https://cdn.domain.io/v3/content_types/shirts/entries", :params => { :environment => 'dev'}).body.readpartial
And this gives my back "api_key":["is not valid."]} error from the server
What am I doing wrong? How do I get this to work?
Typhoeus seems to be working out well:
require "typhoeus"
require 'multi_json'
require "awesome_print"
response = Typhoeus::Request.new(
"https://api.domain.io/v3/content_types/shirts/entries?environment=dev",
headers: { api_key: "somekey", access_token: "sometoken",
accept_encoding: "gzip" }
).run
# puts response.body
begin
ap MultiJson.load(response.body, :symbolize_keys => true)
rescue MultiJson::ParseError => exception
p exception.data # => "{invalid json}"
p exception.cause # => JSON::ParserError: 795: unexpected token at '{invalid json}'
end

parse.com cloud code GET function with parameters?

I'm writing a cloud code function in parse and I'm trying to figure out how to handle parameters in the GET url.
So I have a simple function like this:
Parse.Cloud.define("someFunction", function(request, response) {
// how can I use GET parameters here??
});
How to I rename the "someFunction" to handle GET parameters so I can use them in my cloud code function logic?
so for example I want to be able to pass in a name string: "myName" in the GET
https://api.parse.com/1/functions/someFunction?name=myName
Any simple example? I searched for a while I couldn't find one.
Thank you
EDIT:
So I modified my function to look like this:
Parse.Cloud.define("someFunction", function(request, response) {
// how can I use GET parameters here??
var name = request.params.name
response.success("the name = " + name)
});
then I call it like this:
https://api.parse.com/1/functions/someFunction?name=someName
what I get back is this:
{"result":"the name = **undefined**"}
Cloud Functions are called with a POST request, not a GET request. Here is a simple example for cURL I took from the documentation [1].
curl -X POST \
-H "X-Parse-Application-Id: YOUR_APP_ID" \
-H "X-Parse-REST-API-Key: YOUR_REST_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"John Doe"}' \
https://api.parse.com/1/functions/someFunction
[1] https://www.parse.com/docs/cloud_code_guide#functions
try calling the Cloud from JS layer...
Parse.initialize(appId, jsId);
p = Parse.Cloud.run('someFunc', {"name":refToName}).then(function(result) {

Resources