Rails 3 Post to external web service - ruby-on-rails

Lets say I have a blog post that a user is creating and I want to send all of the data to an external web service as XML with a specific schema so it can be ingested into that web service.
I have been looking into the ActionDispatch::Request
And I read this Using Ruby on Rails to POST JSON/XML data to a web service post and answer
However I got an error saying content_type was not a valid method for request. So I changed that line to call the header method and create a header for content-type with the appropriate information
Ok... so now where to go?
This is my code so far:
url= URI.parse('http://10.29.3.47:8080/ingest')
response = Net::HTTP::Post.new(url.path)
request.headers["Content-Type"] = 'application/json'
request.body = 'all of my xml data and schema which is far too long to type here'
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}
assert_equal '201 Created', response.get_fields('Status')
I get an error saying that request.body is also not a valid method call, but when I look at the API the only thing matching body is "body()" which does not take arguments. So how do I pass the content of my post to the web service?
Thank you for the help!

You had response = Net::HTTP::Post.new(url.path) instead of request = Net::HTTP::Post.new(url.path) and you add headers with add_field.
require 'net/http'
require 'uri'
url= URI.parse('http://10.29.3.47:8080/ingest')
request = Net::HTTP::Post.new(url.path)
request.add_field 'Content-Type', 'application/json'
request.body = 'all of my xml data and schema which is far too long to type here'
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}

Related

Rails Net::HTTP form data with custom headers

I am trying to send a file through form_data and set the Content-Type header as the content type of the file (image/png, image/jpeg, etc.) instead of multipart/form-data.
I have tried multiple ways, but here is my method:
def fetch(url, body, headers, limit, use_ssl, use_file_content_type)
raise HTTPRedirectLevelTooDeep, 'HTTP redirect too deep' if limit.zero?
headers[:'Content-Type'] = body['file'].content_type if use_file_content_type
uri = URI(url)
request = Net::HTTP::Post.new(url)
headers.each { |key, value| request[key.to_s] = value }
form_data = body.to_a
request.set_form form_data, 'multipart/form-data'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: use_ssl) do |http|
http.request(request)
end
case response
when Net::HTTPSuccess then response
when Net::HTTPRedirection then fetch(response['location'], body, headers, limit - 1)
else
response.error!
end
end
This sends the body just as I want it, but does not set the Content Type header correctly (it uses multipart/form-data). I also tried setting the header after setting the form data:
request['Content-Type'] = body['file'].content_type right before http.request(request) but it sends Content-Type: application/x-www-form-urlencoded.
I also tried setting the header in the Net::HTTP::Post.new method, or moving everything after request = inside the Net::HTTP.start method, but it still does not work for me. I also tried using request.set_form form_data, body['file'].content_type, but that just says invalid enctype: image/jpeg
One thing that sent the headers correctly was replacing this:
form_data = body.to_a
request.set_form form_data, 'multipart/form-data'
with
request.body = body.to_json
But this does not send the file as the external API I'm using expects it.
Do you have any suggestions of how I could tackle this? Thanks!

how to save the http.request curl in rails?

