Ruby on Sinatra:根据参数模拟请求
Ruby on Sinatra: Imitate a request based on a parameter
我目前正在开发一个基于 Sinatra 的 Ruby API。此 API 主要从支持外部 API 集成的现有社交平台接收 GET 请求。
社交平台触发如下格式的GET请求(仅显示相关参数):
GET /{command}
参数:命令和文本
其中 text 是用户输入的字符串。
在我的例子中,params[:text] 实际上是一系列命令,由 space 分隔。我想要实现的是,例如: If params[:text]="corporate finance"
然后我希望我的 API 将请求解释为 GET 请求
/{命令}/corporate/finance
而不是使用字符串作为包含请求其余部分的参数来请求 /{command}。
我这边可以实现吗?社交平台的初始请求不能改变。
编辑:我认为解释我想要实现的目标的更好方法如下:
GET /list?text=corporate finance
应该和
一样endpoint/route
GET /list/corporate/finance
这不得影响来自社交平台的初始 GET 请求,因为它希望向用户显示包含文本的响应。有没有一种简洁的最佳实践方法?
get "/" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
end
可能会成功。虽然没有检查。
编辑:好的,之前的过滤器很愚蠢。基本上你也可以路由到“/”然后重定向。或者,甚至更好:
get "/:command" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
}
有很多方法可以实现这一点。您应该检查 sinatra 文档的路由部分 (https://github.com/sinatra/sinatra)
three 的回答应该可以解决问题,并且要绕过每个请求都会调用过滤器的事实,这样的条件应该做:
before do
if params[:text]
sub_commands = params[:text].split.join "/"
redirect "#{params[:command]}/#{sub_commands}"
end
end
我已经在演示应用程序中对其进行了测试,它似乎工作正常。
抱歉,我完全误解了你的问题,所以我用这个替换我的答案:
require 'sinatra'
get '/list/?*' do
"yep"
end
像这样,下面的路线都是一样的
您需要为每个命令添加例程或用 * 替换命令,并根据情况确定输出。
用户输入的params可以通过params hash引用。
http://localhost:4567/list
http://localhost:4567/list/corporate/finance
http://localhost:4567/list?text=corporate/finance
解决方法就是调用!方法。
我使用正则表达式来拦截匹配 /something 且没有其他参数(即 /something/something else)的调用。我觉得这一步可以做得更优雅
从那里开始,我拆分了我的命令:
get %r{^\/\w+$} do
params[:text] ? sub_commands="/"+params[:text].split.join("/") : sub_commands=""
status, headers, body = call! env.merge("PATH_INFO" => "/#{params[:command]}#{sub_commands}")
[status, headers, body]
end
这正是我所需要的,因为它激活了正确的端点,就好像 URL 是以通常的格式输入的,即 /command/subcommand1/subcommand2 等.
我目前正在开发一个基于 Sinatra 的 Ruby API。此 API 主要从支持外部 API 集成的现有社交平台接收 GET 请求。
社交平台触发如下格式的GET请求(仅显示相关参数):
GET /{command}
参数:命令和文本
其中 text 是用户输入的字符串。
在我的例子中,params[:text] 实际上是一系列命令,由 space 分隔。我想要实现的是,例如: If params[:text]="corporate finance"
然后我希望我的 API 将请求解释为 GET 请求 /{命令}/corporate/finance 而不是使用字符串作为包含请求其余部分的参数来请求 /{command}。
我这边可以实现吗?社交平台的初始请求不能改变。
编辑:我认为解释我想要实现的目标的更好方法如下:
GET /list?text=corporate finance
应该和
一样endpoint/routeGET /list/corporate/finance
这不得影响来自社交平台的初始 GET 请求,因为它希望向用户显示包含文本的响应。有没有一种简洁的最佳实践方法?
get "/" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
end
可能会成功。虽然没有检查。
编辑:好的,之前的过滤器很愚蠢。基本上你也可以路由到“/”然后重定向。或者,甚至更好:
get "/:command" do {
text = params[:text].split.join "/"
redirect "#{params[:command]}/#{text}"
}
有很多方法可以实现这一点。您应该检查 sinatra 文档的路由部分 (https://github.com/sinatra/sinatra)
three 的回答应该可以解决问题,并且要绕过每个请求都会调用过滤器的事实,这样的条件应该做:
before do
if params[:text]
sub_commands = params[:text].split.join "/"
redirect "#{params[:command]}/#{sub_commands}"
end
end
我已经在演示应用程序中对其进行了测试,它似乎工作正常。
抱歉,我完全误解了你的问题,所以我用这个替换我的答案:
require 'sinatra'
get '/list/?*' do
"yep"
end
像这样,下面的路线都是一样的 您需要为每个命令添加例程或用 * 替换命令,并根据情况确定输出。 用户输入的params可以通过params hash引用。
http://localhost:4567/list
http://localhost:4567/list/corporate/finance
http://localhost:4567/list?text=corporate/finance
解决方法就是调用!方法。
我使用正则表达式来拦截匹配 /something 且没有其他参数(即 /something/something else)的调用。我觉得这一步可以做得更优雅
从那里开始,我拆分了我的命令:
get %r{^\/\w+$} do
params[:text] ? sub_commands="/"+params[:text].split.join("/") : sub_commands=""
status, headers, body = call! env.merge("PATH_INFO" => "/#{params[:command]}#{sub_commands}")
[status, headers, body]
end
这正是我所需要的,因为它激活了正确的端点,就好像 URL 是以通常的格式输入的,即 /command/subcommand1/subcommand2 等.