Ruby JSON isteği gönder


86

Ruby'de nasıl JSON isteği gönderirim? JSON nesnem var ama yapabileceğimi sanmıyorum .send. Formu javascript göndermeli miyim?

Veya Ruby'de net / http sınıfını kullanabilir miyim?

Başlık - içerik türü = json ve json nesnesinin gövdesi?

Yanıtlar:


77
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

8
Aksi takdirde oldukça sıkıcı olan, ana bilgisayar adını ve bağlantı noktasını işlemek için URI kullanma önerinizi beğendim. Ama Post.new'de uri.path ayarlamayı unuttunuz (...):req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
ArnauOrriols

1
En basit, en temiz yanıt. Bu harika.
joelc

http.request(req).read_bodyyanıt gövdesini okumak için. Harika!
iGian

1
2.4.1'de değiştiğine eminim ama tanrım. Bu sözdizimi iğrenç. Post.new () 'deki URI'ye sahip olduğunu bilir, öyleyse neden değerleri yeniden göndermeniz gerekiyor, start ()' da bölünmüş. Brüt. Ruby'de http ile ilgili pek çok başka paket olmasına şaşmamalı.
Rambatino

50
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

Hangi istisna belirtilmeli
Mio

7
Https istekleri için şunu ekleyin: http.use_ssl = true.
Beceri M2

16

HTTParty bunu biraz daha kolaylaştırdığını düşünüyorum (ve gördüğüm diğer örneklerde işe yaramadı gibi iç içe geçmiş json vb. İle çalışıyor.

require 'httparty'
HTTParty.post("http://localhost:3000/api/v1/users", body: {user: {email: 'user1@example.com', password: 'secret'}}).body

6

gerçek hayat örneği, NetHttps aracılığıyla Airbrake API'yi yeni dağıtım hakkında bilgilendir

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)

Notlar:

Yetkilendirme başlık seti başlığı req['Authorization'] = "Token xxxxxxxxxxxx" veya http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html aracılığıyla kimlik doğrulaması yapmanız durumunda


... ama dürüst bu serin ve tüm ama gerçek canlı içinde isterim sadece kullanmak HTTParty stackoverflow.com/a/14491995/473040 :) ... https taşıma ile uğraşan, özellikle
equivalent8


@ equivalent8: "gerçek hayatta sadece HTTParty kullanırım" - yani, yalın bir mücevher oluşturmuyorsanız veya başka bir bağımlılık istemiyorsanız. :)
Sergio Tulentsev

); Eğer mücevher / lib (ya da Ruby temelli microservice) gereksiz bağımlılıkları tanıtmak istemiyorum inşa ediyoruz sürece @SergioTulentsev ... katılıyorum
equivalent8

5

Tom'un bağlantı verdiğinden çok daha basit ihtiyacı olanlar için basit bir json POST isteği örneği:

require 'net/http'

uri = URI.parse("http://www.example.com/search.json")
response = Net::HTTP.post_form(uri, {"search" => "Berlin"})

19
Bu çalışması gerektiği gibi görünüyor, ancak post_form parametreleri? Anahtar = değer & anahtar = değer sözdizimine çevirir. İstek gövdesi JSON dizesine ayarlanmış bir POST yapmak istiyorsanız, farklı bir çözüme ihtiyacınız olduğunu düşünüyorum.
Ben Gotow

Bu, derinlemesine iç içe geçmiş json ile çalışmaz. Birinci seviyenin ötesinde her şey bir dizge olur.
neoneye

Sadece benzemiyor. İşe yarıyor. Kesinlikle basit. ancak verdiğim örnek gibi basit şeyler için gayet iyi çalışıyor
Christoffer

4
Bu, temelde bir JSON isteği değildir. Bu, kodlanmış bir yapıdır. JSON yok. Başlık bile çok şey söylüyor. Bu hiçbir örnekle çalışmaz.
raylu

4
Bu cevap yanlıştır. Mime / multipart biçiminde bir POST, içinde "json" yazan bir url'dir.
John Haugeland

4

Yıl 2020 - kimse artık kullanmamalı Net::HTTPve tüm cevaplar öyle diyor gibi, Faraday gibi daha yüksek seviyeli bir mücevher kullanın - Github


Bununla birlikte, yapmaktan hoşlandığım şey, HTTP api çağrısının etrafındaki bir sarmalayıcıdır.

rv = Transporter::FaradayHttp[url, options]

çünkü bu, HTTP çağrılarını ek bağımlılıklar olmadan taklit etmeme izin veriyor, yani:

  if InfoSig.env?(:test) && !(url.to_s =~ /localhost/)
    response_body = FakerForTests[url: url, options: options]

  else
    conn = Faraday::Connection.new url, connection_options

Nerede sahtekar gibi görünür bu

HTTP alay / saplama çerçeveleri olduğunu biliyorum, ancak en azından en son araştırdığımda istekleri verimli bir şekilde doğrulamama izin vermediler ve sadece HTTP içindi, örneğin ham TCP değişimleri için değil, bu sistem bana bir tüm API iletişimi için birleşik çerçeve.


Bir hash'i json'a hızlı ve kirli bir şekilde dönüştürmek istediğinizi varsayarsak, bir API'yi test etmek için json'u uzaktaki bir ana bilgisayara gönderin ve Ruby'ye yanıtı ayrıştırmak, muhtemelen ek taşlar içermeyen en hızlı yoldur:

JSON.load `curl -H 'Content-Type:application/json' -H 'Accept:application/json' -X POST localhost:3000/simple_api -d '#{message.to_json}'`

Umarım bunu söylemeye gerek yok ama bunu üretimde kullanmayın.


Bunu NTLM kimlik doğrulaması kullanarak yapamazsınız. Dolayısıyla Net :: HTTP, onu destekleyen bir kitaplığa sahip olan tek dosyadır.
Rhuan

3
'Kimse kullanmamalı Net::HTTP' iddiasına
katılmıyorum

1
@Bbozonobody should be using Net::HTTP any more
Patricio Sard

3

Bu, JSON nesnesi ve yazılı yanıt gövdesi ile Ruby 2.4 HTTPS Post üzerinde çalışır.

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

2

`` Unirest '' adlı bu hafif http istek istemcisini beğendim

gem install unirest

kullanım:

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

1

Net / http api'nin kullanımı zor olabilir.

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

Bu kod çalışmıyor. Net :: HTTP'yi #start ile şu şekilde başlatmanız gerekir:Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |client|
Tyler

Ruby 2.3.7p456 (2018-03-28 revizyon 63024) ile çalışır [universal.x86_64-darwin18]
Moriarty

0
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'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.