How can i unescape this query string - ruby-on-rails

I am sending this request to a service:
get_store_data = Typhoeus::Request.new("http://localhost:3000/api/v1/store?service=#{(proxy_ticket.service)}&ticket=#{proxy_ticket.ticket}")
proxy_ticket.service resolves to this string "http://localhost:3000/api/v1/store". When the request is sent, This string is escaped to this:
service=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fv1%2Fstore
The problem is that the service on the other end expects the service parameter as "http://localhost:3000/api/v1/store" how can i prevent this query string from being escaped?

The other side should be unescaping the params. If you would still like to know how to do it however here is the method uri.unescape which is used like so:
require 'uri'
enc_uri = URI.escape("http://example.com/?a=\11\15")
p enc_uri
# => "http://example.com/?a=%09%0D"
p URI.unescape(enc_uri)
# => "http://example.com/?a=\t\r"
If you ever want to quickly unescape a uri (and don't want to open a repl for some strange reason or other, like maybe it insulted your honour or something.) you can try this site

You can't. Its the 'other side' who should decode this param (and most likely they do).
For example rails do this encoding automatically. You can check it by altering some of your actions to raise params.pretty_inspect and invoke it with extra param your/action/route?service=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fv1%2Fstore. You will see that params include service: http://localhost:3000/api/v1/store.
If this is not working for you this mine that you need to get in touch with the other side so they implement this. There is no other way to pass urls within get urls.

Related

How to send an array with a POST request, with a parameter name for the array that contains an empty set of square brackets []?

So, Rails normally handles parsing of incoming Arrays sent via HTTP Post requests (forms), like this:
"Normally Rails ignores duplicate parameter names. If the parameter
name contains an empty set of square brackets [] then they will be
accumulated in an array." - Rails Guides
But when using Net::HTTP.Post to send a Post request to a third party service (API), then it seems this convention of handling arrays in HTTP Post requests is not followed.
This code:
data = {:categories => [one, two, three]}
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.set_form_data(data)
response = http.request(request)
Then set_form_data will serialize the Array like this:
categories=one&categories=two&categories=three
And not like this (which I thought was the conventional Rails way):
categories[]=one&categories[]=two&categories[]=three
Why?
I can see that it has to do with the recent implementation of the URI.encode_www_form method that set_form_data uses. But what is the purpose deviating from the conventional Rails way?
And, more importantly, how do I easily modify this to send it in the latter way (without overloading a bunch of inherent Ruby/Rails methods)?
I found out that the solution was as easy as changing the table name:
data = {'categories[]' => [one, two, three]}
It even works if other elements of the data hash are :symbols.
I'd still be curious to find out why Rails makes this "hack" necessary when using the Net::HTTPHeader::set_form_data method, to get Rails' otherwise conventional way of handling arrays in the url parameters.

There is a common practice to reject "malicious" user-input to a rails application

I am using Ruby on Rails 3.1.0 and I would like to know what is a common practice to prevent to store "malicious" values in the database.
For example, I have a database table column means to store URLs. A user, passing the validation (just a length check), can submit a URL like http://<script>alert('hello!');</script>. I would like to do not permit to store links like the above... how can I make that?
The proper thing to do is use URI to parse the supposed URL and then check each component:
validate :url_check
def url_check
u = URI.parse(self.url)
# check u.scheme, u.userinfo, etc. and call errors.add(:url, '...')
# if something is invalid.
rescue URI::InvalidURIError
errors.add(:url, 'You are being naughty.')
end
While those links are in the database, they do no harm. Problems might occur when you try to render them. Rails does a good job in escaping most things that you output (I didn't dare to say "everything", 'cause I don't know for sure).
You can be extra sure and escape a string yourself:
CGI.escape your_link_url
Link: CGI.escape
You can use regex to validate it's a valid url without the '<', '>' url. And HTML encode it where it applies.

Escape URL in rails

I have a commenting system where people can leave a comment together with their website. Since rails now escapes everything by default I don't really do anything to avoid XSS and it works find - almost. For some reason the URL isn't escaped.
In order to display the username I have a simple helper:
def display_name(name, site)
if !site.blank?
return link_to(name, site)
else
return name
end
end
But if you put something like javascript:alert(1) into the website field it get injected directly into the page - any idea how to escape this?
Even if you escape javascript, malicous users could still create URLs which point to, say, delete urls that could potentially affect a user's data. Why not verify the URL as such when you collect it?
validates :attribute, :url => true
I'd recommend using Thong Kuah's UrlValidator.

Get raw params rather than the "processed into hashes" versions

Rails 3 question.
If i send a request like this PUT http://myapp/posts/123?post[title]=hello
then in my controller i get params = {:id => 123, :post => {:title => "hello"}}
This is fine normally and usually useful for eg Post.create(params[:post])
However, on this occasion i need to get access to the 'raw' form of the params so i can order them pull out the values, dealing with them all as simple strings, ie i want them listed so the param name is "post[title]" and the param value is "hello".
Is there any way i get get these values? I thought there might be a method of request that has the params in their original stringy form but i can't find one.
It had occurred to me to try to convert the hash back into a string with to_param but this seems a but dirty and possibly unecessary.
As a bonus, i'd like it to ignore the :id parameter, literally just taking the part after the ? in the original request. In fact, if i can just get back the original request string, ie "http://myapp/posts/123?post[title]=hello" then that would do: i could split on the ? and take it from there. It just occurred to me that i can probably get it out of a header. In the meantime though, if anyone knows a nicer way then tell me please :)
Grateful for any advice - max
Don't do the parsing by hand, please. Grab the URI from the Rails request:
url = request.url
# Or, depending on the Rails version and stack
url = request.request_uri
# Or even
url = request.scheme + '://' + request.host_with_port + request.fullpath
The return value from request.url seems to depend on your server stack, request.request_uri is supposed to fix that but doesn't seem to exist in Rails 3.1. The third "build it all yourself" approach should produce consistent results everywhere. Sigh.
Then, once you have the URI, use URI.parse and URI.decode_www_form to parse it:
u = URI.parse(url)
q = URI.decode_www_form(u.query)
# if u.query was "a=b&c=d&a=x" then q is
# [["a", "b"], ["c", "d"], ["a", "x"]]
Request#body and Request#uri should help you. You can get the "raw" request data, but not some intermediate form... though it's not that hard to just split at the ampersands and then again at the "=" if you want key-value pairs ;)

Append query string to request.request_uri without knowing if there was a query string

When a user arrives to my site on an iPhone I want to present them with a page with 2 options:
1) Go get our app or
2) Continue on to the requested URL
I do this by checking the user agent in my application controller and rendering a view.
For option 2 to work properly on that view I want the link to preserve the original URL and append a query string parameter fullsite=1. I look for that query string parameter param in a before_filter in my application controller and set a cookie so that the user is not prompted again.
What is the cleanest way to append a query string parameter to a request.request_uri knowing that that request url may or may not have had a query string to start with? I know it is straight forward to check if the request had parameters but I'm wondering if there is a helper to append a parameter cleanly in either case (no params or with existing params) without evaluating things on my own. Seeking the correct "railsy" way to do this.
Probably the best way to do this is to add your flag to the params hash, which will already have all the other information you need to build that link (presuming you catch iPhones and render in a before_filter), and then build your link from the modified params hash:
In your before_filter:
params[:fullsite] = 1
And then in your view:
<%= link_to('Continue to the Full Site', params) %>
This way Rails gets to do all the messy work of escaping and appending your query strings - both :fullsite and whatever the original query string contained.
If you're just using :fullsite as a way to avoid redirecting iPhones through your iPhone portal multiple times, though, it seems like either of these approaches would work better:
Set :fulltext in the session instead, or
Only redirect users if they're on iPhones AND request.referer is something other than your site.
Hope this helps!

Resources