Подтвердить что ты не робот

Проверьте ответ HTTP Ruby на успех

Как правильно проверить ответ от Net:: HTTP:: Get (например) для "успеха" (т.е. код возврата 2xx)? Документация, похоже, печально умалчивает об этом простом вопросе.

У меня есть:

response=Net::HTTP.new( host, port ).request my_get_request # details not important

После кучи Google и почти случайного ввода текста я наконец решил, что это работает:

response.class < Net::HTTPSuccess

Действительно ли это канонический способ сделать это?

4b9b3361

Ответ 1

Для Net::HTTP, да, проверка класса объекта ответа - это способ сделать это. Использование kind_of? немного яснее (но функционально эквивалентно использованию <):

response.kind_of? Net::HTTPSuccess

Вызов value в response также приведет к появлению Net::HTTPError, если код состояния не был успешным (что плохо named method...).

Если это возможно, вы можете захотеть использовать драгоценный камень вместо Net::HTTP, так как они часто предлагают лучшие API и производительность. Typhoeus и HTTParty - два хороших, среди других.

Ответ 2

Вы можете использовать инструкцию Ruby case, которая идиоматически выполняет сопоставления классов, благодаря использованию === под капотом.

Вот пример от клиента JSON, который ловит определенные ошибки, но в остальном просто возвращает сообщение сервера:

  case response
    when Net::HTTPSuccess
      JSON.parse response.body
    when Net::HTTPUnauthorized
      {'error' => "#{response.message}: username and password set and correct?"}
    when Net::HTTPServerError
      {'error' => "#{response.message}: try again later?"}
    else
      {'error' => response.message}
  end

Примечание выше Net:: родительские классы HTTPResponse (например, Net::HTTPServerError) тоже работают.

Ответ 3

Если все, что вы хотите захватить, это код статуса HTTP внешнего API или веб-сайта, попробуйте Net::HTTP.get_response.

Net::HTTP.get(url) возвращает строку. Вы не сможете легко проанализировать ответ заголовка от него:

url = URI('http://example.com')
string_response = Net::HTTP.get(url)
# => "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        background-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-family: \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        padding: 50px;\n        background-color: #fff;\n        border-radius: 1em;\n    }\n    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;\n    }\n    @media (max-width: 700px) {\n        body {\n            background-color: #fff;\n        }\n        div {\n            width: auto;\n            margin: 0 auto;\n            border-radius: 0;\n            padding: 1em;\n        }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</h1>\n    <p>This domain is established to be used for illustrative examples in documents. You may use this\n    domain in examples without prior coordination or asking for permission.</p>\n    <p><a href=\"http://www.iana.org/domains/example\">More information...</a></p>\n</div>\n</body>\n</html>\n"

string_response.class
# => String
string_response.kind_of? Net::HTTPSuccess
# => false

status_response = Net::HTTP.get_response(url)
# => #<Net::HTTPOK 200 OK readbody=true>
status_response.class
# => Net::HTTPOK
status_response.kind_of? Net::HTTPSuccess
# => true