#ruby #http
#ruby #http
Вопрос:
Я пытаюсь найти способ воспроизвести HTTP-запрос, который отправляет двоичные данные в полезной нагрузке, а также задает Content-Type: binary
заголовок, как следующая команда с cURL:
echo -e 'x14x00x00x00x70x69x6ex67x00x00' | curl -X POST
-H 'Content-Type: binary'
-H 'Accept: */*'
-H 'Accept-Encoding: gzip,deflate,sdch'
-H 'Accept-Language: en-US,en;q=0.8,pt;q=0.6'
-H 'Cookie: JSESSIONID=m1q1hkaptxcqjuvruo5qugpf'
--data-binary @-
--url 'http://202.12.53.123'
--trace-ascii /dev/stdout
Я уже пробовал использовать REST Client (https://github.com/rest-client/rest-client ) и HttpClient (https://github.com/nahi/httpclient), но безуспешно. Используя приведенный ниже код, сервер ответил HTTP 500. Кто-нибудь делал это раньше или это невозможно для целей, для которых были разработаны драгоценные камни?
Ruby code:
require 'rest-client'
request = RestClient::Request.new(
:method => :post,
:url => 'http://202.12.53.123',
:payload => %w[14 00 00 00 70 69 6e 67 00 00],
:headers => {
:content_type => :binary,
:accept => '*/*',
:accept_encoding => 'gzip,deflate,sdch',
:accept_language => 'en-US,en;q=0.8,pt;q=0.6',
:cookies => {'JSESSIONID' => 'm1q1hkaptxcqjuvruo5qugpf'}
}
)
request.execute
ОБНОВЛЕНИЕ (с одним из возможных решений)
В итоге я выполнил запрос с помощью HTTParty (следуя указаниям, данным @DemonKingPiccolo), и это сработало. Вот код:
require 'httparty'
hex_data = "14 00 00 00 70 69 6e 67 00 00"
response = HTTParty.post(
'http://202.12.53.123',
:headers => {
'Content-Type' => 'binary',
'Accept-Encoding' => 'gzip,deflate,sdch',
'Accept-Language' => 'en-US,en;q=0.8,pt;q=0.6'
},
:cookies => {'JSESSIONID' => 'm1q1hkaptxcqjuvruo5qugpf'},
:body => [hex_data.gsub(/s /,'')].pack('H*').force_encoding('ascii-8bit')
)
puts response.body, response.code, response.message, response.headers.inspect
Тело также может быть написано, как предложено @gumbo:
%w[14 00 00 00 70 69 6e 67 00 00].map { |h| h.to_i(16) }.map(amp;:chr).join
Комментарии:
1. httparty мог бы это сделать.
2. Вы сказали, что пытались «безуспешно», но что это значит?
3.
%w[14 00 00 00 70 69 6e 67 00 00]
делает не то, что вы можете подумать. Это создает массив, эквивалентный["14", "00", "00", "00", "70", "69", "6e", "67", "00", "00"]
. Может быть, вы скорее ищете%w[14 00 00 00 70 69 6e 67 00 00].map { |h| h.to_i(16) }.map(amp;:chr).join
4. Кстати,
binary
это недопустимое значение дляContent-Type
заголовка.Content-Type
ожидает значение в формате MIME-типа, т. е.type/subtype
. При отправке двоичных данных, которые вы обычно хотите использоватьapplication/octet-stream
.5. Вместо того, чтобы выполнять все эти операции с
hex_data
(gsub
,pack
,map
и т.д.), Почему бы просто не использовать строку с экранируемыми символами, как в моем примере?"x14x00x00x00x70x69x6ex67x00x00"
приведет к тому же самому.
Ответ №1:
Я только что попробовал это, и это сработало как шарм:
require "net/http"
uri = URI("http://example.com/")
http = Net::HTTP.new(uri.host, uri.port)
req = Net::HTTP::Post.new(uri.path)
req.body = "x14x00x00x00x70x69x6ex67x00x00"
req.content_type = "application/octet-stream"
http.request(req)
# => #<Net::HTTPOK 200 OK readbody=true>
Я проверил, что данные размещены правильно, используя RequestBin.
Net:: HTTP действительно груб по краям и не очень интересен в использовании (например, вам приходится форматировать заголовки файлов cookie вручную). Его главное преимущество в том, что он находится в стандартной библиотеке. Такой gem, как RestClient или HTTParty, может быть лучшим выбором, и я почти уверен, что любой из них будет обрабатывать двоичные данные по крайней мере так же легко.
Комментарии:
1. Спасибо @jordan, что представил мне Net :: HTTP. Я отредактировал описание вопроса с другими возможными решениями, которые я нашел.
2. В следующей строке: req = NET::HTTP::Post.new(uri.path) исправлена опечатка, это: req = Net :: HTTP::Post.new(uri.path)