Ruby отправить запрос JSON

Как отправить запрос JSON в рубине? У меня есть объект JSON, но я не думаю, что смогу просто сделать .send. Должен ли я использовать javascript для отправки формы?

Или я могу использовать класс net / http в ruby?

С заголовком - тип содержимого = json и тело объекта json?


person Andy    schedule 08.01.2010    source источник


Ответы (9)


HTTParty, я думаю, немного упрощает это (и работает с вложенным json и т. д., что, похоже, не сработало в других примерах, которые я ' видел.

require 'httparty'
HTTParty.post("http://localhost:3000/api/v1/users", body: {user: {email: '[email protected]', password: 'secret'}}).body
person Brian Armstrong    schedule 24.01.2013

пример из реальной жизни, уведомить Airbrake API о новом развертывании через 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)

Примечания:

если вы выполняете аутентификацию через заголовок авторизации, установите header req['Authorization'] = "Token xxxxxxxxxxxx" или http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html.

person equivalent8    schedule 05.09.2016
comment
... но, честно говоря, это круто, но в реальной жизни я бы просто использовал HTTParty stackoverflow.com/a/14491995/473040 :) ... особенно если вы имеете дело с обработкой https - person equivalent8; 26.03.2018
comment
требовать uri бесполезно, так как он уже требуется net / http - person noraj; 21.08.2018
comment
@ equal8: в реальной жизни я бы просто использовал HTTParty - то есть, если вы не создаете бережливую жемчужину или иным образом не хотите другую зависимость. :) - person Sergio Tulentsev; 07.12.2018
comment
@SergioTulentsev согласен ... если вы не создаете gem / lib (или микросервис на основе Ruby), где вы не хотите вводить ненужные зависимости;) - person equivalent8; 11.12.2018

Простой пример запроса JSON POST для тех, кому он нужен, даже проще, чем тот, на который ссылается Том:

require 'net/http'

uri = URI.parse("http://www.example.com/search.json")
response = Net::HTTP.post_form(uri, {"search" => "Berlin"})
person Christoffer    schedule 28.08.2012
comment
Похоже, это должно работать, но post_form переводит параметры в синтаксис? Key = value & key = value. Если вы хотите выполнить POST с телом запроса, установленным в строку JSON, я думаю, вам нужно другое решение. - person Ben Gotow; 24.04.2013
comment
Это не работает с глубоко вложенным json. Все, что выше первого уровня, становится строкой. - person neoneye; 15.05.2014
comment
Не просто так выглядит. Оно работает. Это просто конечно. но для простых вещей, таких как пример, который я привел, он отлично работает - person Christoffer; 30.09.2015
comment
По сути, это не запрос JSON. Это тело с URL-кодом. Нет JSON. Об этом и сказано в заголовке. Это никогда не работает ни с одним примером. - person raylu; 21.10.2016
comment
Это неверный ответ. Это POST в mime / multipart на URL-адрес, в котором написано json. - person John Haugeland; 21.12.2016
comment
Вы можете сделать это запросом JSON так: require "json"; uri = …; Net::HTTP.post(uri, { "search" => "Berlin" }.to_json, "Content-Type" => "application/json") - person Henrik N; 16.12.2019

Это работает на Ruby 2.4 HTTPS Post с записанным объектом JSON и текстом ответа.

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
person szabcsee    schedule 11.03.2019

Наступил 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

Где фейкер выглядит примерно так: this

Я знаю, что существуют фреймворки имитации / заглушки HTTP, но, по крайней мере, когда я исследовал в прошлый раз, они не позволяли мне эффективно проверять запросы, и они были только для HTTP, а не, например, для необработанных обменов TCP, эта система позволяет мне иметь единая структура для всего API-взаимодействия.


Предполагая, что вы просто хотите быстро и грязно преобразовать хэш в json, отправьте json на удаленный хост, чтобы протестировать API и проанализировать ответ на ruby, это, вероятно, самый быстрый способ без использования дополнительных драгоценных камней:

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

Надеюсь, это само собой разумеется, но не используйте это в продакшене.

person bbozo    schedule 19.11.2013
comment
Вы не можете сделать это с помощью проверки подлинности NTLM. Таким образом, Net :: HTTP по-прежнему единственный, у которого есть поддерживающая его библиотека. - person Rhuan; 07.05.2020
comment
Не согласен с утверждением "никто не должен использовать Net::HTTP" - person JellicleCat; 11.08.2020
comment
Проголосовали против nobody should be using Net::HTTP any more @bbozo - person Patricio Sard; 02.09.2020

Мне нравится этот легкий клиент HTTP-запросов под названием `unirest '

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
person tokhi    schedule 05.04.2016

API net / http может быть трудным в использовании.

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
person Moriarty    schedule 22.05.2015
comment
Этот код не работает. Вам нужно инициализировать Net :: HTTP с помощью #start следующим образом: Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |client| - person Tyler; 16.12.2015
comment
Работает с ruby ​​2.3.7p456 (28.03.2018 ревизия 63024) [universal.x86_64-darwin18] - person Moriarty; 19.07.2019

person    schedule
comment
Мне нравится ваше предложение использовать URI для обработки имени хоста и порта, что в противном случае довольно утомительно. Но вы забыли установить uri.path в Post.new (...): req = Net::HTTP::Post.new(uri.path, initheader = {'Content-Type' =>'application/json'}) - person ArnauOrriols; 27.05.2014
comment
Самый простой и понятный ответ. Отлично. - person joelc; 20.07.2015
comment
http.request(req).read_body, чтобы прочитать текст ответа. Большой! - person iGian; 26.06.2018
comment
Я почти уверен, что это изменилось в 2.4.1, но боже мой. Этот синтаксис груб. Он знает, что у него есть URI из Post.new (), так зачем вам заново передавать значения, разделяя их в start (). Валовой. Неудивительно, что в Ruby так много других пакетов, которые имеют дело с http. - person Rambatino; 02.08.2018

person    schedule
comment
Какое исключение следует указать - person Mio; 17.02.2016
comment
Для запросов https просто добавьте: http.use_ssl = true. - person Skill M2; 11.12.2016