Проверьте ответ HTTP Ruby на успех
Как правильно проверить ответ от Net:: HTTP:: Get (например) для "успеха" (т.е. код возврата 2xx)? Документация, похоже, печально умалчивает об этом простом вопросе.
У меня есть:
response=Net::HTTP.new( host, port ).request my_get_request # details not important
После кучи Google и почти случайного ввода текста я наконец решил, что это работает:
response.class < Net::HTTPSuccess
Действительно ли это канонический способ сделать это?
Ответы
Ответ 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