Fusion Tables: Why do I keep getting a "400 Bad Request" error when trying to update a table style via Ruby's RestClient gem
Asked Answered
S

6

6

I'm trying to update a style for one of my Fusion Tables by using the Ruby gem RestClient.

Here's my code:

require 'rest_client'

tableId = '<STRING CONTAINING TABLEID>'
styleId = '<STRING CONTAINING STYLEID>'
key = '<STRING CONTAINING MY FUSION TABLES API KEY>'

table_url = "https://www.googleapis.com/fusiontables/v1/tables/#{tableId}/styles/#{styleId}?key=#{key}"
update = '{"polygonOptions": {"strokeColor":"#ffffff"}}'

token = 'STRING CONTAINING AUTHORIZATION TOKEN'

RestClient.put table_url,update,{"Authorization" => "Bearer #{token}"}

When I run that code, I get this error:

C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/abstract_response.rb:48:in `return!': 400 Bad Request (RestClient::BadRequest)
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:230:in `process_result'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:178:in `block in transmit'
    from C:/Ruby193/lib/ruby/1.9.1/net/http.rb:745:in `start'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:172:in `transmit'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:64:in `execute'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/request.rb:33:in `execute'
    from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient.rb:80:in `put'

When I input the update code into Google's official Style request PUT maker thingie, the update works. But it does not work when I run my Ruby code.

Does anyone know what I am doing wrong?

EDIT: Extra output I get from adding in RestClient.log = logger

RestClient.put "https://www.googleapis.com/fusiontables/v1/tables/<MY TABLE ID HERE>/styles/4?key=<AND HERE'S WHERE MY FUSION TABLE API KEY GOES>", "{\"polygonOptions\":{\"strokeColor\":\"#ffffff\"}}", "Accept"=>"*/*; q=0.5, application/xml", "Accept-Encoding"=>"gzip, deflate", "Authorization"=>"Bearer <THIS CONTAINS THE BEARER STRING>", "Content-Length"=>"44"
# => 400 BadRequest | application/json 255 bytes
Spay answered 28/1, 2013 at 22:49 Comment(3)
What message do you get back from Google?Sn
Is your token still valid? Example of how to validate a OAuth-token: googleapis.com/oauth2/v1/tokeninfo?access_token=your_tokenSn
@Pafjo, yes I checked, and the JSON object that URL returned showed that the token was still validSpay
P
4

You really should be using the google-api-ruby-client library instead of building your own REST calls. The library abstracts a lot of the OAuth stuff and formatting of the parameters for you.

Having said that, can you enable debugging for your RestClient and post the output of the RestClient call along with the output from Google official PUT maker thingie (I like your technical jargon there)? Comparing the two should show how they differ and what Google doesn't like with yours.

Penicillate answered 3/2, 2013 at 13:21 Comment(2)
Hm, that example uses Ruby on Rails. Do I do the same thing in regular Ruby to enable debugging?Spay
As for 'google-api-ruby-client,' i can't seem to understand it exactly (yet), though I guess that's what StackOverflow is for. Every time I initialize a new client, I get a W, [2013-02-04T16:21:40.128897 #4680] WARN -- : Google::APIClient - Please provide :application_name and :application_version when initializing the client, even when I specify the API name and version number, for instance.Spay
G
4

In answer to your question about setting up a logger without Rails, in the comments to @Jay Lee's answer…

Here is a logger set up to output to standard out:

logger = Logger.new STDOUT
logger.level = Logger::WARN # INFO/DEBUG… whatever level you find is needed
logger.datetime_format = '%a %d-%m-%Y %H%M '

Then put the rest of your code into a console (e.g. IRB) and before the last line add:

RestClient.log = logger

and you should get some helpful information output to the terminal. See the documents for the Logger class for more information on the levels available.

Gnathous answered 6/2, 2013 at 0:58 Comment(2)
Updated my question with thisSpay
@Spay did you try uping the log level from WARN to INFO or DEBUG to get more info? (sorry, I should've made clear you could do that, I've added that to the answer).Gnathous
S
4

I think the problem is that you are not setting the content-type to application/json. Try to do something like this:

RestClient.put(table_url, update, {"Authorization" => "Bearer #{token}", "Content-type" => "application/json"})

The payload in this case needs to be json so you can either use your json-string from your example or run to_json on you data structure.

Sn answered 7/2, 2013 at 17:17 Comment(3)
Strange! It worked when I tried it. What message did Google respond with?Sn
By the way, when I tried it I used ClientLogin instead of using a OAuth-token so my Authorization-header looked like this: GoogleLogin auth=a-really-long-auth-tokenSn
Can you update the code to reflect that? As for your first question, my error that Ruby spat back at me was C:/Ruby193/lib/ruby/gems/1.9.1/gems/rest-client-1.6.7/lib/restclient/abstract_response.rb:48:in return!': 401 Unauthorized (RestClient::Unauthorized)`Spay
T
2

It could be because your hash here

update = '{"polygonOptions": {"strokeColor":"#ffffff"}}'

should probably be

update = {"polygonOptions" => {"strokeColor" => "#ffffff"}}

Good luck!

Tonyatonye answered 6/2, 2013 at 1:23 Comment(3)
Nah, doesn't work. update is supposed to be read by Fusion Tables API as JSON.Spay
@Spay even so, you might try using engineerDave's hash and then calling .to_json on it instead of writing your own as you're not a JSON parser :) i.e. don't do things that the computer can do for you as it is a good way to introduce bugs. {"polygonOptions" => {"strokeColor" => "#ffffff"}}.to_jsonGnathous
Hm...dang, it still didn't work. I changed that line to update = {"polygonOptions"=>{"strokeColor"=>"#ffffff"}}.to_json, but still get a 400 Bad Request error...Spay
C
1

FYI,

Alternatives to try:

1) Remove HTTPS request in project settings and token regeneration.

2) Try to use SSL in that case.

3) Sometimes this error occurs when the values exceeds more than 255 characters that may be the possibility here with you. The same problem occurred sometime back with someone and was resolved after debugging. Check the link for more information.

Coagulate answered 7/2, 2013 at 12:57 Comment(7)
#1: Replacing 'https' with 'http', or just removing 'http(s)://' altogether gets me a 403 Forbidden error.Spay
#2: Do you know how I would do that with Ruby?Spay
#3: According to the new output from RestClient log, the content length appears to be 44 characters...Spay
Remember that special characters are not allowed in the url. They can mark seperation with the rest of the url and you get "403 Forbidden" error. You may used styles that contain special characters but haven't used literals to escape any.Coagulate
Secondly you don't seem to be using ruby's interpolation properly - table_url may not getting replaced by the value of constants. Make sure what you getting from substitutes in the url.Coagulate
What do you mean by that last comment?Spay
It is that you are putting key, table_id and style_id in the url and this can be anything. If any of these have special characters then replace each with literals to escape otherwise ruby will interpolate special chars as the one end of url and you will get "Forbidden Error".Coagulate
S
0

I was having the same 400 Bad Request problem, specifically when posting styles. I was able to solve the problem by making sure any values for "kind" in the style were namespaced, which the examples in the docs don't always get right -- for example:

{
     ...
     "kind": "fusiontables#buckets"
     ...
}

Instead of just "buckets".

Sulfanilamide answered 30/4, 2013 at 0:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.