【问题标题】:Standardizing api responses in a modular Sinatra application在模块化 Sinatra 应用程序中标准化 api 响应
【发布时间】:2012-12-15 13:19:15
【问题描述】:

我正在开发一个作为模块化 Sinatra Web 应用程序的 api,并希望标准化返回的响应,而不必明确这样做。我认为这可以通过使用中间件来实现,但在大多数情况下都失败了。以下示例应用程序是我目前所拥有的。

config.ru

require 'sinatra/base'
require 'active_support'
require 'rack'

class Person
  attr_reader :name, :surname
  def initialize(name, surname)
    @name, @surname = name, surname
  end
end

class MyApp < Sinatra::Base

  enable :dump_errors, :raise_errors
  disable :show_exceptions

  get('/string') do
    "Hello World"
  end

  get('/hash') do
    {"person" => { "name" => "john", "surname" => "smith" }}
  end

  get('/array') do
    [1,2,3,4,5,6,7, "232323", '3245235']
  end

  get('/object') do
    Person.new('simon', 'hernandez')
  end

  get('/error') do
    raise 'Failure of some sort'
  end
end

class ResponseMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    begin
      status, headers, body = @app.call(env)
      response = {'status' => 'success', 'data' => body}
      format(status, headers, response)
    rescue ::Exception => e
      response = {'status' => 'error', 'message' => e.message}
      format(500, {'Content-Type' => 'application/json'}, response)
    end
  end

  def format(status, headers, response)
    result = ActiveSupport::JSON.encode(response)
    headers["Content-Length"] = result.length.to_s
    [status, headers, result]
  end
end

use ResponseMiddleware
run MyApp

示例(JSON 格式):

/string
  Expected: {"status":"success","data":"Hello World"}
  Actual:   {"status":"success","data":["Hello World"]}

/hash (works)
  Expected: {"status":"success","data":{"person":{"name":"john","surname":"smith"}}}
  Actual:   {"status":"success","data":{"person":{"name":"john","surname":"smith"}}}

/array
  Expected: {"status":"success","data": [1,2,3,4,5,6,7,"232323","3245235"]}
  Actual:   {"status":"error","message":"wrong number of arguments (7 for 1)"}

/object
  Expected: {"status":"success","data":{"name":"simon","surname":"hernandez"}}
  Actual:   {"status":"success","data":[]}

/error (works)
  Expected: {"status":"error","message":"Failure of some sort"}
  Actual:   {"status":"error","message":"Failure of some sort"}

如果您执行代码,您将看到 /hash 和 /error 会返回所需的响应,但其余的则不会。理想情况下,我不想更改 MyApp 类中的任何内容。它目前正在 Sinatra 1.3.3、ActiveSupport 3.2.9 和 Rack 1.4.1 之上构建。

【问题讨论】:

    标签: ruby api sinatra rack middleware


    【解决方案1】:

    在 irc.freenode.org 上的#sinatra 的帮助下,我设法将其归结为我想要的。我将以下内容添加到 MyApp

    def route_eval
      result = catch(:halt) { super }
      throw :halt, {"result" => result}
    end
    

    然后我在 ResponseMiddleware 中更改了以下行:

    response = {'status' => 'success', 'data' => body}
    

    response = {'status' => 'success', 'data' => body["result"]}
    

    我所有的测试用例都通过了。

    【讨论】:

      猜你喜欢
      • 2013-06-19
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-11
      • 2014-05-23
      相关资源
      最近更新 更多