Как заставить Grape принимать и возвращать только JSON?

Как мне ограничить мой API, чтобы он принимал и отвечал только в формате json на Rails и Grape, я пробовал format :json на своем контроллере Grape и (например) я могу получить к нему доступ на example.com/api/v1/ping.json, но я также могу получить к нему доступ через example.com/api/v1/ping.xml, example.com/api/v1/ping.foobar, и список расширений можно продолжить...

То, что я хотел бы сделать, это выдать ошибку на example.com/api/v1/ping.not_json_extensions.

Я использую:

  • рельсы (4.1.1)
  • виноград (0.7.0)

/config/routes.rb

mount API::Base => '/api'

/controllers/api/base.rb

module API
 class Base < Grape::API
  mount API::V1::Base
 end
end

/controllers/api/v1/base.rb

module API
 module V1
  class Base < Grape::API
   format :json
   mount API::V1::Ping
  end
 end

конец

/controllers/api/v1/ping.rb

module API
 module V1
  class Ping < Grape::API
    include API::V1::Defaults
    desc 'Returns pong.'
    get :ping do
      { ping: params[:pong] || 'pong' }
    end
  end
 end

конец


person Community    schedule 21.06.2014    source источник


Ответы (1)


Глядя на исходный код Grape, кажется, что это было запланированное поведение, но изменение для предотвращения утечек памяти эффективно сломало его. .

Вы можете реализовать правильное поведение «вручную», добавив явную проверку в свой класс API (в /controllers/api/base.rb):

before do
  # Make sure the format specified by the request extension is one
  # we support
  parts = request.path.split('.')

  if parts.size > 1
    extension = parts.last

    if !extension.eql? 'json'
      throw :error, {
        status: 406,
        message: "The requested format '#{extension}' is not supported."
      }
    end
  end
end

Этот код практически дословно скопирован из исходного кода Grape (в lib). /grape/middleware/formatter.rb) и как сама Grape проверяет расширение, используемое в запросе.

В этом файле negotiate_content_type отвечает за проверку того, поддерживается ли запрашиваемый формат API, и явно отдает приоритет расширению запроса. Однако метод, который анализирует расширение из URI, format_from_extension, также проверяет, поддерживается ли формат, и возвращает nil, если это не так, как если бы расширения вообще не было. В результате negotiate_content_type никогда не вызовет ошибку, если в расширении запроса указан неподдерживаемый формат, даже если он явно предназначен для этого.

Вы можете «исправить» это, изменив код на странице . formatter.rb:109 из

# avoid symbol memory leak on an unknown format
return extension.to_sym if content_type_for(extension)

просто

return extension.to_sym

Комментарий предполагает, что код был написан таким образом по какой-то причине, поэтому действуйте с осторожностью.

person Community    schedule 21.06.2014
comment
Я вижу утечку памяти, поскольку злоумышленник может спамить вас множеством неподдерживаемых форматов. Таким образом, это приведет к постоянному увеличению кэша символов. Так что это в основном исправление памяти и безопасности. Исправление для меня было бы другим броском! - person Nick; 07.11.2014
comment
На самом деле это немного сложнее, так как изменение, которое я предложил, нарушает многие спецификации. Глядя на это. - person Nick; 07.11.2014
comment
Саймон, я отправлю патч, github.com/realtymaps/grape/blob/v.0.9.0_format_patch/lib/grape/ github.com/realtymaps/grape/commit/ - person Nick; 08.11.2014