REXML:: RuntimeError (расширение объекта стало слишком большим)

После обновления до Ruby-1.9.3-p392 сегодня REXML выдает ошибку Runtime при попытке получить ответ XML по определенному размеру - все работает отлично, и при получении менее 25 записей XML не возникает ошибка, но после достигнут определенный порог длины ответа XML, я получаю эту ошибку:

Error occurred while parsing request parameters.
Contents:

RuntimeError (entity expansion has grown too large):
  /.rvm/rubies/ruby-1.9.3-p392/lib/ruby/1.9.1/rexml/text.rb:387:in `block in unnormalize'

Я понимаю, что это было изменено в самой последней версии Ruby: http://www.ruby-lang.org/en/news/2013/02/22/rexml-dos-2013-02-22/

В качестве быстрого исправления я изменил размер REXML::Document.entity_expansion_text_limit на большее число, и ошибка исчезла.

Существует ли менее рискованное решение?

Ответ 1

Эта проблема возникает, когда вы отправляете слишком много контента в виде ответа XML.

Чтобы устранить эту проблему: вам нужно ограничить данные (< 10k) в отдельном node (вместо отправки всех данных, показать усеченные данные и предоставить отдельную ссылку для просмотра полного содержимого).

Ошибка возникает из следующего файла: ruby-2.1.2/lib/ruby/2.1.0/rexml/text.rb

# Unescapes all possible entities
def Text::unnormalize( string, doctype=nil, filter=nil, illegal=nil )
  sum = 0
  string.gsub( /\r\n?/, "\n" ).gsub( REFERENCE ) {
    s = Text.expand($&, doctype, filter)
    if sum + s.bytesize > Security.entity_expansion_text_limit
      raise "entity expansion has grown too large"
    else
      sum += s.bytesize
    end
    s
  }
end

Предел ruby-2.1.2/lib/ruby/2.1.0/rexml/text.rb по умолчанию - 10240, что означает 10k данных на node.

REXML уже по умолчанию использует только 10000 подстановок на один документ, поэтому максимальная сумма текста, которая может быть сгенерирована подстановкой сущности, будет составлять около 98 мегабайт. (См. https://www.ruby-lang.org/en/news/2013/02/22/rexml-dos-2013-02-22/)

Ответ 2

Это звучит как много XML. Вам действительно нужно все это получить? Может быть, вы можете просто запросить определенные поля с удаленного сервера? Один из вариантов может состоять в том, чтобы попробовать другой синтаксический анализатор XML (Nokogiri). Другой вариант, возможно, использовать что-то другое, кроме XML, как транспорт (JSON? Binary?).