RubyはJSONリクエストを送信します


86

RubyでJSONリクエストを送信するにはどうすればよいですか?私はJSONオブジェクトを持っていますが、私はそれができるとは思いません.send。javascriptにフォームを送信させる必要がありますか?

または、Rubyでnet / httpクラスを使用できますか?

ヘッダー付き-コンテンツタイプ= jsonおよび本体jsonオブジェクト?

回答:


76
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 2014年

1
最もシンプルでクリーンな応答。これは素晴らしい。
joelc 2015

http.request(req).read_body応答本文を読み取ります。すごい!
iGian

1
2.4.1で変更されたと確信していますが、私の神様。その構文は大雑把です。Post.new()からのURIがあることを知っているので、start()で値を分割して再渡す必要があるのはなぜですか。キモい。ルビーにはhttpを扱うパッケージが他にもたくさんあるのも不思議ではありません。
ランバティーノ2018

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

17

HTTPartyを使用すると、これが少し簡単になります(ネストされたjsonなどで機能しますが、これまでに見た他の例では機能しなかったようです。

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

6

実際の例では、NetHttpsを介して新しいデプロイについてAirbrakeAPIに通知します

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

uriを要求することはnet / httpによってすでに要求されているので役に立たない
noraj 2018

@ equivalent8:「実際にはHTTPartyを使用するだけです」-つまり、無駄のないgemを構築している場合、または別の依存関係を必要としない場合を除きます。:)
Sergio Tulentsev 2018

@SergioTulentsevは同意します...不要な依存関係を導入したくないgem / lib(またはRubyベースのマイクロサービス)を構築している場合を除きます;)
同等

4

トムがリンクしているものよりもさらに単純なものを必要とする人のための単純なjsonPOSTリクエストの例:

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を実行する場合は、別のソリューションが必要だと思います。
ベンゴトウ2013

これは、深くネストされたjsonでは機能しません。最初のレベルを超えるものはすべて文字列になります。
neoneye 2014年

のように見えるだけではありません。できます。確かに簡単です。しかし、私が与えた例のような単純なものについては、それはうまく機能します
Christoffer 2015

4
これは基本的にJSONリクエストではありません。これはurlencoded本体です。JSONはありません。ヘッダーにも同じことが書かれています。これは、どの例でも機能しません。
raylu 2016年

4
この答えは正しくありません。これは、mime / multipartの、「json」と書かれたURLへのPOSTです。
John Haugeland 2016

4

誰も使ってはならない-それは2020年だNet::HTTP、それ以上とすべての答えは、そう言っているように見えるように、ファラデーのような、より高いレベルの宝石を使用する-のGithub


そうは言っても、私がやりたいのはHTTPapi呼び出しのラッパーです。

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モック/スタブフレームワークがあることは知っていますが、少なくとも前回調査したときは、リクエストを効率的に検証できず、HTTP専用であり、たとえば生のTCP交換用ではありませんでした。このシステムでは、すべてのAPI通信のための統一されたフレームワーク。


ハッシュをjsonにすばやくダーティに変換したい場合は、jsonをリモートホストに送信してAPIをテストし、rubyへの応答を解析します。これは、追加のgemを使用せずにおそらく最速の方法です。

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

言うまでもないことですが、本番環境では使用しないでください。


2
笑、なぜすべての嫌いなのですか?:)投稿には、本番
環境

NTLM認証を使用してこれを行うことはできません。したがって、Net :: HTTPは、それをサポートするライブラリを持っている唯一のものです。
ルアン

1
'誰も使用してはならないNet::HTTP'アサーションに同意しない
JellicleCat

@bbozoのためにnobody should be using Net::HTTP any more反対票を投じた
Patricio Sard

3

これは、JSONオブジェクトと応答本文が書き出されたruby 2.4 HTTPSPostで機能します。

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 / httpapiは使いにくい場合があります。

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|
タイラー

ルビー2.3.7p456(2018年3月28日リビジョン63024)で動作[universal.x86_64-darwin18]
モリアーティ

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.