On Mar 18, 2010, at 9:00 PM, Adam Ziemba wrote:
Colin Law wrote:
open("http://chart.apis.google.com/chart#{CGI.escape('?
cht=bvg&chbh=a&chd=s:vttusty&chs=500x300&chxt=x,y&chxl=0:|Sun|Mon|
Tue|Wed|Thu|Fri|Sat|1:|0|2|4|6|8|10|12')}")
do |chart|
File.open('chart.png', 'w') {|f| f.write chart.read }
end
I definitely understand the why you would want to escape the URI, but
I'm not convinced that this approach will never work.
The URL with the escaped characters causes Google to reject it as
invalid parameters, which is why you got all that HTML and Javascript.
E.g. if you use your browser to open the result of the above URI with
escaped characters:
http://chart.apis.google.com/chart%3Fcht%3Dbvg%26chbh%3Da%26chd%3Ds%3Avttusty%26chs%3D500x300%26chxt%3Dx%2Cy%26chxl%3D0%3A%7CSun%7CMon%7CTue%7CWed%7CThu%7CFri%7CSat%7C1%3A%7C0%7C2%7C4%7C6%7C8%7C10%7C12
You are redirected to the Google chart API. Retaining the original
characters with:
http://chart.apis.google.com/chart?cht=bvg&chbh=a&chd=s:vttusty&chs=500x300&chxt=x,y&chxl=0
:|Sun|Mon|Tue|Wed|Thu|Fri|Sat|1:|0|2|4|6|8|10|12
you'll get a PNG image and nothing else.
Okay, so Google doesn't want the escaped characters, and the URI::open
method doesn't want the plain characters... or does it? Is there no
way
around this? The thing is the characters used in the URL above are
valid, or so I thought. I pass these kind of characters as parameters
from controller to view all throughout my application, with full
browser
compatibility.
I tried using backslashes for all the characters, e.g. "\&" instead of
"&" and the URI open method still rejects it.
I've seen some people successfully get images to save to the file
system
using URI, but I'm assuming all their code is outdated as I could not
get it to work. Also, the image URL they were using actually pointed
to
a PNG image, with a PNG extension, whereas the Google Chart URL will
return a PNG image.
I appreciate all the help!
You just need a URI that's technically valid, not just one that
browsers understand. URI.parse and thus open-uri is rather more strict
than the other tools suggested.
Here's an irb session that shows the right way to get a valid URI for
the chart you want.
$ irb -ruri -ropen-uri -rcgi
irb> orig = 'http://chart.apis.google.com/chart?cht=bvg&chbh=a&chd=s:vttusty&chs=500x300&chxt=x,y&chxl=0
:|Sun|Mon|Tue|Wed|Thu|Fri|Sat|1:|0|2|4|6|8|10|12'
=> "http://chart.apis.google.com/chart?cht=bvg&chbh=a&chd=s:vttusty&chs=500x300&chxt=x,y&chxl=0
:|Sun|Mon|Tue|Wed|Thu|Fri|Sat|1:|0|2|4|6|8|10|12"
irb> md = %r{(https?:)//((?i:[-a-z0-9.]+))(/[^?]+)\??(.*)}.match(orig)
=> #<MatchData:0x391070>
irb> scheme, host, path, query_string = md.captures
=> ["http:", "chart.apis.google.com", "/chart",
"cht=bvg&chbh=a&chd=s:vttusty&chs=500x300&chxt=x,y&chxl=0:|Sun|Mon|Tue|
Wed|Thu|Fri|Sat|1:|0|2|4|6|8|10|12"]
irb> query_string.split('&').map{|pair| pair.split('=')}
=> [["cht", "bvg"], ["chbh", "a"], ["chd", "s:vttusty"], ["chs",
"500x300"], ["chxt", "x,y"], ["chxl", "0:|Sun|Mon|Tue|Wed|Thu|Fri|Sat|
1:|0|2|4|6|8|10|12"]]
irb> u = URI.parse "#{scheme}//#{host}"
=> #<URI::HTTP:0x37cf44 URL:http://chart.apis.google.com>
irb> u.path = path
=> "/chart"
irb> u.query = query_string.split('&').map{|pair|
pair.split('=')}.map{|n,v| "#{n}=#{CGI.escape(v)}"}.join('&')
=> "cht=bvg&chbh=a&chd=s%3Avttusty&chs=500x300&chxt=x%2Cy&chxl=0%3A
%7CSun%7CMon%7CTue%7CWed%7CThu%7CFri%7CSat%7C1%3A
%7C0%7C2%7C4%7C6%7C8%7C10%7C12"
irb> open(u.to_s) do |chart|
?> File.open('chart.png', 'w') {|f| f.write chart.read }
irb> end
=> 5445
irb> File.exist?('chart.png')
=> true
Note that if you are building up the URI yourself, you could just
create it with valid escaping on the query string rather than pulling
it apart and escaping it as you put it back together.
-Rob
Rob Biedenharn http://agileconsultingllc.com
[email protected]
--
You received this message because you are subscribed to the Google Groups "Ruby on
Rails: Talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/rubyonrails-talk?hl=en.