Come invio una richiesta JSON in ruby? Ho un oggetto JSON ma non penso di poterlo fare .send
. Devo fare in modo che javascript invii il modulo?
O posso usare la classe net / http in ruby?
Con header - content type = json e body l'oggetto json?
Risposte:
uri = URI('https://myapp.com/api/v1/resource')
req = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
req.body = {param1: 'some value', param2: 'some other value'}.to_json
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req)
end
http.request(req).read_body
per leggere il corpo della risposta. Grande!
require 'net/http'
require 'json'
def create_agent
uri = URI('http://api.nsa.gov:1337/agent')
http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Post.new(uri.path, 'Content-Type' => 'application/json')
req.body = {name: 'John Doe', role: 'agent'}.to_json
res = http.request(req)
puts "response #{res.body}"
rescue => e
puts "failed #{e}"
end
HTTParty lo rende un po 'più semplice penso (e funziona con json nidificato ecc., Che non sembra funzionare in altri esempi che ho visto.
require 'httparty'
HTTParty.post("http://localhost:3000/api/v1/users", body: {user: {email: 'user1@example.com', password: 'secret'}}).body
esempio di vita reale, notifica all'API Airbrake di una nuova distribuzione tramite NetHttps
require 'uri'
require 'net/https'
require 'json'
class MakeHttpsRequest
def call(url, hash_json)
uri = URI.parse(url)
req = Net::HTTP::Post.new(uri.to_s)
req.body = hash_json.to_json
req['Content-Type'] = 'application/json'
# ... set more request headers
response = https(uri).request(req)
response.body
end
private
def https(uri)
Net::HTTP.new(uri.host, uri.port).tap do |http|
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
end
end
project_id = 'yyyyyy'
project_key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
url = "https://airbrake.io/api/v4/projects/#{project_id}/deploys?key=#{project_key}"
body_hash = {
"environment":"production",
"username":"tomas",
"repository":"https://github.com/equivalent/scrapbook2",
"revision":"live-20160905_0001",
"version":"v2.0"
}
puts MakeHttpsRequest.new.call(url, body_hash)
Appunti:
nel caso in cui esegui l'autenticazione tramite l'intestazione del set di intestazioni di autorizzazione req['Authorization'] = "Token xxxxxxxxxxxx"
o http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
Un semplice esempio di richiesta POST json per coloro che ne hanno bisogno ancora più semplice di quello a cui Tom si collega:
require 'net/http'
uri = URI.parse("http://www.example.com/search.json")
response = Net::HTTP.post_form(uri, {"search" => "Berlin"})
È il 2020 - nessuno dovrebbe più usare Net::HTTP
e tutte le risposte sembrano dirlo, usa una gemma di livello più alto come Faraday - Github
Detto questo, quello che mi piace fare è un wrapper attorno alla chiamata API HTTP, qualcosa che si chiama come
rv = Transporter::FaradayHttp[url, options]
perché questo mi consente di falsificare le chiamate HTTP senza dipendenze aggiuntive, ad esempio:
if InfoSig.env?(:test) && !(url.to_s =~ /localhost/)
response_body = FakerForTests[url: url, options: options]
else
conn = Faraday::Connection.new url, connection_options
Dove il falsario assomiglia a questo
So che esistono framework di mocking / stubbing HTTP, ma almeno quando ho cercato l'ultima volta non mi hanno permesso di convalidare le richieste in modo efficiente ed erano solo per HTTP, non ad esempio per scambi TCP grezzi, questo sistema mi permette di avere un framework unificato per tutte le comunicazioni API.
Supponendo che tu voglia solo convertire rapidamente e in modo sporco un hash in json, invia il json a un host remoto per testare un'API e analizzare la risposta a ruby, questo è probabilmente il modo più veloce senza coinvolgere gemme aggiuntive:
JSON.load `curl -H 'Content-Type:application/json' -H 'Accept:application/json' -X POST localhost:3000/simple_api -d '#{message.to_json}'`
Si spera che sia ovvio, ma non usarlo in produzione.
Net::HTTP
affermazione "nessuno dovrebbe usare "
nobody should be using Net::HTTP any more
@bbozo
Funziona su ruby 2.4 HTTPS Post con oggetto JSON e il corpo della risposta scritto.
require 'net/http' #net/https does not have to be required anymore
require 'json'
require 'uri'
uri = URI('https://your.secure-url.com')
Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
request.body = {parameter: 'value'}.to_json
response = http.request request # Net::HTTPResponse object
puts "response #{response.body}"
end
Mi piace questo client di richiesta http leggero chiamato `unirest '
gem install unirest
utilizzo:
response = Unirest.post "http://httpbin.org/post",
headers:{ "Accept" => "application/json" },
parameters:{ :age => 23, :foo => "bar" }
response.code # Status code
response.headers # Response headers
response.body # Parsed body
response.raw_body # Unparsed body
L'api net / http può essere difficile da usare.
require "net/http"
uri = URI.parse(uri)
Net::HTTP.new(uri.host, uri.port).start do |client|
request = Net::HTTP::Post.new(uri.path)
request.body = "{}"
request["Content-Type"] = "application/json"
client.request(request)
end
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |client|
data = {a: {b: [1, 2]}}.to_json
uri = URI 'https://myapp.com/api/v1/resource'
https = Net::HTTP.new uri.host, uri.port
https.use_ssl = true
https.post2 uri.path, data, 'Content-Type' => 'application/json'
req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})