Json array in post method Apex RestFul - post

I successfully create a post service that accepts data in the request body of the xml structure, but now there is a need to get an array of type json from the request body and process it, but I cannot find an example or documentation for this solution .

Using a REST API defined like the example below, you can process both JSON and XML using the same endpoint. Using the Content-Type header, the user/application sending the information to the API can specify if they are sending JSON or XML.
I tested the code below using ORDS 19.2 and Oracle 19c.
BEGIN
ORDS.ENABLE_SCHEMA (p_enabled => TRUE,
p_url_mapping_type => 'BASE_PATH',
p_url_mapping_pattern => 'api-test',
p_auto_rest_auth => FALSE);
ORDS.DEFINE_MODULE (p_module_name => 'v1', p_base_path => '/v1/');
ORDS.DEFINE_TEMPLATE (p_module_name => 'v1', p_pattern => 'demo');
ORDS.DEFINE_HANDLER (p_module_name => 'v1',
p_pattern => 'demo',
p_method => 'POST',
p_source_type => ords.source_type_plsql,
p_source => '
DECLARE
l_input clob := :body_text;
l_input_json json_array_t;
l_input_xml XMLTYPE;
BEGIN
OWA_UTIL.mime_header (''text/plain'');
IF OWA_UTIL.get_cgi_env (''content-type'') = ''application/json''
THEN
l_input_json := json_array_t.parse (l_input);
htp.p (l_input_json.stringify);
ELSIF OWA_UTIL.get_cgi_env (''content-type'') = ''application/xml''
THEN
null;
l_input_xml := xmltype (l_input);
htp.p (l_input_xml.getstringval);
ELSE
HTP.p (''Unsupported content type'');
:status_code := 500;
END IF;
END;');
COMMIT;
END;
Below are some screenshots from Postman showing how to send the different content types
Example sending XML content
Example sending JSON content
Example sending unknown content type

Related

Rails: Empty params when do ajax post with content-type = application/json

I used Backbone as Javascript framework for my new project. However, When I invoke save() on a Model , Rails server just can't parse it to the params hash
Javascript
user new Project.Models.User({email : "nqtien310#gmail.com"})
user.save()
Rails server
puts params
=> {"action"=>"create", "controller"=>"users"}
puts request.raw_post
=> "{\"email\":\"nqtien310#gmail.com\"}"
Then I tried to set Backbone.emulateJSON to true
Javascript
Backbone.emulateJSON = true
and Rails can parse the post data to params now, but not the expected data
puts params
=> {"model"=>"{\"email\":\"nqtien310#gmail.com\"}", "action"=>"create", "controller"=>"users"}
Well, after a long research , I figure it out that inside of my profiles' initialize/mime_types.rb , they added
Mime::Type.register "application/json", :mobile
Dig into a bit , I can see that Rails uses the mime types to parse the request body , in this case , application/json is overriden , and Rails can't use the Json parse strategy to parse the request body into params hash, that's why it's empty
Backbone.emulateJSOn will set another content-type instead of application/json, that's why Rails still can understand this Mime Type, and has correspond parse strategy for it , but since it's not the JSON strategy , so the params is not in JSON format
Json parse strategy ( from Rails source )
when :json
data = request.deep_munge ActiveSupport::JSON.decode(request.body)
request.body.rewind if request.body.respond_to?(:rewind)
data = {:_json => data} unless data.is_a?(Hash)
data.with_indifferent_access

Post destination receive put data 2 times in parameters

I'm developping a post to a callback url in Ruby on Rails and use the Httparty library for this, I receive the post perfectly on the url but it seems that rails convert the data that is pushed to the url 2 times to parameters. Here is the code that I use to do the call :
#result = HTTParty.post("http://localhost:3000/mailchimp/callback/",
:body => {
:data => {
:title => 'This is the screen name'}
}.to_json,
:headers => { 'Content-Type' => 'application/json' } )
In the logs of the receiving application I got this :
Parameters: {"mailchimp"=>{"controller"=>"mailchimp", "action"=>"callback", "data"=>{"title"=>"This is the screen name"}}, "data"=>{"title"=>"This is the screen name"}}
You see directly that I have 2 times the data parameters, once in the controller hash and once in the normal parameters hash. How does this come?
This is caused by the ParamsWrapper module https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/params_wrapper.rb
This is enabled by default in your rails app by the initializer config/wrap_parameters.rb

