Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating a single page proxy using Ruby Sinatra

I am trying to use Ruby Sinatra to create a simple proxy for a specific web page. I can do it in C#, I just can't seem to work it out for Sinatra, the C# code is below:

<%@ 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;
    }
}

}

The Ruby Sinatra code I have tried is as follows:

require 'rubygems'
require 'sinatra'

get '/mapsproxy/staticmap' do
  request.path_info = 'http://maps.google.com/maps/api/staticmap'
  pass
end

I am assuming that the Sinatra one does not work (get a 404) as is is only passing the request to pages in the same domain. Any hep would be greatly appreciated.

EDIT:

With the Tin Man's help I've come up with a nice succinct solution, which works well for me:

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

Thanks for all the help.

like image 416
wm.wragg Avatar asked Feb 11 '11 14:02

wm.wragg


2 Answers

If you want your Sinatra app to retrieve the URL, you'll need to fire up a HTTP client of some sort:

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

I think this will work and is about as minimal as you can get.

You could use HTTPClient if you need more tweakability.

Also, I think that Rack can do it. Sinatra is built on top of Rack, but it's been a while since I played at that level.

I still need to find a way to extract the contentType from the response

From the Open-URI docs:

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
}

For your purposes something like this should work:

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

I haven't tested that, but I think the return value of the block will be assigned to body. If that doesn't work then try:

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

but I think the first will work.

like image 106
the Tin Man Avatar answered Nov 03 '22 11:11

the Tin Man


With the help of the Tin Man and TK-421 I've worked out a solution, see the Sinatra route below:

get '/proxy/path' do
  require 'open-uri'
  uri = URI.parse(<URI>)
  getresult = uri.read
  halt 200, {'Content-Type' => getresult.content_type}, getresult
end

Just replace the <URI> with the page you require, and you're good to go.

After some more playing this is what I've come up with:

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

As mentioned else where you need to require 'open-uri' at the top of the code. The reason for the gsub is that for some reason the parse fails if they are left in, and my browser doesn't encode them automatically.

like image 27
wm.wragg Avatar answered Nov 03 '22 10:11

wm.wragg