使用Ruby Sinatra创建单页代理

wm.*_*agg 7 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(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;
    }
}

}
Run Code Online (Sandbox Code Playgroud)

我尝试过的Ruby Sinatra代码如下:

require 'rubygems'
require 'sinatra'

get '/mapsproxy/staticmap' do
  request.path_info = 'http://maps.google.com/maps/api/staticmap'
  pass
end
Run Code Online (Sandbox Code Playgroud)

我假设Sinatra一个不起作用(获得404),因为只是将请求传递给同一域中的页面.任何肝脏将非常感激.

编辑:

随着铁皮人的帮助下,我想出了一个很好的解决方案简洁,这对我来说工作得很好:

get '/proxy/path' do
   URI.parse(<URI> + request.query_string.gsub("|", "%7C")).read
end
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助.

the*_*Man 4

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

get '/mapsproxy/staticmap' do
  require 'open-uri'
  open('http://maps.google.com/maps/api/staticmap').read
end
Run Code Online (Sandbox Code Playgroud)

我认为这会起作用,并且是尽可能少的。

如果您需要更多可调整性,您可以使用HTTPClient 。

另外,我认为 Rack 可以做到。Sinatra 是建立在 Rack 之上的,但我已经有一段时间没有玩过那个级别的游戏了。

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

来自Open-URI文档:

The opened file has several methods for meta information as follows since
it is extended by OpenURI::Meta.

open("http://www.ruby-lang.org/en") {|f|
    f.each_line {|line| p line}
    p f.base_uri         # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/>
    p f.content_type     # "text/html"
    p f.charset          # "iso-8859-1"
    p f.content_encoding # []
    p f.last_modified    # Thu Dec 05 02:45:02 UTC 2002
}
Run Code Online (Sandbox Code Playgroud)

出于您的目的,这样的事情应该有效:

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

我还没有测试过,但我认为该块的返回值将被分配给body. 如果这不起作用,请尝试:

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

但我认为第一个会起作用。