I'm currently creating both the client and server app using ActiveResource for web servicing. The client has a long string (:history) that needs a conversion process done by the server.
Here, the client calls the post method on my object which extends ActiveResource::Base
active_resource.post(:convert, {:history => hh, :format => format})
This line errors complaining that the URI is too long:
ActiveResource::ClientError Failed. Response code = 414. Response message = Request-URI Too Large.
What other options do I have for sending "large" data ? Probably looking in the neighborhood of 2000 characters of data for the hh string above.
Thanks!
So the signature for the post method is:
post(custom_method_name, options = {}, body = '')
So, when you do:
active_resource.post(:convert, {:history => hh, :format => format})
It's putting your post variables in the options hash, which comes out in your query string for the post.
What you want to do is:
active_resource.post(:convert, nil, {:history => hh, :format => format}.to_json)
I didn't think post parameters factored into URI length. Are you sure it's the hh string and not the actual URI that active_resource.post is using?
Related
I have the following 3 strings...
a = "The URL is www.google.com"
b = "The URL is google.com"
c = "The URL is http://www.google.com"
Ruby's URI extract method only returns the URL in the third string, because it contains the http part.
URI.extract(a)
=> []
URI.extract(b)
=> []
URI.extract(c)
=> ["http://www.google.com"]
How can I create a method to detect and return the URL in all 3 instances?
Use regular expressions :
Here is a basic one that should work for most cases :
/(https?:\/\/)?\w*\.\w+(\.\w+)*(\/\w+)*(\.\w*)?/.match( a ).to_s
This will only fetch the first url in the string and return a string.
There's no perfect solution to this problem: it's fraught with edge cases. However, you might be able to get tolerably good results using something like the regular expressions used by Twitter to extract URLs from tweets (stripping off the extra leading spaces is left as an exercise!):
require './regex.rb'
def extract_url(s)
s[Twitter::Regex[:valid_url]]
end
a = "The URL is www.google.com"
b = "The URL is google.com"
c = "The URL is http://www.google.com"
extract_url(a)
# => " www.google.com"
extract_url(b)
# => " google.com"
extract_url(c)
# => " http://www.google.com"
You seem to be satisfied with Sucrenoir's answer. The essence of Sucrenoir's answer is to identity a URL by assuming that it includes at least one period. if that is the case, Sucrenoir's regex can be simplified (not equivalently, but for the most part) to this:
string[/\S+\.\S+/]
This is something I used a while ago, hopefully it helps
validates :url, :format =>
{ :with => URI::regexp(%w(http https)), :message => "Not Valid URL" }
Pass it through that validation (I assume your using a database)
Try with this method. Hope it will work for you
def get_url(str)
arr = str.split(' ')
url = nil
arr.map {|arr_str| url = arr_str if arr_str.include?('.com')}
url
end
This is your example
get_url("The URL is www.google.com") #=> www.google.com
get_url("The URL is google.com") #=> google.com
get_url("The URL is http://www.google.com") #=> http://www.google.com
I am currently banging my head against the wall repeatedly until I get passed this issue. I'm using ruby-1.9.3-p194 and Rails. I'm attempting to make a post request which I can do fine with Net::HTTP.post_form, but I can't use that here because I need to set a cookie in the header. http.post is erroring saying
"undefined method `bytesize' for #<Hash:0xb1b6c04>"
because I guess it's trying to perform some operation on the data being sent.
Does anyone have some kind of fix or work around?
Thanks
headers = {'Cookie' => 'mycookieinformationinhere'}
uri = URI.parse("http://asite.com/where/I/want/to/go")
http = Net::HTTP.new(uri.host, uri.port)
response = http.post(uri.path, {'test' => 'test'}, headers)
The bytesize method is on String, not Hash. That's your first clue. The second clue is the documentation for Net::HTTP#post:
post(path, data, initheader = nil, dest = nil)
Posts data (must be a String) to path. header must be a Hash like { ‘Accept’ => ‘/’, … }.
You're trying to pass a Hash, {'test' => 'test'}, to post where it expects to see a String. I think you want something more like this:
http.post(uri.path, 'test=test', headers)
I am doing an http get using the url http://localhost/add?add_key[0][key]=1234&add_key[0][id]=1.
I have a rails app which gives me a neat params hash {"add_key"=>{"0"=>{"key"=>"1234", "id"=>"1"}}. However when I try to post this to a different server using
new_uri = URI.parse("http://10.10.12.1/test")
res = Net::HTTP.post_form new_uri,params
The server handling the post is seeing this parameter in the request
{"add_key"=>"0key1234id1"}
Looks like post_form requires a String to String hash. So how do I convert the params hash to
{"add_key[0][key]" => "1234", add_key[0][id]" => "1"}
From the fine manual:
post_form(url, params)
Posts HTML form data to the specified URI object. The form data must be provided as a Hash mapping from String to String.
So you're right about what params needs to be.
You could grab the parsed params in your controller:
{"add_key"=>{"0"=>{"key"=>"1234", "id"=>"1"}}
and then recursively pack that back to the flattened format that post_form expects but that would be a lot of pointless busy work. An easy way to do this would be to grab the raw URL and parse it yourself with URI.parse and CGI.parse, something like this in your controller:
u = URI.parse(request.url)
p = CGI.parse(u.query)
That will leave you with {"add_key[0][key]" => "1234", "add_key[0][id]" => "1"} in p and then you can hand that p to Net::HTTP.post_form.
Is there a way to manage URL encoding with ActiveResource? Specifically I am looking for a way to pass an email address as a parameter.
Currently my query fails as the # symbol gets URL encoded to %40, causing the lookup on the remote app to fail.
For example, the following query on the ActiveResource model Person…
Person.all(:from => :remote_find_by_email, :params => {:email => "john#example.com")
Produces the following URL
http://example.com/people/remote_find_by_email.xml?email=john%40example.com
Alternately, is there something the remote app should be doing to decode the parameter before performing the lookup?
UPDATE
Thanks to eks, I added the following method and before filter to the controller on the remote app:
before_filter :cgi_unescape_params, :only => [:remote_find_by_email]
private
def cgi_unescape_params
params.each { |k, v| params[k] = CGI.unescape(v) }
end
Try using CGI::unescape on the remote end, that should take care of any % encoded value. Cheers!
Hi
I want to use two params hashes in one page
The job of this page is straightforward, it's an edit page, and I want it to send out notifications to a server once the editing job is done.
def update
#description = Tempdescription.find(params[:id])
#description.update_attributes(params[:tempdescription])
sendnotification
end
def sendnotification
params[:to_ids]="xxxx"
sig = hash_params(params);
params[:sig] = sig
response = RestClient.post "http://api.xxxx.com/restserver.do", params, :content_type => :json, :accept => :json
render :text=>response
end
def hash_params(params)
params = Hash[*params.sort.flatten]
payload = ''
params.sort.each do |pair|
key, value = pair
payload = payload + "#{key}=#{value}"
end
return Digest::MD5.hexdigest(payload + API_SECRET)
end
Not surprisingly the params in sendnotification also includes params used for updating
and the server returns 104 error
Therefore,
I tried
new_params=Hash[]
and use new_params to replace the old params in sendnotification
But then rails complains
undefined method `<=>' for :session_key:Symbol
app/controllers/tempdescriptions_controller.rb:72:in `<=>'
app/controllers/tempdescriptions_controller.rb:72:in `sort'
app/controllers/tempdescriptions_controller.rb:72:in `hash_params'
app/controllers/tempdescriptions_controller.rb:45:in `sendnotification'
So I am thinking if there is any way I can create another params?
Thanks in advance
Ok, having complained about your formatting I suppose I should hazard an attempt at your problem.
This code:
def hash_params(params)
params = Hash[*params.sort.flatten]
payload = ''
params.sort.each do |pair|
key, value = pair
payload = payload + "#{key}=#{value}"
end
return Digest::MD5.hexdigest(payload + API_SECRET)
end
.. appears to accept a hash as its argument and then recreate it with the keys sorted. Presumably this code is targeted at ruby 1.9 otherwise that would be rather pointless. It then sorts again for no reason I can determine before joining the keys and values with = but without separating the pairs with &.
The error is a little mysterious though; I have no trouble sorting symbols with ruby 1.9. Perhaps you're running ruby 1.8?
Ok...after playing with rails console for a while I finally find a solution to this problem.
In sendnotification method I created a new hash
p=Hash[]
but simply putting this will not work, as I mentioned before.
Then I changed all
p[:key]
to
p["key"]
and it works.
Obviously Hash#sort doesn't work with hash[:key] if the hash is newly created but it works with params and that's what puzzled me and made me believe there is a difference between params and normal hash.
I am using Ruby 1.8.7 so I think it might just be a bug of this version.