Issue downloading an image from a URL (HTTP request)

I am trying to download the image of a chart I created using the
GoogleChart API using the 'net/http' module. I have the URL I want to
download the image from stored in a string variable named failures_url,
when I use the variable to download the image it doesn't work. But if I
use the string literal value of that variable it does work.

This is what I am doing:
require 'net/http'

#try with variable
Net::HTTP.start("http://chart.googleapis.com") { |http|
  resp = http.get("/chart?#{failures_url}")
  open("pie1.png" ,"wb") { |file|
    file.write(resp.body)
  }
}

the value of failures_url is:
"chtt=Failure+By+Type+Over+Last+Year&cht=p
&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,
17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,
0.336134453781513,0.224089635854342,0.168067226890756,
0.130718954248366,0.0373482726423903&chs=700x400&
chco=4466AA|9BC4E2|1464F4|0000FF|63D1F4|388E8E&
chl=Build/Compile+Failure+26.87%|Unknown+Failure+25.6%|
User+Manifest+Failure+24.99%|Invalid+Clientspec+17.98%|
Incomplete+Build+2.8%|Coverity+System+Error+0.65%|
Do+Not+Use+Error+0.35%|Version+Failure+0.34%|Coverity+Defects+0.22%|
Flash+Build+Error+0.17%|Space+Insufficient+0.13%|Integrate+Failure+0.04%"

This attempt does not work.

#2nd attempt with string literal
Net::HTTP.start("http://chart.googleapis.com") { |http|
  resp =
http.get("/chart?chtt=Failure+By+Type+Over+Last+Year&cht=p&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,0.336134453781513,0.224089635854342,0.168067226890756,0.130718954248366,0.0373482726423903&chs=700x400&chco=4466AA|9BC4E2|1464F4|0000FF|63D1F4|388E8E&chl=Build/Compile+Failure+26.87%|Unknown+Failure+25.6%|User+Manifest+Failure+24.99%|Invalid+Clientspec+17.98%|Incomplete+Build+2.8%|Coverity+System+Error+0.65%|Do+Not+Use+Error+0.35%|Version+Failure+0.34%|Coverity+Defects+0.22%|Flash+Build+Error+0.17%|Space+Insufficient+0.13%|Integrate+Failure+0.04%")
  open("pie2.png" ,"wb") { |file|
    file.write(resp.body)
  }
}

This attempt DOES work. Does anyone know why this is happening? The
value is the same in both http.get(...) calls but only the literal one
generates an image file.

Thanks
Hunter

···

--
Posted via http://www.ruby-forum.com/.

I don't know why one of your attempts works and the other won't, maybe
you should post a complete example that fails. But looking at how I'd
do it I realized that in the failures_url variable there are a couple
of characters that are not valid for a URL and should be escaped: %
and |. So I tried this and it worked for me:

ruby-1.8.7-p334 :022 > require 'open-uri'
=> true
ruby-1.8.7-p334 :037 >
failures_url="chtt=Failure+By+Type+Over+Last+Year&cht=p&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,0.336134453781513,0.224089635854342,0.168067226890756,0.130718954248366,0.0373482726423903&chs=700x400&chco=4466AA|9BC4E2|1464F4|0000FF|63D1F4|388E8E&chl=Build/Compile+Failure+26.87%|Unknown+Failure+25.6%|User+Manifest+Failure+24.99%|Invalid+Clientspec+17.98%|Incomplete+Build+2.8%|Coverity+System+Error+0.65%|Do+Not+Use+Error+0.35%|Version+Failure+0.34%|Coverity+Defects+0.22%|Flash+Build+Error+0.17%|Space+Insufficient+0.13%|Integrate+Failure+0.04%"
ruby-1.8.7-p334 :038 > failures_url.gsub!("%", URI.escape("%"))
=> "chtt=Failure+By+Type+Over+Last+Year&cht=p&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,0.336134453781513,0.224089635854342,0.168067226890756,0.130718954248366,0.0373482726423903&chs=700x400&chco=4466AA|9BC4E2|1464F4|0000FF|63D1F4|388E8E&chl=Build/Compile+Failure+26.87%25|Unknown+Failure+25.6%25|User+Manifest+Failure+24.99%25|Invalid+Clientspec+17.98%25|Incomplete+Build+2.8%25|Coverity+System+Error+0.65%25|Do+Not+Use+Error+0.35%25|Version+Failure+0.34%25|Coverity+Defects+0.22%25|Flash+Build+Error+0.17%25|Space+Insufficient+0.13%25|Integrate+Failure+0.04%25"
ruby-1.8.7-p334 :039 > failures_url.gsub!("|", URI.escape("|"))
=> "chtt=Failure+By+Type+Over+Last+Year&cht=p&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,0.336134453781513,0.224089635854342,0.168067226890756,0.130718954248366,0.0373482726423903&chs=700x400&chco=4466AA%7C9BC4E2%7C1464F4%7C0000FF%7C63D1F4%7C388E8E&chl=Build/Compile+Failure+26.87%25%7CUnknown+Failure+25.6%25%7CUser+Manifest+Failure+24.99%25%7CInvalid+Clientspec+17.98%25%7CIncomplete+Build+2.8%25%7CCoverity+System+Error+0.65%25%7CDo+Not+Use+Error+0.35%25%7CVersion+Failure+0.34%25%7CCoverity+Defects+0.22%25%7CFlash+Build+Error+0.17%25%7CSpace+Insufficient+0.13%25%7CIntegrate+Failure+0.04%25"
ruby-1.8.7-p334 :040 > File.open("test.png", "wb") {|f| f.write
open("https://chart.googleapis.com/chart?#{failures_url\}"\).read}
=> 46677

