question marks in sinatra get method - ruby

I am trying to use a question mark in one of my url's but sinatra/ruby is interpreting it as the regex character that makes precedings optional. Is there any way to allow actual ? in your get methods? I have tried \? and [?] but they didn't work. Here is the begining of my get method:
get '/group?groupid=:groupId' do |id|
If I go to www.mydomain.com/group?groupid=1 I get an error but it works if I go to www.mydomain.com/groupgroupid=1

The "?" starts the querystring portion of the URL; querystring parameters are accessible via the "params" Hash.

Related

Ruby on Sinatra: Imitate a request based on a parameter

I am currently developing a Ruby API based on Sinatra. This API mostly receives GET requests from an existing social platform which supports external API integration.
The social platform fires off GET requests in the following format (only relevant parameters shown):
GET /{command}
Parameters: command and text
Where text is a string that the user has entered.
In my case, params[:text] is in fact a series of commands, delimited by a space. What I want to achieve is, for example: If params[:text]="corporate finance"
Then I want my API to interpret the request as a GET request to
/{command}/corporate/finance
instead of requesting /{command} with a string as a parameter containing the rest of the request.
Can this be achieved on my side? Nothing can be changed in terms of the initial request from the social platform.
EDIT: I think a better way of explaining what I am trying to achieve is the following:
GET /list?text=corporate finance
Should hit the same endpoint/route as
GET /list/corporate/finance
This must not affect the initial GET request from the social platform as it expects a response containing text to display to the user. Is there a neat, best practice way of doing this?
get "/" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
end
might do the trick. Didn't check though.
EDIT: ok, the before filter was stupid. Basically you could also route to "/" and then redirect. Or, even better:
get "/:command" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
}
There a many possible ways of achieving this. You should check the routes section of the sinatra docs (https://github.com/sinatra/sinatra)
The answer by three should do the trick, and to get around the fact that the filter will be invoked with every request, a conditional like this should do:
before do
if params[:text]
sub_commands = params[:text].split.join "/"
redirect "#{params[:command]}/#{sub_commands}"
end
end
I have tested it in a demo application and it seems to work fine.
The solution was to use the call! method.
I used a regular expression to intercept calls which match /something with no further parameters (i.e. /something/something else). I think this step can be done more elegantly.
From there, I split up my commands:
get %r{^\/\w+$} do
params[:text] ? sub_commands="/"+params[:text].split.join("/") : sub_commands=""
status, headers, body = call! env.merge("PATH_INFO" => "/#{params[:command]}#{sub_commands}")
[status, headers, body]
end
This achieves exactly what I needed, as it activates the correct endpoint, as if the URL was typed it the usual format i.e. /command/subcommand1/subcommand2 etc.
Sorry, I completely misunderstood your question, so I replace my answer with this:
require 'sinatra'
get '/list/?*' do
"yep"
end
like this, the following routes all lead to the same
You need to add a routine for each command or replace the command with a * and depend your output based on a case when.
The params entered by the user can be referred by the params hash.
http://localhost:4567/list
http://localhost:4567/list/corporate/finance
http://localhost:4567/list?text=corporate/finance

WebApi Send String with # in it

I am sending a string to a Post method in WebApi. The string contains a # character. When the Post method receives it, the string is received without the # character and everything after it.
So if the string I send is
abc#def
The Post method actually receives
abc
What's wrong here?
As this parameter is passed in the URI, anything after the # is ignored. This is standard web behaviour. You simply cannot do this sorry.
One thing you could do is take it in via the request body instead, that would work fine.
A similar question addresses the same issue here, although it's more to do with routing, but the same concept applies.

No implicit conversion of Array into String?

I have a Sinatra application with the following GET method that takes the URL passed in:
get %r{/html/(.+)} do
url = params[:captures] # stores url => http://www.example.com
gethtml(url)
end
However, when gethtml(url) is called, it raises the error Sinatra no implicit conversion of Array into String.
gethtml accepts input such as http://example.com.
I know this is a data-type conversion issue and I tried calling to_s but it did not work.
Any help would be appreciated.
params[:captures] returns an array of strings, while get_html most likely accepts one URL as string.
Since you want to use the first group that matches as the URL:
get %r|/html/(.+)| do
get_html params[:captures].first
end
This is consistent with the Route matching with Regular Expressions example in the Routes section of the README.

How to pass a URL in params?

I have a url, "localhost/test/http://myimage.com/" (I'm passing myimage.com, because it's hosted on another site and I'm accessing it via an api) my question is how do I go about encoding the image portion of the URL? I thought about doing a gsub on the '.' and '/' and then gsubing them back, but I'm wondering if there's an easier way. Thanks for your help.
You could use URI::encode_www_form_component(str) and URI::decode_www_form_component
Check: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/uri/rdoc/URI.html
You can use the uri library to escape and unescape a url
require 'uri'
escaped = URI.escape(data, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
and you can get the data back with
original = URI.unescape(escaped)

Problem with `&` in Net::HTTP::Get.new

I'm using net/http in Ruby to send a GET request to a web service. The important bit of code is the following:
Net::HTTP.start("www.thehost.com") do |http|
req = Net::HTTP::Get.new("/api" + ROUTES[sym] + "?" + params)
resp = http.request req
end
params is a string which contains key-value pairs in the form key=val&blag=blorg. When the response comes in, it turns out to be an error page from the server, which quotes the request URI; instead of key=val&blag=blorg, it has key=val&blag=blorg. Since when I enter the same address into a web browser with & instead of &, I get the expected response, I suspect that the escaping of & is what's causing the problem. If anyone with more experience disagrees with that, however, feel free to rename my question!
I should note that when I use http://www.thehost.com/api#{ROUTES[sym]}?#{params} with Net::HTTP.get_response, I get the expected response. What can I do to fix this?
Just a wild guess: are you doing this in Rails, and could its XSS protection/HTML escaping features be the culprit? What happens if you change it to params.html_safe?
Since using #{...} in one case works, what happens if you do "/api#{ROUTES[sym]}?#{params}" instead of concatenating strings with +?

Resources