sinatra routes first path param is a number - ruby

I want to be able to match a route that looks something like
/2/monkey/session
I have the following in sinatra but
/:version_number/:name/session
And I keep getting the Sinatra doesn’t know this ditty. Anyone knows a way to getting this to work so that I can have params[:version_number] and params[:name] matched.

I wrote the code below (Ruby 2.0.0 / Sinatra 1.4.3).
require "sinatra"
get "/:version_number/:name/session" do
params.inspect
end
The response seems like correctly.
{"splat"=>[], "captures"=>["2", "monkey"], "version_number"=>"2", "name"=>"monkey"}
Why don't you check HTTP method or comment out other code?

Related

Ruby Sinatra - Range Error with large-ish json payload in post request

I am building a small Sinatra API that will run some calculations and store results on the server. The POST route requires a JSON payload. The JSON payload is a combination of floats, arrays of floats and base64 encoded data.
This is the route
post '/calc' do
rad_data = JSON.parse(request.body.read)
# Perform calculations
end
Everything works fine when the json is around 2.8MB, but when the size gets to 3.9MB I receive the error
2021-11-20 17:33:43 +0000 Rack app ("POST /calc" - (78.110.164.58)): #<RangeError: RangeError>
(It is also weird that 78.110.164.58 is not the ip address of the machine and i have no idea where it comes from.)
The structure of the payload is exactly the same. The larger one has simply longer arrays. Also, if I load the file directly on the server everything works, so it is not a problem with the json content.
Based on this answer I have added the key_space_limit to the beginning of the app, but it makes no difference.
require 'sinatra'
require 'sinatra/reloader'
require 'rack'
if Rack::Utils.respond_to?("key_space_limit=")
puts "Yes"
Rack::Utils.key_space_limit = 2**64
end
Just in case it helps, I send my request with Ruby rest-client
RestClient.post(uri_post, JSON.dump(rad_data))

Custom Sinatra route

I'm looking to make a custom route for my Sinatra blog project which shows the user the last entered post in the database.
get "/most-recent-job" do
Job.last
Can anyone help? I can't find info in my curriculum for such a request.
The Sinatra documentation on routes is pretty thorough. Assuming you're just trying to call a class method of Jobs::last, and that the method returns something stringifyable, then:
get '/most-recent-job' do
Jobs.last
end
should get it done. If that's insufficient for your use case, you'll have to expand your question to include code and output showing what Jobs.last is supposed to return, whatever errors you're getting from the route currently, and what you think the route's output ought to look like if you're expecting a MIME type other than text/plain.

how to get sinatra route_path like in grape

I want to report stats for my routes.
To do that, I have to know what they are
I am using ruby's sinatra
so I have
get '/test/:username' do
....
end
after do
request.path_info
end
But I get '/test/test_username123' as an output
Is there a variable (like grape route.route_path) that will enable me to get the route?
Edit: Grape's route.route_path will output "/api/:version/test/:username(.:format)"

Local variables in a block that are not passed as parameters [duplicate]

This question already has answers here:
Rails params explained?
(5 answers)
Closed 9 years ago.
I'm trying to understand how to make a variable available to a block that is not passed to the block as a parameter.
For example, how does Sinatra make params hash available?
get '/hello/:name' do
howAmIAccessingThis = params[:name]
end
Where is params coming from? This:
get '/hello/:name' do |params|
#hisName = params[:name]
end
might make sense because params is declared as a block argument, but that's not how it works. Looking through the source I cannot find how the params hash is getting passed to the block without it being a block parameter.
If it is not a local variable or a block variable, then it is a method. I don't know about Sinatra, but there must be a method params defined somewhere.
Using Parameters
Parameters in Sinatra are like everything else--simple and straightforward.
#!/usr/bin/env ruby
require 'rubygems'
require 'sinatra'
get '/hello/:name' do
"Hello #{params[:name]}!"
end
Once you've made this change, you'll need to restart the Sinatra application. Kill it with Ctrl-C and run it again. (There's a way around this, but we'll look at that in a future article.) Now, the parameters are straightforward. We've made an action called /hello/:name. This syntax is imitating what the URLs will look like, so go to http://localhost:4567/hello/Your Name to see it in action.
The /hello portion matches that portion of the URL from the request you made, and :name will absorb any other text you give it and put it in the params hash under the key :name. Parameters are just that easy. There is of course much more you can do with these, including regexp-based parameters, but this is all you'll need in almost every case.
Reference: http://ruby.about.com/od/sinatra/a/sinatra2.htm
EDIT
params values can come from the query string of a GET request, or the form data of a POST request, but there's also a third place they can come from: The path of the URL.
As you might know, Rails uses something called routes to direct requests to their corresponding controller actions. These routes may contain segments that are extracted from the URL and put into params. For example, if you have a route like this:
match 'products/:id', ...
Then a request to a URL like http://example.com/products/42 will set params[:id] to 42
So, whenever an URL GET, POST or Path contains such pattern then params hash is automatically constructed by rails.
Also check the Parameters section(Section 4) here

Handling 405's in Sinatra

In Sinatra if I create a simple endpoint such as:
post '/users' do
'posted'
end
curl -v -X GET http://localhost:8080/users returns a 404, when I would expect a 405.
I've looked through the documentation but not found anything. Before digging through the source code, does anyone know how to handle and return 405's in Sinatra? Sort of like the not found method:
not_found do
'Not found - ' + request.path
end
You got an 404 because sinatra can't find a get route /users. If you want return a custom error you may look at Halt
throw a error
The you can return a 405 on get /users like this:
get "/users" do
halt 405
end
For catch multiple http verbs at once you can use multi route
require 'sinatra'
require "sinatra/multi_route"
route :get, :post, '/foo' do
# "GET" or "POST"
p request.env["REQUEST_METHOD"]
end
# Or for module-style applications
class MyApp < Sinatra::Base
register Sinatra::MultiRoute
route :get, :post, '/foo' do
# ...
end
end
source
handle errors
If you want handle error codes in sinatra you can simple do for 404 errors:
not_found do
'This is nowhere to be found.'
end
In your case handle a 405 error:
error 405 do
'Access forbidden'
end
Looks like it's not possible without repeating yourself a lot. From looking through the Sinatra source code, the hash of routes has the verb as the key: https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L1513
It then looks up a route using that verb:
https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb#L943
Which is not ideal and I would consider a weakness/bug in the framework as throwing a 405 when a verb isn't allowed is standard HTTP Spec.
I'll maybe raise an issue see what the contributors say. Ideally it would store routes by their url first, and then check the appropriate verb can be executed for a given url. This would make handling something as standard as a 405, much easier.
In fact I found an issue raised on github for the above:
https://github.com/sinatra/sinatra/issues/24
As mentioned nearer the bottom, it's not currently handled and something they may work on for v2.0

Resources