Create record example for Quickbooks Online and Intuit Anywhere using Ruby and httparty?

Can someone post an example of creating a record in quickbooks online / intuit anywhere, using ruby and httparty?
I am working on an integration to a ruby on rails app using intuit anywhere, and am running into an issue with my POST request when attempting to create a new record. I have been able to successfully retrieve data (customers) using a POST command that doesn't require XML data in the body of the request, but am running into trouble when trying to create new records that have required fields that need to be passed in XML in the body of the request.
I get the same flavor of error in any entity for which I try to create a record for: an invalid or missing required field. It seems to me that the XML in the body (where the data for the required fields is added) is either being ignored (incorrect formatting?) or is not being attached.
I was hoping the someone else familiar with ruby could post an example of a record creation using httparty. If I could see how to correctly pass the XML using httparty, I can fix my problem myself.
I have been using the customer.com example (https://code.intuit.com/integration/viewvc/viewvc.cgi/IntuitAnywhere-Ruby/customer.com/?root=intuitanywhere&system=exsy1003) mostly as posted, with a few irrelevant modifications needed to get it to work in Rails 3.1. I am using the data pull and handling provided in the example, which looks like a pretty standard API wrapper built using httparty.
I am using a pull similar to the one found in the company_controller customers method. Here are two different ways I have tried submitting the XML:
#########################################
#Example 1 - XML
e = #company.intuit_token.post("https://qbo.intuit.com/qbo1/resource/account/v2/#{#company.realm}",
{ :body =>
"<Account xmlns:ns2=\"http://www.intuit.com/sb/cdm/qbo\" xmlns=\"http://www.intuit.com/sb/cdm/v2\">
<Name>Test Account 2</Name>
<Desc>Test Account</Desc>
<Subtype>Savings</Subtype>
<AcctNum>5001</AcctNum>
<OpeningBalanceDate>2010-05-14</OpeningBalanceDate>
</Account>",
:headers => {
"Content-Type" => "application/xml"
}}
)
#########################################
#Example 2 - hash
e = #company.intuit_token.post("https://qbo.intuit.com/qbo1/resource/account/v2/#{#company.realm}",
{ :body => {
:Account => {
:Name => "Loan Account 2",
:Desc => "Loac Account 2",
:Subtype => "Savings",
:AcctNum => "5001",
:OpeningBalanceDate => "2011-04-22"
}
},
:headers => {
"Content-Type" => "application/xml"
}}
)
I incorrectly assumed the customer.com example provided by intuit was using the httparty gem to make the POST call, so I was using the wrong syntax. They are actually using the OAuth gem's POST call, who's syntax can be found here: http://oauth.rubyforge.org/rdoc/classes/OAuth/AccessToken.html
I also had to modify the headers to get the Intuit Anywhere service to accept the XML body. Here is the code that finally worked for me to create a record in quickbooks online using intuit anywhere:
e = #company.intuit_token.post("https://qbo.intuit.com/qbo1/resource/account/v2/#{#company.realm}", "<Account xmlns:ns2=\"http://www.intuit.com/sb/cdm/qbo\" xmlns=\"http://www.intuit.com/sb/cdm/v2\"><Name>Test Account </Name><Desc>Test Account</Desc><Subtype>Savings</Subtype><AcctNum>5002</AcctNum><OpeningBalanceDate>2010-05-14</OpeningBalanceDate></Account>", {"Content-Type" => "application/xml", "standalone" => "yes", "encoding" => "UTF-8"})

How can I post xml data using net/http that also has data in the url

