Added Sinatra API explorer example app.
git-svn-id: https://google-api-ruby-client.googlecode.com/svn/trunk@52 c1d61fac-ed7f-fcc1-18f7-ff78120a04ef
This commit is contained in:
		
							parent
							
								
									e50442091c
								
							
						
					
					
						commit
						4b7fd4490c
					
				| 
						 | 
					@ -0,0 +1,509 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env ruby
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# INSTALL
 | 
				
			||||||
 | 
					#   sudo gem install sinatra liquid
 | 
				
			||||||
 | 
					# RUN
 | 
				
			||||||
 | 
					#   ruby examples/sinatra/buzz_api.rb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					root_dir = File.expand_path("../../..", __FILE__)
 | 
				
			||||||
 | 
					lib_dir = File.expand_path("./lib", root_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$LOAD_PATH.unshift(lib_dir)
 | 
				
			||||||
 | 
					$LOAD_PATH.uniq!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					require 'rubygems'
 | 
				
			||||||
 | 
					begin
 | 
				
			||||||
 | 
					  require 'sinatra'
 | 
				
			||||||
 | 
					  require 'liquid'
 | 
				
			||||||
 | 
					  require 'signet/oauth_1/client'
 | 
				
			||||||
 | 
					  require 'google/api_client'
 | 
				
			||||||
 | 
					rescue LoadError
 | 
				
			||||||
 | 
					  STDERR.puts "Missing dependencies."
 | 
				
			||||||
 | 
					  STDERR.puts "sudo gem install sinatra liquid signet google-api-client"
 | 
				
			||||||
 | 
					  exit(1)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CSS = <<-CSS
 | 
				
			||||||
 | 
					/* http://meyerweb.com/eric/tools/css/reset/ */
 | 
				
			||||||
 | 
					/* v1.0 | 20080212 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html, body, div, span, applet, object, iframe,
 | 
				
			||||||
 | 
					h1, h2, h3, h4, h5, h6, p, blockquote, pre,
 | 
				
			||||||
 | 
					a, abbr, acronym, address, big, cite, code,
 | 
				
			||||||
 | 
					del, dfn, em, font, img, ins, kbd, q, s, samp,
 | 
				
			||||||
 | 
					small, strike, strong, sub, sup, tt, var,
 | 
				
			||||||
 | 
					b, u, i, center,
 | 
				
			||||||
 | 
					dl, dt, dd, ol, ul, li,
 | 
				
			||||||
 | 
					fieldset, form, label, legend,
 | 
				
			||||||
 | 
					table, caption, tbody, tfoot, thead, tr, th, td {
 | 
				
			||||||
 | 
					  margin: 0;
 | 
				
			||||||
 | 
					  padding: 0;
 | 
				
			||||||
 | 
					  border: 0;
 | 
				
			||||||
 | 
					  outline: 0;
 | 
				
			||||||
 | 
					  font-size: 100%;
 | 
				
			||||||
 | 
					  vertical-align: baseline;
 | 
				
			||||||
 | 
					  background: transparent;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					body {
 | 
				
			||||||
 | 
					  line-height: 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					ol, ul {
 | 
				
			||||||
 | 
					  list-style: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					blockquote, q {
 | 
				
			||||||
 | 
					  quotes: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					blockquote:before, blockquote:after,
 | 
				
			||||||
 | 
					q:before, q:after {
 | 
				
			||||||
 | 
					  content: '';
 | 
				
			||||||
 | 
					  content: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* remember to define focus styles! */
 | 
				
			||||||
 | 
					:focus {
 | 
				
			||||||
 | 
					  outline: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* remember to highlight inserts somehow! */
 | 
				
			||||||
 | 
					ins {
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					del {
 | 
				
			||||||
 | 
					  text-decoration: line-through;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* tables still need 'cellspacing="0"' in the markup */
 | 
				
			||||||
 | 
					table {
 | 
				
			||||||
 | 
					  border-collapse: collapse;
 | 
				
			||||||
 | 
					  border-spacing: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* End Reset */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body {
 | 
				
			||||||
 | 
					  color: #555555;
 | 
				
			||||||
 | 
					  background-color: #ffffff;
 | 
				
			||||||
 | 
					  font-family: 'Helvetica', 'Arial', sans-serif;
 | 
				
			||||||
 | 
					  font-size: 18px;
 | 
				
			||||||
 | 
					  line-height: 27px;
 | 
				
			||||||
 | 
					  padding: 27px 72px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					p {
 | 
				
			||||||
 | 
					  margin-bottom: 27px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					h1 {
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-variant: normal;
 | 
				
			||||||
 | 
					  font-weight: normal;
 | 
				
			||||||
 | 
					  font-family: 'Helvetica', 'Arial', sans-serif;
 | 
				
			||||||
 | 
					  font-size: 36px;
 | 
				
			||||||
 | 
					  line-height: 54px;
 | 
				
			||||||
 | 
					  margin-bottom: 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					h2 {
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-variant: normal;
 | 
				
			||||||
 | 
					  font-weight: normal;
 | 
				
			||||||
 | 
					  font-family: 'Monaco', 'Andale Mono', 'Consolas', 'Inconsolata', 'Courier New', monospace;
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  line-height: 27px;
 | 
				
			||||||
 | 
					  margin-top: 0px;
 | 
				
			||||||
 | 
					  margin-bottom: 54px;
 | 
				
			||||||
 | 
					  letter-spacing: 0.1em;
 | 
				
			||||||
 | 
					  text-transform: none;
 | 
				
			||||||
 | 
					  text-shadow: rgba(204, 204, 204, 0.75) 0px 1px 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#output h3 {
 | 
				
			||||||
 | 
					  font-style: normal;
 | 
				
			||||||
 | 
					  font-variant: normal;
 | 
				
			||||||
 | 
					  font-weight: bold;
 | 
				
			||||||
 | 
					  font-size: 18px;
 | 
				
			||||||
 | 
					  line-height: 27px;
 | 
				
			||||||
 | 
					  margin: 27px 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#output h3:first-child {
 | 
				
			||||||
 | 
					  margin-top: 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					ul, ol, dl {
 | 
				
			||||||
 | 
					  margin-bottom: 27px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					li {
 | 
				
			||||||
 | 
					  margin: 0px 0px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					form {
 | 
				
			||||||
 | 
					  float: left;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					form label, form input, form textarea {
 | 
				
			||||||
 | 
					  font-family: 'Monaco', 'Andale Mono', 'Consolas', 'Inconsolata', 'Courier New', monospace;
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					form label {
 | 
				
			||||||
 | 
					  margin-bottom: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					form input {
 | 
				
			||||||
 | 
					  width: 300px;
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					  padding: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					form textarea {
 | 
				
			||||||
 | 
					  height: 150px;
 | 
				
			||||||
 | 
					  min-height: 150px;
 | 
				
			||||||
 | 
					  width: 300px;
 | 
				
			||||||
 | 
					  min-width: 300px;
 | 
				
			||||||
 | 
					  max-width: 300px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#output {
 | 
				
			||||||
 | 
					  font-family: 'Monaco', 'Andale Mono', 'Consolas', 'Inconsolata', 'Courier New', monospace;
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  margin-left: 27px;
 | 
				
			||||||
 | 
					  padding: 27px;
 | 
				
			||||||
 | 
					  border: 1px dotted #555555;
 | 
				
			||||||
 | 
					  width: 1120px;
 | 
				
			||||||
 | 
					  max-width: 100%;
 | 
				
			||||||
 | 
					  min-height: 600px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#output pre {
 | 
				
			||||||
 | 
					  overflow: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					a {
 | 
				
			||||||
 | 
					  color: #000000;
 | 
				
			||||||
 | 
					  text-decoration: none;
 | 
				
			||||||
 | 
					  border-bottom: 1px dotted rgba(112, 56, 56, 0.0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					a:hover {
 | 
				
			||||||
 | 
					  -webkit-transition: all 0.3s linear;
 | 
				
			||||||
 | 
					  color: #703838;
 | 
				
			||||||
 | 
					  border-bottom: 1px dotted rgba(112, 56, 56, 1.0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					p a {
 | 
				
			||||||
 | 
					  border-bottom: 1px dotted rgba(0, 0, 0, 1.0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					h1, h2 {
 | 
				
			||||||
 | 
					  color: #000000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					h3, h4, h5, h6 {
 | 
				
			||||||
 | 
					  color: #333333;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.block {
 | 
				
			||||||
 | 
					  display: block;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					button {
 | 
				
			||||||
 | 
					  margin-bottom: 72px;
 | 
				
			||||||
 | 
					  padding: 7px 11px;
 | 
				
			||||||
 | 
					  font-size: 14px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					CSS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					JAVASCRIPT = <<-JAVASCRIPT
 | 
				
			||||||
 | 
					  var uriTimeout = null;
 | 
				
			||||||
 | 
					  $(document).ready(function () {
 | 
				
			||||||
 | 
					    $('#output').hide();
 | 
				
			||||||
 | 
					    var rpcName = $('#rpc-name').text().trim();
 | 
				
			||||||
 | 
					    var serviceId = $('#service-id').text().trim();
 | 
				
			||||||
 | 
					    var getParameters = function() {
 | 
				
			||||||
 | 
					      var parameters = {};
 | 
				
			||||||
 | 
					      var fields = $('.parameter').parents('li');
 | 
				
			||||||
 | 
					      for (var i = 0; i < fields.length; i++) {
 | 
				
			||||||
 | 
					        var input = $(fields[i]).find('input');
 | 
				
			||||||
 | 
					        var label = $(fields[i]).find('label');
 | 
				
			||||||
 | 
					        if (input.val() && input.val() != "") {
 | 
				
			||||||
 | 
					          parameters[label.text()] = input.val();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return parameters;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var updateOutput = function (event) {
 | 
				
			||||||
 | 
					      var request = $('#request').text().trim();
 | 
				
			||||||
 | 
					      var response = $('#response').text().trim();
 | 
				
			||||||
 | 
					      if (request != '' || response != '') {
 | 
				
			||||||
 | 
					        $('#output').show();
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        $('#output').hide();        
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var handleUri = function (event) {
 | 
				
			||||||
 | 
					      updateOutput(event);
 | 
				
			||||||
 | 
					      if (uriTimeout) {
 | 
				
			||||||
 | 
					        clearTimeout(uriTimeout);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      uriTimeout = setTimeout(function () {
 | 
				
			||||||
 | 
					        $.ajax({
 | 
				
			||||||
 | 
					          "url": "/template/" + serviceId + "/" + rpcName + "/",
 | 
				
			||||||
 | 
					          "data": getParameters(),
 | 
				
			||||||
 | 
					          "dataType": "text",
 | 
				
			||||||
 | 
					          "ifModified": true,
 | 
				
			||||||
 | 
					          "success": function (data, textStatus, xhr) {
 | 
				
			||||||
 | 
					            updateOutput(event);
 | 
				
			||||||
 | 
					            if (textStatus == 'success') {
 | 
				
			||||||
 | 
					              $('#uri-template').html(data);
 | 
				
			||||||
 | 
					              if (uriTimeout) {
 | 
				
			||||||
 | 
					                clearTimeout(uriTimeout);
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					      }, 350);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var getResponse = function (event) {
 | 
				
			||||||
 | 
					      $.ajax({
 | 
				
			||||||
 | 
					        "url": "/response/" + serviceId + "/" + rpcName + "/",
 | 
				
			||||||
 | 
					        "type": "POST",
 | 
				
			||||||
 | 
					        "data": getParameters(),
 | 
				
			||||||
 | 
					        "dataType": "html",
 | 
				
			||||||
 | 
					        "ifModified": true,
 | 
				
			||||||
 | 
					        "success": function (data, textStatus, xhr) {
 | 
				
			||||||
 | 
					          if (textStatus == 'success') {
 | 
				
			||||||
 | 
					            $('#response').text(data);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					          updateOutput(event);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var getRequest = function (event) {
 | 
				
			||||||
 | 
					      $.ajax({
 | 
				
			||||||
 | 
					        "url": "/request/" + serviceId + "/" + rpcName + "/",
 | 
				
			||||||
 | 
					        "type": "GET",
 | 
				
			||||||
 | 
					        "data": getParameters(),
 | 
				
			||||||
 | 
					        "dataType": "html",
 | 
				
			||||||
 | 
					        "ifModified": true,
 | 
				
			||||||
 | 
					        "success": function (data, textStatus, xhr) {
 | 
				
			||||||
 | 
					          if (textStatus == 'success') {
 | 
				
			||||||
 | 
					            $('#request').text(data);
 | 
				
			||||||
 | 
					            updateOutput(event);
 | 
				
			||||||
 | 
					            getResponse(event);
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    var transmit = function (event) {
 | 
				
			||||||
 | 
					      $('#request').html('');
 | 
				
			||||||
 | 
					      $('#response').html('');
 | 
				
			||||||
 | 
					      handleUri(event);
 | 
				
			||||||
 | 
					      updateOutput(event);
 | 
				
			||||||
 | 
					      getRequest(event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    $('form').submit(function (event) { event.preventDefault(); });
 | 
				
			||||||
 | 
					    $('button').click(transmit);
 | 
				
			||||||
 | 
					    $('.parameter').keyup(handleUri);
 | 
				
			||||||
 | 
					    $('.parameter').blur(handleUri);
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					JAVASCRIPT
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def client
 | 
				
			||||||
 | 
					  @client ||= Google::APIClient.new(
 | 
				
			||||||
 | 
					    :service => 'buzz',
 | 
				
			||||||
 | 
					    :authorization => Signet::OAuth1::Client.new(
 | 
				
			||||||
 | 
					      :temporary_credential_uri =>
 | 
				
			||||||
 | 
					        'https://www.google.com/accounts/OAuthGetRequestToken',
 | 
				
			||||||
 | 
					      :authorization_uri =>
 | 
				
			||||||
 | 
					        'https://www.google.com/buzz/api/auth/OAuthAuthorizeToken',
 | 
				
			||||||
 | 
					      :token_credential_uri =>
 | 
				
			||||||
 | 
					        'https://www.google.com/accounts/OAuthGetAccessToken',
 | 
				
			||||||
 | 
					      :client_credential_key => 'anonymous',
 | 
				
			||||||
 | 
					      :client_credential_secret => 'anonymous'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def service(service_name, service_version)
 | 
				
			||||||
 | 
					  unless service_version
 | 
				
			||||||
 | 
					    service_version = client.latest_service(service_name).version
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  client.discovered_service(service_name, service_version)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get '/template/:service/:method/' do
 | 
				
			||||||
 | 
					  service_name, service_version = params[:service].split("-", 2)
 | 
				
			||||||
 | 
					  method = service(service_name, service_version).to_h[params[:method].to_s]
 | 
				
			||||||
 | 
					  parameters = method.parameters.inject({}) do |accu, parameter|
 | 
				
			||||||
 | 
					    accu[parameter] = params[parameter.to_sym] if params[parameter.to_sym]
 | 
				
			||||||
 | 
					    accu
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  uri = Addressable::URI.parse(
 | 
				
			||||||
 | 
					    method.uri_template.partial_expand(parameters).pattern
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					  template_variables = method.uri_template.variables
 | 
				
			||||||
 | 
					  query_parameters = method.normalize_parameters(parameters).reject do |k, v|
 | 
				
			||||||
 | 
					    template_variables.include?(k)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  if query_parameters.size > 0
 | 
				
			||||||
 | 
					    uri.query_values = (uri.query_values || {}).merge(query_parameters)
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  # Normalization is necessary because of undesirable percent-escaping
 | 
				
			||||||
 | 
					  # during URI template expansion
 | 
				
			||||||
 | 
					  return uri.normalize.to_s.gsub('%7B', '{').gsub('%7D', '}')
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get '/request/:service/:method/' do
 | 
				
			||||||
 | 
					  service_name, service_version = params[:service].split("-", 2)
 | 
				
			||||||
 | 
					  method = service(service_name, service_version).to_h[params[:method].to_s]
 | 
				
			||||||
 | 
					  parameters = method.parameters.inject({}) do |accu, parameter|
 | 
				
			||||||
 | 
					    accu[parameter] = params[parameter.to_sym] if params[parameter.to_sym]
 | 
				
			||||||
 | 
					    accu
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  body = ''
 | 
				
			||||||
 | 
					  request = client.generate_request(
 | 
				
			||||||
 | 
					    method, parameters.merge("pp" => "1"), body, [], {:signed => false}
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					  method, uri, headers, body = request
 | 
				
			||||||
 | 
					  merged_body = StringIO.new
 | 
				
			||||||
 | 
					  body.each do |chunk|
 | 
				
			||||||
 | 
					    merged_body << chunk
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  merged_body.rewind
 | 
				
			||||||
 | 
					  <<-REQUEST.strip
 | 
				
			||||||
 | 
					#{method} #{uri} HTTP/1.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#{(headers.map { |k,v| "#{k}: #{v}" }).join('\n')}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#{merged_body.string}
 | 
				
			||||||
 | 
					REQUEST
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					post '/response/:service/:method/' do
 | 
				
			||||||
 | 
					  require 'rack/utils'
 | 
				
			||||||
 | 
					  service_name, service_version = params[:service].split("-", 2)
 | 
				
			||||||
 | 
					  method = service(service_name, service_version).to_h[params[:method].to_s]
 | 
				
			||||||
 | 
					  parameters = method.parameters.inject({}) do |accu, parameter|
 | 
				
			||||||
 | 
					    accu[parameter] = params[parameter.to_sym] if params[parameter.to_sym]
 | 
				
			||||||
 | 
					    accu
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  body = ''
 | 
				
			||||||
 | 
					  response = client.execute(
 | 
				
			||||||
 | 
					    method, parameters.merge("pp" => "1"), body, [], {:signed => false}
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					  status, headers, body = response
 | 
				
			||||||
 | 
					  status_message = Rack::Utils::HTTP_STATUS_CODES[status.to_i]
 | 
				
			||||||
 | 
					  merged_body = StringIO.new
 | 
				
			||||||
 | 
					  body.each do |chunk|
 | 
				
			||||||
 | 
					    merged_body << chunk
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  merged_body.rewind
 | 
				
			||||||
 | 
					  <<-RESPONSE.strip
 | 
				
			||||||
 | 
					#{status} #{status_message}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#{(headers.map { |k,v| "#{k}: #{v}" }).join("\n")}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#{merged_body.string}
 | 
				
			||||||
 | 
					RESPONSE
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get '/explore/:service/' do
 | 
				
			||||||
 | 
					  service_name, service_version = params[:service].split("-", 2)
 | 
				
			||||||
 | 
					  service_version = service(service_name, service_version).version
 | 
				
			||||||
 | 
					  variables = {
 | 
				
			||||||
 | 
					    "css" => CSS,
 | 
				
			||||||
 | 
					    "service_name" => service_name,
 | 
				
			||||||
 | 
					    "service_version" => service_version,
 | 
				
			||||||
 | 
					    "methods" => service(service_name, service_version).to_h.keys.sort
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  Liquid::Template.parse(<<-HTML).render(variables)
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					  <head>
 | 
				
			||||||
 | 
					    <title>{{service_name}}</title>
 | 
				
			||||||
 | 
					    <style type="text/css">
 | 
				
			||||||
 | 
					      {{css}}
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					  </head>
 | 
				
			||||||
 | 
					  <body>
 | 
				
			||||||
 | 
					    <h1>{{service_name}}</h1>
 | 
				
			||||||
 | 
					    <ul>
 | 
				
			||||||
 | 
					      {% for method in methods %}
 | 
				
			||||||
 | 
					        <li>
 | 
				
			||||||
 | 
					          <a href="/explore/{{service_name}}-{{service_version}}/{{method}}/">
 | 
				
			||||||
 | 
					            {{method}}
 | 
				
			||||||
 | 
					          </a>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					      {% endfor %}
 | 
				
			||||||
 | 
					    </ul>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
 | 
					  HTML
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get '/explore/:service/:method/' do
 | 
				
			||||||
 | 
					  service_name, service_version = params[:service].split("-", 2)
 | 
				
			||||||
 | 
					  service_version = service(service_name, service_version).version
 | 
				
			||||||
 | 
					  method = service(service_name, service_version).to_h[params[:method].to_s]
 | 
				
			||||||
 | 
					  variables = {
 | 
				
			||||||
 | 
					    "css" => CSS,
 | 
				
			||||||
 | 
					    "javascript" => JAVASCRIPT,
 | 
				
			||||||
 | 
					    "http_method" => (method.description['httpMethod'] || 'GET'),
 | 
				
			||||||
 | 
					    "service_name" => service_name,
 | 
				
			||||||
 | 
					    "service_version" => service_version,
 | 
				
			||||||
 | 
					    "method" => params[:method].to_s,
 | 
				
			||||||
 | 
					    "required_parameters" =>
 | 
				
			||||||
 | 
					      method.required_parameters,
 | 
				
			||||||
 | 
					    "optional_parameters" =>
 | 
				
			||||||
 | 
					      method.optional_parameters.sort,
 | 
				
			||||||
 | 
					    "template" => method.uri_template.pattern
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  Liquid::Template.parse(<<-HTML).render(variables)
 | 
				
			||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					  <head>
 | 
				
			||||||
 | 
					    <title>{{service_name}} - {{method}}</title>
 | 
				
			||||||
 | 
					    <style type="text/css">
 | 
				
			||||||
 | 
					      {{css}}
 | 
				
			||||||
 | 
					    </style>
 | 
				
			||||||
 | 
					    <script
 | 
				
			||||||
 | 
					      src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"
 | 
				
			||||||
 | 
					      type="text/javascript">
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					    <script type="text/javascript">
 | 
				
			||||||
 | 
					      {{javascript}}
 | 
				
			||||||
 | 
					    </script>
 | 
				
			||||||
 | 
					  </head>
 | 
				
			||||||
 | 
					  <body>
 | 
				
			||||||
 | 
					    <h3 id="service-id">
 | 
				
			||||||
 | 
					      <a href="/explore/{{service_name}}-{{service_version}}/">
 | 
				
			||||||
 | 
					        {{service_name}}-{{service_version}}
 | 
				
			||||||
 | 
					      </a>
 | 
				
			||||||
 | 
					    </h3>
 | 
				
			||||||
 | 
					    <h1 id="rpc-name">{{method}}</h1>
 | 
				
			||||||
 | 
					    <h2>{{http_method}} <span id="uri-template">{{template}}</span></h2>
 | 
				
			||||||
 | 
					    <form>
 | 
				
			||||||
 | 
					      <ul>
 | 
				
			||||||
 | 
					        {% for parameter in required_parameters %}
 | 
				
			||||||
 | 
					          <li>
 | 
				
			||||||
 | 
					            <label for="param-{{parameter}}">{{parameter}}</label>
 | 
				
			||||||
 | 
					            <input id="param-{{parameter}}" name="param-{{parameter}}"
 | 
				
			||||||
 | 
					              class="parameter" type="text" />
 | 
				
			||||||
 | 
					          </li>
 | 
				
			||||||
 | 
					        {% endfor %}
 | 
				
			||||||
 | 
					        {% for parameter in optional_parameters %}
 | 
				
			||||||
 | 
					          <li>
 | 
				
			||||||
 | 
					            <label for="param-{{parameter}}">{{parameter}}</label>
 | 
				
			||||||
 | 
					            <input id="param-{{parameter}}" name="param-{{parameter}}"
 | 
				
			||||||
 | 
					              class="parameter" type="text" />
 | 
				
			||||||
 | 
					          </li>
 | 
				
			||||||
 | 
					        {% endfor %}
 | 
				
			||||||
 | 
					        {% if http_method != 'GET' %}
 | 
				
			||||||
 | 
					        <li>
 | 
				
			||||||
 | 
					          <label for="http-body">body</label>
 | 
				
			||||||
 | 
					          <textarea id="http-body" name="http-body"></textarea>
 | 
				
			||||||
 | 
					        </li>
 | 
				
			||||||
 | 
					        {% endif %}
 | 
				
			||||||
 | 
					      </ul>
 | 
				
			||||||
 | 
					      <button>Transmit</button>
 | 
				
			||||||
 | 
					    </form>
 | 
				
			||||||
 | 
					    <div id="output">
 | 
				
			||||||
 | 
					      <h3>Request</h3>
 | 
				
			||||||
 | 
					      <pre id="request"></pre>
 | 
				
			||||||
 | 
					      <h3>Response</h3>
 | 
				
			||||||
 | 
					      <pre id="response"></pre>
 | 
				
			||||||
 | 
					    </div>
 | 
				
			||||||
 | 
					  </body>
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
 | 
					  HTML
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					get '/favicon.ico' do
 | 
				
			||||||
 | 
					  require 'httpadapter'
 | 
				
			||||||
 | 
					  HTTPAdapter.transmit(
 | 
				
			||||||
 | 
					    ['GET', 'http://www.google.com/favicon.ico', [], ['']],
 | 
				
			||||||
 | 
					    HTTPAdapter::NetHTTPRequestAdapter
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
		Loading…
	
		Reference in New Issue