and I got your nice pie chart in test.png. Ideally you would
URI.escape each parameter and value of the URL separately, but as in
this example you already had the big string with everything I cherry
picked the problematic characters. But if you are building the query
string programatically, you should escape like this. Say you have a
map with all the params and values for the query string:

require 'uri'

map = {"chtt" => "Failure By Type Over Last Year", "cht" => "p" } # and so on

failures_url = ""
map.each {|key,value| failures_url << URI.escape(key) << "&" <<
URI.escape(value)}

and then the rest of the program.

Hope this helps,

Jesus.

···

On Thu, Jul 21, 2011 at 7:42 PM, Hunter Mcmillen <mcmillhj@gmail.com> wrote:

I am trying to download the image of a chart I created using the
GoogleChart API using the 'net/http' module. I have the URL I want to
download the image from stored in a string variable named failures_url,
when I use the variable to download the image it doesn't work. But if I
use the string literal value of that variable it does work.

Ooops, sorry, I got it wrong (I was joining with &):

map = {"chtt" => "Failure By Type Over Last Year", "cht" => "p" } # and so on
failures_url = map.map {|key,value|
"#{URI.escape(key)}=#{URI.escape(value)}" }.join("&")

Jesus.

···

2011/7/22 Jesús Gabriel y Galán <jgabrielygalan@gmail.com>:

On Thu, Jul 21, 2011 at 7:42 PM, Hunter Mcmillen <mcmillhj@gmail.com> wrote:

I am trying to download the image of a chart I created using the
GoogleChart API using the 'net/http' module. I have the URL I want to
download the image from stored in a string variable named failures_url,
when I use the variable to download the image it doesn't work. But if I
use the string literal value of that variable it does work.

I don't know why one of your attempts works and the other won't, maybe
you should post a complete example that fails. But looking at how I'd
do it I realized that in the failures_url variable there are a couple
of characters that are not valid for a URL and should be escaped: %
and |. So I tried this and it worked for me:

ruby-1.8.7-p334 :022 > require 'open-uri'
=> true
ruby-1.8.7-p334 :037 >
failures_url="chtt=Failure+By+Type+Over+Last+Year&cht=p&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,0.336134453781513,0.224089635854342,0.168067226890756,0.130718954248366,0.0373482726423903&chs=700x400&chco=4466AA|9BC4E2|1464F4|0000FF|63D1F4|388E8E&chl=Build/Compile+Failure+26.87%|Unknown+Failure+25.6%|User+Manifest+Failure+24.99%|Invalid+Clientspec+17.98%|Incomplete+Build+2.8%|Coverity+System+Error+0.65%|Do+Not+Use+Error+0.35%|Version+Failure+0.34%|Coverity+Defects+0.22%|Flash+Build+Error+0.17%|Space+Insufficient+0.13%|Integrate+Failure+0.04%"
ruby-1.8.7-p334 :038 > failures_url.gsub!("%", URI.escape("%"))
=> "chtt=Failure+By+Type+Over+Last+Year&cht=p&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,0.336134453781513,0.224089635854342,0.168067226890756,0.130718954248366,0.0373482726423903&chs=700x400&chco=4466AA|9BC4E2|1464F4|0000FF|63D1F4|388E8E&chl=Build/Compile+Failure+26.87%25|Unknown+Failure+25.6%25|User+Manifest+Failure+24.99%25|Invalid+Clientspec+17.98%25|Incomplete+Build+2.8%25|Coverity+System+Error+0.65%25|Do+Not+Use+Error+0.35%25|Version+Failure+0.34%25|Coverity+Defects+0.22%25|Flash+Build+Error+0.17%25|Space+Insufficient+0.13%25|Integrate+Failure+0.04%25"
ruby-1.8.7-p334 :039 > failures_url.gsub!("|", URI.escape("|"))
=> "chtt=Failure+By+Type+Over+Last+Year&cht=p&chd=t:26.8720821661998,25.6022408963585,24.9859943977591,17.9831932773109,2.80112044817927,0.65359477124183,0.354808590102708,0.336134453781513,0.224089635854342,0.168067226890756,0.130718954248366,0.0373482726423903&chs=700x400&chco=4466AA%7C9BC4E2%7C1464F4%7C0000FF%7C63D1F4%7C388E8E&chl=Build/Compile+Failure+26.87%25%7CUnknown+Failure+25.6%25%7CUser+Manifest+Failure+24.99%25%7CInvalid+Clientspec+17.98%25%7CIncomplete+Build+2.8%25%7CCoverity+System+Error+0.65%25%7CDo+Not+Use+Error+0.35%25%7CVersion+Failure+0.34%25%7CCoverity+Defects+0.22%25%7CFlash+Build+Error+0.17%25%7CSpace+Insufficient+0.13%25%7CIntegrate+Failure+0.04%25"
ruby-1.8.7-p334 :040 > File.open("test.png", "wb") {|f| f.write
open("https://chart.googleapis.com/chart?#{failures_url\}&quot;\).read}
=> 46677

and I got your nice pie chart in test.png. Ideally you would
URI.escape each parameter and value of the URL separately, but as in
this example you already had the big string with everything I cherry
picked the problematic characters. But if you are building the query
string programatically, you should escape like this. Say you have a
map with all the params and values for the query string:

require 'uri'

map = {"chtt" => "Failure By Type Over Last Year", "cht" => "p" } # and so on

failures_url = ""
map.each {|key,value| failures_url << URI.escape(key) << "&" <<
URI.escape(value)}

and then the rest of the program.