I am working with an api that requires me to post xml to url such as someapi.com?userID=123. Thus far, I have tried this (assume the xml is composed already in the xml variable):
url = URI.parse('http://www.someapi.com/process_leads.asp')
request = Net::HTTP::Post.new(url.path)
request.content_type = 'text/xml'
request.body = xml
request.set_form_data({'userID' => '1204'}, ';')
response = Net::HTTP.start(url.host, url.port) {|http| http.request(request)}
I am trying to figure out if I can have the userID as form data but also post xml? I am basically supposed to post the xml to http://www.someapi.com/process_leads.asp?userID=1204. Is that possible?
I would consider using a Http library, e.g. HTTParty
Example using HTTParty for your request would look something like:
HTTParty.post('http://www.someapi.com/process_leads.asp', :query => {:userID => 1024}, :body => xml )
the :query option takes a hash of key/values which will be added to the post URL,
the :body is where the xml goes.
NOTE: some api's require the xml to have a name e.g. you may have to do something like
:body => "request=#{xml}"
Hope this helps.

How to post JSON data in rails 3 functional test

I plan to use JSON data in both request and response in my project and having some problems in testing.
After searching for a while, I find the following code which uses curl to post JSON data:
curl -H "Content-Type:application/json" -H "Accept:application/json" \
-d '{ "foo" : "bar" }' localhost:3000/api/new
In the controller I can access the JSON data simply using params[:foo] which is really easy. But for functional testing, I only find post and xhr (alias for xml_http_request).
How can I write functional test in rails to achieve the same effect as using curl? Or should I do test in other ways?
Here's what I've tried. I find the implementation for xhr in action_controller/test_case.rb, and tried to add jhr method simply changing 'Conetent-Type' and 'HTTP_ACCEPT'. (Added in test/test_helpers.rb.)
def json_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
#request.env['Content-Type'] = 'Application/json'
#request.env['HTTP_ACCEPT'] ||= [Mime::JSON, Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
__send__(request_method, action, parameters, session, flash).tap do
#request.env.delete 'Content-Type'
#request.env.delete 'HTTP_ACCEPT'
end
end
alias jhr :json_http_request
I used this in the same way as xhr, but it does not work. I inspected the #response object and sees the body is " ".
I also find one similar question on Stack Overflow but it's for rails 2 and the answer for posting raw data does not work in rails 3.
As of Rails 5, the way to do this is:
post new_widget_url, as: :json, params: { foo: "bar" }
This will also set the Content-type header correctly (to application/json).
I found that this does exactly what I want – post JSON to a controller's action.
post :create, {:format => 'json', :user => { :email => "test#test.com", :password => "foobar"}}
Just specify appropriate content type:
post :index, '{"foo":"bar", "bool":true}', "CONTENT_TYPE" => 'application/json'
Json data should go as a string, not as a Hash.
Looking at stack trace running a test you can acquire more control on request preparation:
ActionDispatch::Integration::RequestHelpers.post => ActionDispatch::Integration::Session.process =>
Rack::Test::Session.env_for
Specifying :format does not work because request go as 'application/x-www-form-urlencoded' and json isn't parsed properly processing a request body.
Assuming you have a controller named api, a method named new, and you're in the test for the api controller:
#request.env["RAW_POST_DATA"] = '{ "foo" : "bar" }'
post :new
did the trick for me.
Here is a snippet that let me post json data to test my own app. rails 3
port = Rails.env.production? ? 80 : 3000
uri = URI.parse( Rails.application.routes.url_helpers.books_url(:host => request.host, :port => port, :format => :json) )
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
request.content_type = 'application/json'
request.body = #json_data
response = http.request( request )
#result = response.body
Hope this helps others
As #taro suggests in a comment above, the syntax that works for me in functional and integration tests is:
post :create, {param1: 'value1', param2: 'value2', format: 'json'}
(The curly braces aren't always necessary, but sometimes it doesn't work if they're missing, so I always add them.)
Here's what params and request.format look like for a post of that sort:
params:
{"param1"=>"value1", "param2"=>"value2", "format"=>"json", "controller"=>"things", "action"=>"create"}
request.format:
application/json
The best answer I can come up with to this is you don't
Whether or not it was intentional it s maybe good that rails doesn't implement this for you.
In functional tests you really want to just test your controller and not rails method of deserialization or even that routing and mime detection are all setup correctly, those all fall under an IntegrationTest.
So for your controllers, don't pass JSON just pass your params hash like you normally would. Maybe adding :format as an argument as well if you need to check that and respond differently.
If you want to test the full stack move to an IntegrationTest

Resources