I already managed to make a post request of curl in rails
I print on the console the response.body
{"access_token":"XXXXXXX","public_key":"XXXXXX","refresh_token":"XXXXXX","live_mode":false,"user_id":XXXX,"token_type":"bearer","expires_in":15552000,"scope":"offline_access read write"}
now I want to gurantee that data in a table in rails
How can you do that?
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
If I understood correctly what you want is to make a HTTP request then parse the response and store it into a table (model) in your database. Well if that is the case:
require 'net/https'
uri = URI.parse("http://example.com/path")
// You can change the request method to whatever method you want
request = Net::HTTP::Post.new(uri.request_uri)
request.body = { //json hear in case you need it }
request.add_field 'token', 'XXXXX'
response = http.request(request).body
json_response = JSON.parse(response, symbolize_names: true)
You will have the response in json_response, then you only will have to store that information in the model you want:
Model.create(attribute_1: json_response[:parameter_1], attribute_2: json_response[:parameter_2]...)

Running a HTTP request with rails

It has been a while since I have used Rails. I currently have a curl request as follows
curl -X GET -H 'Authorization: Element TOKEN, User TOKEN' 'https://api.cloud-elements.com/elements/api-v2/hubs/marketing/ping'
All I am looking to do is to be able to run this request from inside of a rails controller, but my lack of understanding when it comes to HTTP requests is preventing me from figuring it out to how best handle this. Thanks in advance.
Use this method for HTTP requests:
def api_request(type , url, body=nil, header =nil )
require "net/http"
uri = URI.parse(url)
case type
when :post
request = Net::HTTP::Post.new(uri)
request.body = body
when :get
request = Net::HTTP::Get.new(uri)
when :put
request = Net::HTTP::Put.new(uri)
request.body = body
when :delete
request = Net::HTTP::Delete.new(uri)
end
request.initialize_http_header(header)
#request.content_type = 'application/json'
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') {|http| http.request request}
end
Your example will be:
api_request(:get, "https://api.cloud-elements.com/elements/api-v2/hubs/marketing/ping",nil, {"Authorization" => "Element TOKEN, User TOKEN" })
It would be something like the following. Note that the connection will be blocking, so it can tie up your server depending on how quickly the remote host returns the HTTP response and how many of these requests you are making.
require 'net/http'
# Let Ruby form a canonical URI from our URL
ping_uri = URI('https://api.cloud-elements.com/elements/api-v2/hubs/marketing/ping')
# Pass the basic configuration to Net::HTTP
# Note, this is not asynchronous. Ruby will wait until the HTTP connection
# has closed before moving forward
Net::HTTP.start(ping_uri.host, ping_uri.port, :use_ssl => true) do |http|
# Build the request using the URI as a Net::HTTP::Get object
request = Net::HTTP::Get.new(ping_uri)
# Add the Authorization header
request['Authorization'] = "Element #{ELEMENT_TOKEN}, User #{user.token}"
# Actually send the request
response = http.request(request)
# Ruby will automatically close the connection once we exit the block
end
Once the block exits, you can use the response object as necessary. The response object is always a subclass (or subclass of a subclass) of Net::HTTPResponse and you can use response.is_a? Net::HTTPSuccess to check for a 2xx response. The actual body of the response will be in response.body as a String.

Ruby Net:HTTP::Get weird behavior with JSON

I am using Net::HTTP for sending GET request to an API Server to fetch some data based on some configurations as below:
# method to fetch shirt sample details from api server
def fetch_shirt_sample(shirt, query_params)
path = "http://myapiserver.com/shirts/#{shirt.id}/shirt_sample"
url = URI.parse(path)
req = Net::HTTP::Get.new(url.path + '?' + query_params)
res = Net::HTTP.start(url.host, url.port) { |http| http.request(req) }
JSON.parse(res.body)
end
What is wrong or weird I found is above method works for following query params:
"&name=medium_shirt&color=red&configs=[\"full_length\",\"no_collar\",\"casual\"]"
but doesn't even send GET request for following query params:
"&name=medium_shirt&color=red&configs=[\"full_length\",\"15\",\"43\",\"30\"]"
Could anyone help me to understand what is wrong in the above setup?

Net::HTTP::Put.new(url.path) shows the 401 error in RUby

HI ,
i am new to ROR
i am writing Ruby code for calling API blogs
i have written ruby code for
Creating the blog by
require 'net/http'
require 'uri'
url = URI.parse('http://localhost:3000/api/blogs/create.xml')
req = Net::HTTP::Post.new(url.path)
req.basic_auth 'a', 'a'
req.set_form_data({'blogpost[title]'=>'TestingAPIBlogposttitle',
'blogpost[description]'=>'Testing api desc',
'blogpost[category_id]'=>'3121'}, ';')
res = Net::HTTP.new(url.host, url.port).start {|http| http.request(req)}
case res
when Net::HTTPSuccess, Net::HTTPRedirection
puts res.body
else
res.error!
end
which runs successfully by creating a new blog
And i have a search code
require 'net/http'
require 'uri'
require 'cgi'
## Change this part according to the api to be accessed and the params to be passed.
uri = URI.parse( "http://localhost:3000/api/blogs/show/blogtitle.xml" )
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.path)
request.basic_auth 'a', 'a'
response = http.request(request)
puts response.body
which returns the
<?xml version="1.0" encoding="UTF-8"?>
<blogpost>
<created-at type="datetime">2010-09-02T08:18:22Z</created-at>
<description><p>Blog desc</p></description>
<slug>blogtitle</slug>
<title>blogtitle</title>
<user>
<firstname>admin</firstname>
<lastname>k</lastname>
<login>admin</login>
</user>
</blogpost>
Now i am trying to Update a BLog
for this how to write the code
i tried by simply changing the POST.new by PUT.new
but it didnt works for me
its showing me the error even if i gave admin User credentials
It might be worth trying a POST request but also adding a _method = 'put' parameter to the request. Rails can simulate a PUT request in this way though I would expect it to respond correctly to an HTTP PUT too.

Resources