使用Ruby Sinatra创建单页代理

使用Ruby Sinatra创建单页代理,ruby,proxy,sinatra,Ruby,Proxy,Sinatra,我试图使用Ruby Sinatra为特定网页创建一个简单的代理。我可以用C#来做,但我似乎无法为Sinatra解决这个问题,C#代码如下: <%@ WebHandler Language="C#" Class="Map" %> using System; using System.Web; using System.Net; using System.IO; public class Map : IHttpHandler { static void CopyStream(Str

我试图使用Ruby Sinatra为特定网页创建一个简单的代理。我可以用C#来做,但我似乎无法为Sinatra解决这个问题,C#代码如下:

<%@ WebHandler Language="C#" Class="Map" %>

using System;
using System.Web;
using System.Net;
using System.IO;

public class Map : IHttpHandler {

static void CopyStream(Stream input, Stream output)
{
    byte[] buffer = new byte[0x1000];
    int read;
    while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
        output.Write(buffer, 0, read);
}

public void ProcessRequest(HttpContext context)
{
    string gmapUri = string.Format("http://maps.google.com/maps/api/staticmap{0}", context.Request.Url.Query);
    WebRequest request = WebRequest.Create(gmapUri);

    using (WebResponse response = request.GetResponse())
    {
        context.Response.ContentType = response.ContentType;
        Stream responseStream = response.GetResponseStream();

        CopyStream(responseStream, context.Response.OutputStream);
    }
}

public bool IsReusable {
    get {
        return false;
    }
}

}
我假设Sinatra one不工作(获取404),因为它只是将请求传递给同一域中的页面。任何hep都将不胜感激

编辑:

在铁皮人的帮助下,我想出了一个简洁的解决方案,对我来说效果很好:

get '/proxy/path' do
   URI.parse(<URI> + request.query_string.gsub("|", "%7C")).read
end
get'/proxy/path'do
parse(+request.query_string.gsub(“|“,“%7C”)).read
结束

谢谢您的帮助。

如果您想让Sinatra应用程序检索URL,您需要启动某种HTTP客户端:

get '/mapsproxy/staticmap' do
  require 'open-uri'
  open('http://maps.google.com/maps/api/staticmap').read
end
我认为这会起作用,并且是尽可能少的

如果需要更多的可调整性,可以使用

而且,我认为这个架子可以做到。西纳特拉是建在架子上的,但我已经有一段时间没有达到那个水平了

我仍然需要找到一种从响应中提取contentType的方法

从文档中:

我还没有对此进行测试,但我认为块的返回值将分配给
body
。如果不起作用,请尝试:

content_type = ''
body = ''
open("http://www.ruby-lang.org/en") {|f|
  content_type = f.content_type     # "text/html"
  body = f.read
}

但我认为第一种方法会奏效。

在锡人和TK-421的帮助下,我已经找到了一个解决方案,请参见下面的Sinatra路线:

get '/proxy/path' do
  require 'open-uri'
  uri = URI.parse(<URI>)
  getresult = uri.read
  halt 200, {'Content-Type' => getresult.content_type}, getresult
end
get'/proxy/path'do
需要“打开uri”
uri=uri.parse()
getresult=uri.read
halt 200,{'Content-Type'=>getresult.Content\u-Type},getresult
结束
只需将
替换为您需要的页面,就可以了

再玩一段时间后,我就想到了:

get '/proxy/path' do
   URI.parse(<URI> + request.query_string.gsub("|", "%7C")).read
end
get'/proxy/path'do
parse(+request.query_string.gsub(“|“,“%7C”)).read
结束

正如前面提到的,您需要
在代码顶部要求“openuri”
。使用
gsub
的原因是,由于某些原因,如果保留它们,解析将失败,并且我的浏览器不会自动对它们进行编码。

您需要添加一些异常处理,并且可能希望使用
超时
模块在请求花费太长时间时提供更好的控制。请参阅示例。它似乎可以处理基于文本的响应,尽管它确实重新格式化了响应,但不会重新格式化图像响应。我认为我需要以某种方式将响应流式传输到Sinatra响应…不应该有任何重新格式化,因为开放URI在不进行任何转换的情况下流式传输数据;它基本上是一个文件I/O,与文本/二进制无关。除了使用OpenURI检索大量文本外,我还将MP3、PDF和图像检索到磁盘。西纳特拉可能在做些什么。有关流媒体示例,请参阅我最后的评论。没问题。我还在编辑。对于你的问题+1,因为它提醒了我Sinatra有多酷。我已经有一段时间没玩了,我错过了它。也可以看看西纳特拉的老大哥,他坐在西纳特拉和Rails之间。干杯。它真的很酷,我才刚刚开始使用它,我对它的威力感到惊讶。我来看看帕德里诺。在将新请求响应导入Sinatra one时仍然存在问题。但我比一小时前进步了很多,谢谢你的帮助。铁皮人给出了正确的答案。很高兴看到它在工作。那么,你更喜欢Ruby而不是C吗实际上,您可以使用
return getresult
来代替
halt 200,{'Content-Type'=>getresult.Content\u-Type},getresult
,因为uri会返回完整的响应,据我所知。我从来都不喜欢C#,只在工作中使用它,我更喜欢用解释语言来编写自己的代码(lisp、Scheme、Clojure、JavaScript)。我对Ruby很陌生,但我很喜欢:)不要
在块中要求
。。。这简直是浪费。并不是说它每次都会加载lib,而是它会检查它是否已经加载了它。”实际上,您可以使用return getresult来代替halt 200,{'Content-Type'=>getresult.Content\u Type},getresult作为uri返回一个完整的响应“您不需要使用
return
。这在Ruby中是隐含的,它返回退出块之前看到的最后一个值。您也不需要解析URI
open
对字符串URL很满意,因此您正在做一些不需要的工作,实际上会妨碍您提取所需的
内容类型
信息。
content_type = ''
body = ''
open("http://www.ruby-lang.org/en") {|f|
  content_type = f.content_type     # "text/html"
  body = f.read
}
get '/proxy/path' do
  require 'open-uri'
  uri = URI.parse(<URI>)
  getresult = uri.read
  halt 200, {'Content-Type' => getresult.content_type}, getresult
end
get '/proxy/path' do
   URI.parse(<URI> + request.query_string.gsub("|", "%7C")).read
end