Ruby는 JSON 요청을 보냅니다.


86

Ruby에서 JSON 요청을 어떻게 보내나요? JSON 개체가 있지만 할 수 있다고 생각하지 않습니다 .send. 양식을 자바 스크립트로 보내야합니까?

아니면 루비에서 net / http 클래스를 사용할 수 있습니까?

헤더-콘텐츠 유형 = json 및 본문 json 객체?

답변:


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
호스트 이름과 포트를 처리하기 위해 URI를 사용하라는 제안을 좋아합니다. 그렇지 않으면 매우 지루합니다. 하지만 Post.new (...)에서 uri.path를 설정하는 것을 잊었습니다.req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'})
ArnauOrriols

1
가장 간단하고 깨끗한 응답. 이것은 훌륭합니다.
joelc

http.request(req).read_body응답 본문을 읽으십시오. 큰!
iGian

1
나는 그것이 2.4.1에서 변경되었다고 확신하지만 세상에. 그 구문은 엄청납니다. Post.new ()의 URI가 있다는 것을 알고 있으므로 start ()에서 값을 분할하여 다시 전달해야하는 이유는 무엇입니까? 심한. 루비에 http를 다루는 다른 많은 패키지가 있다는 것은 당연합니다.
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

지정해야하는 예외
Mio

7
https 요청의 경우 http.use_ssl = true를 추가하십시오.
스킬 M2

16

HTTParty 는 이것을 조금 더 쉽게 만듭니다 (그리고 내가 본 다른 예제에서는 작동하지 않는 중첩 된 json 등에서 작동합니다.

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

6

실제 사례, NetHttps 를 통해 새 배포에 대해 Airbrake API에 알립니다.

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)

메모:

Authorization 헤더 세트 헤더 req['Authorization'] = "Token xxxxxxxxxxxx" 또는 http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html을 통해 인증을 수행하는 경우


...하지만 정직이 멋진이며 모든하지만 실제 라이브에서 나는 것 바로 사용 HTTParty stackoverflow.com/a/14491995/473040 : ... 당신은 https를 처리 다루고있는 특히
equivalent8

이미 그물 / HTTP에 의해 필요로 URI를 요구하는 것은 쓸모가
noraj

@ equivalent8 : "실생활에서는 HTTParty를 사용합니다"-즉, 린 gem을 빌드하지 않거나 다른 종속성을 원하지 않는 한. :)
Sergio Tulentsev

@SergioTulentsev는 동의합니다 ... 불필요한 종속성을 도입하고 싶지 않은 gem / lib (또는 Ruby 기반 마이크로 서비스)를 빌드하지 않는 한;)
equivalent8

5

Tom이 링크하는 것보다 훨씬 더 간단해야하는 사람들을위한 간단한 json POST 요청 예제 :

require 'net/http'

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

19
이것은 작동하는 것처럼 보이지만 post_form은 매개 변수를? key = value & key = value 구문으로 변환합니다. 요청 본문을 JSON 문자열로 설정하여 POST를 수행하려면 다른 솔루션이 필요하다고 생각합니다.
Ben Gotow 2013

이것은 깊게 중첩 된 json에서는 작동하지 않습니다. 첫 번째 수준을 넘어서는 것은 문자열이됩니다.
neoneye

그냥 외모가 아닙니다. 효과가있다. 간단합니다. 하지만 예제와 같은 간단한 것들은 잘 작동합니다
Christoffer

4
이것은 근본적으로 JSON 요청이 아닙니다. 이것은 urlencoded 시체입니다. JSON이 없습니다. 헤더는 심지어 많은 것을 말합니다. 이것은 어떤 예에서도 작동하지 않습니다.
raylu

4
이 대답은 틀 렸습니다. 그것은 "json"이라는 URL에 대한 mime / multipart의 POST입니다.
John Haugeland

4

2020 년입니다-아무도 Net::HTTP더 이상 사용해서는 안되며 모든 답변이 그렇게 말하는 것 같습니다. Faraday와 같은 더 높은 수준의 보석을 사용하세요. - Github에서


즉, 제가 좋아하는 것은 HTTP API 호출을 둘러싼 래퍼입니다.

rv = Transporter::FaradayHttp[url, options]

이렇게하면 추가 종속성없이 HTTP 호출을 가짜로 만들 수 있습니다.

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

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

가짜가 어떻게 생겼는지 이렇게

나는 HTTP 모킹 / 스터 빙 프레임 워크가 있다는 것을 알고 있지만, 적어도 지난번에 조사했을 때 요청을 효율적으로 검증 할 수 없었고, 원시 TCP 교환이 아닌 HTTP를위한 것이 었습니다.이 시스템을 사용하면 모든 API 통신을위한 통합 프레임 워크.


해시를 json으로 빠르고 더럽게 변환하고 싶다면 json을 원격 호스트에 보내 API를 테스트하고 루비에 대한 응답을 구문 분석하는 것이 아마도 추가 gem을 사용하지 않고 가장 빠른 방법 일 것입니다.

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

바라건대 이것은 말할 필요도 없지만 프로덕션에서 사용하지 마십시오.


NTLM 인증을 사용하여이 작업을 수행 할 수 없습니다. 따라서 Net :: HTTP는 여전히이를 지원하는 라이브러리를 가진 유일한 것입니다.
Rhuan

3
동의 '아무도는 사용해야 Net::HTTP주장'
JellicleCat

1
때문에의을 downvoted nobody should be using Net::HTTP any more@bbozo
파트 리 훙 옥수

3

이것은 JSON 객체와 작성된 응답 본문이있는 Ruby 2.4 HTTPS Post에서 작동합니다.

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'라는 경량 http 요청 클라이언트를 좋아한다.

gem install unirest

용법:

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는 사용하기 어려울 수 있습니다.

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

이 코드는 작동하지 않습니다. 다음과 같이 #start를 사용하여 Net :: HTTP를 초기화해야합니다.Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |client|
Tyler

루비 2.3.7p456 (2018-03-28 개정 63024)에서 작동 [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'
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.