Как отправить запрос на многоэлементную потоковую передачу с использованием httpclient в ruby - PullRequest
3 голосов
/ 20 мая 2019

Я пытаюсь получить сообщение о многочастной потоковой передаче, работающее с HTTPClient для Ruby. После чего я сталкиваюсь с двумя проблемами.

Задача 1 : Во-первых, если я пытаюсь сделать нормальный пост способом, описанным в документации; и я возвращаю его через httpbin.org Я вижу, что это происходит:

Код

        File.open(path_to_my_file) do |file|
          body = [{ 'Content-Type' => 'application/atom+xml; charset=UTF-8',
                    :content => '<entry>...</entry>' },
                  { 'Content-Type' => 'video/mp4',
                    'Content-Transfer-Encoding' => 'binary',
                    :content => file }]
          res = @http_client.post('http://httpbin.org/post', body: body)
          response = res
          puts res.body

Результат

{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "{\"Content-Type\"=>\"application/atom+xml; charset=UTF-8\", :content=>\"<entry>...</entry>\"}": "", 
    "{\"Content-Type\"=>\"video/mp4\", \"Content-Transfer-Encoding\"=>\"binary\", :content=>#<File:{{path_to_file}}>}": ""
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "322", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Date": "Mon, 20 May 2019 06:43:17 GMT", 
    "Host": "httpbin.org", 
    "User-Agent": "HTTPClient/1.0 (2.8.3, ruby 2.6.0 (2018-12-25))"
  }, 
  "json": null, 
  "origin": "IP, IP", 
  "url": "https://httpbin.org/post"
}

Как видите, я не могу видеть содержимое файла, а только идентификатор, содержащий URI для файла; и поэтому я не знаю, как это исправить, чтобы я мог видеть и возвращать содержимое. Насколько я знаю, похоже, что он пытается увидеть объект File как String, что, конечно, не то, что я хотел бы, чтобы он делал.

задачи2: Всякий раз, когда я создаю тело динамически, это; Создание хеш-массива динамически с объектами, установленными в моем коде, и я пытаюсь отправить его асинхронно (что, я считаю, является правильным способом потоковой передачи в HTTPClient для Ruby, хотя я не совсем уверен) он отправляет все тело как данные, а не как форму или заголовки.

код

        request_body = []
        body.files.each do |k, v|
          request_body.push( { 'Content-Type' => v.content_type, :content => v.content })
        end
        body.values.each { |k, v| request_body << { k.to_sym => v }}

        #This creates the array correctly, although I just wanted to show how it was generated

        connection = @http_client.send(method + '_async', uri, body: request_body, header: headers)

        response = connection.pop
        # Starts reading result here

Ответ

  "args": {}, 
  "data": "%7B%22Content-Type%22%3D%3E%22video%2Fmp4%22%2C+%3Acontent%3D%3E%23%3CFile%3A%2Fhome%2Fuser%2Ffiles%2file.mp4%3E%7D=&%7B%3Avalue%3D%3E%22hello+world%22%7D=", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "247", 
    "Content-Type": "application/json", 
    "Date": "Mon, 20 May 2019 06:44:11 GMT", 
    "Host": "httpbin.org", 
    "User-Agent": "HTTPClient/1.0 (2.8.3, ruby 2.6.0 (2018-12-25))", 
    "ApplicationIdentifier": "identifier"
  }, 
  "json": null, 
  "origin": "IP, IP", 
  "url": "https://httpbin.org/post"
}

Как видите, он помещает все в данные, и я, честно говоря, не знаю, как заставить его отправлять сообщение с телом в виде формы, а не в виде данных. Я отправляю файл сюда как объект File. Я попытался отправить его как обычный пост вместо post_async, но, похоже, он не работает.

Кто-нибудь сталкивался с этими проблемами раньше и знает, как мне их исправить? (или вы видите, где я ошибся, чтобы хотя бы попытаться продвинуться немного дальше)

Заранее спасибо

1 Ответ

1 голос
/ 20 мая 2019

Что касается вашей первой проблемы, похоже, что документация неверна.Я провел несколько тестов, и тип содержимого выглядит как application / x-www-form-urlencoded.Вам необходимо явно указать тип содержимого:

body: body, header: {'Content-Type': 'multipart/form-data; boundary=ABC'}

Этого недостаточно.Вам также необходимо установить расположение содержимого вручную.Например:

      body = [{ 'Content-Type' => 'application/atom+xml; charset=UTF-8',
                'Content-Disposition' => 'form-data; name="name1"',
                :content => '<entry>...</entry>' },
              { 'Content-Type' => 'video/mp4',
                'Content-Disposition' => 'form-data; name="file"; filename="myfile.pdf"',
                'Content-Transfer-Encoding' => 'binary',
                :content => file }]

При этом httpbin сообщает об одном файле и одном параметре формы.

Ваша вторая проблема связана с тем же.Как ваши файлы, так и значения должны иметь установленное расположение содержимого.Например (быстрый и грязный, стиль может быть лучше):

files.each do |k, v|
    request_body << { 'Content-Type' => v.content_type, :content => v.content, 'Content-Disposition' => 'form-data; name="' + k + '"; filename="' + v.filename + '"' }
end
values.each { |k, v| request_body << { :content => v, 'Content-Disposition' => 'form-data; name="' + k + '"' }}

Обратите внимание, что вы должны избегать любого "в имени или имени файла.

...