deltacloud-core 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +145 -0
- data/NOTICE +10 -1
- data/Rakefile +50 -2
- data/bin/deltacloudd +111 -14
- data/config/addresses.xml +14 -0
- data/config/condor.yaml +30 -0
- data/config/drivers/azure.yaml +3 -0
- data/config/drivers/condor.yaml +3 -0
- data/config/{drivers.yaml → drivers/ec2.yaml} +5 -34
- data/config/drivers/eucalyptus.yaml +8 -0
- data/config/drivers/gogrid.yaml +3 -0
- data/config/drivers/mock.yaml +3 -0
- data/config/drivers/opennebula.yaml +4 -0
- data/config/drivers/rackspace.yaml +3 -0
- data/config/drivers/rhevm.yaml +3 -0
- data/config/drivers/rimuhosting.yaml +3 -0
- data/config/drivers/sbc.yaml +2 -0
- data/config/drivers/terremark.yaml +3 -0
- data/config/drivers/vsphere.yaml +8 -0
- data/deltacloud-core.gemspec +13 -5
- data/deltacloud.rb +4 -2
- data/lib/deltacloud/backend_capability.rb +2 -2
- data/lib/deltacloud/base_driver/base_driver.rb +23 -52
- data/lib/deltacloud/base_driver/exceptions.rb +168 -0
- data/lib/deltacloud/base_driver/features.rb +31 -12
- data/lib/deltacloud/base_driver/mock_driver.rb +2 -1
- data/lib/deltacloud/core_ext/string.rb +2 -0
- data/lib/deltacloud/drivers/azure/azure_driver.rb +5 -5
- data/lib/deltacloud/drivers/condor/condor_client.rb +273 -0
- data/lib/deltacloud/drivers/condor/condor_driver.rb +236 -0
- data/lib/deltacloud/drivers/condor/ip_agents/confserver.rb +75 -0
- data/lib/deltacloud/drivers/condor/ip_agents/default.rb +84 -0
- data/lib/deltacloud/drivers/ec2/ec2_driver.rb +326 -95
- data/lib/deltacloud/drivers/ec2/ec2_mock_driver.rb +3 -3
- data/lib/deltacloud/drivers/eucalyptus/eucalyptus_driver.rb +40 -8
- data/lib/deltacloud/drivers/gogrid/gogrid_client.rb +7 -7
- data/lib/deltacloud/drivers/gogrid/gogrid_driver.rb +42 -25
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob1.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob2.yml +7 -5
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob3.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob4.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/{buckets/blobs → blobs}/blob5.yml +6 -4
- data/lib/deltacloud/drivers/mock/data/buckets/bucket1.yml +7 -1
- data/lib/deltacloud/drivers/mock/data/buckets/bucket2.yml +6 -1
- data/lib/deltacloud/drivers/mock/data/images/img1.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/images/img2.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/images/img3.yml +6 -2
- data/lib/deltacloud/drivers/mock/data/instances/inst0.yml +11 -10
- data/lib/deltacloud/drivers/mock/data/instances/inst1.yml +14 -7
- data/lib/deltacloud/drivers/mock/data/instances/inst2.yml +14 -7
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap1.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap2.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_snapshots/snap3.yml +3 -2
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol1.yml +4 -3
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol2.yml +4 -3
- data/lib/deltacloud/drivers/mock/data/storage_volumes/vol3.yml +4 -3
- data/lib/deltacloud/drivers/mock/mock_client.rb +101 -0
- data/lib/deltacloud/drivers/mock/mock_driver.rb +367 -429
- data/lib/deltacloud/drivers/opennebula/opennebula_driver.rb +6 -0
- data/lib/deltacloud/drivers/rackspace/rackspace_driver.rb +59 -9
- data/lib/deltacloud/drivers/rhevm/rhevm_client.rb +62 -8
- data/lib/deltacloud/drivers/rhevm/rhevm_driver.rb +100 -45
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_client.rb +3 -2
- data/lib/deltacloud/drivers/rimuhosting/rimuhosting_driver.rb +8 -11
- data/lib/deltacloud/drivers/sbc/sbc_client.rb +6 -6
- data/lib/deltacloud/drivers/sbc/sbc_driver.rb +16 -0
- data/lib/deltacloud/drivers/terremark/terremark_driver.rb +17 -12
- data/lib/deltacloud/drivers/vsphere/vsphere_client.rb +140 -0
- data/lib/deltacloud/drivers/vsphere/vsphere_driver.rb +405 -0
- data/lib/deltacloud/drivers/vsphere/vsphere_filemanager.rb +182 -0
- data/lib/deltacloud/hardware_profile.rb +1 -1
- data/lib/deltacloud/helpers.rb +2 -1
- data/lib/deltacloud/helpers/application_helper.rb +92 -20
- data/lib/deltacloud/helpers/blob_stream.rb +160 -12
- data/lib/deltacloud/helpers/conversion_helper.rb +6 -2
- data/lib/deltacloud/helpers/json_helper.rb +31 -0
- data/lib/deltacloud/models/address.rb +28 -0
- data/lib/deltacloud/models/base_model.rb +5 -1
- data/lib/deltacloud/models/blob.rb +1 -1
- data/lib/deltacloud/models/bucket.rb +10 -0
- data/lib/deltacloud/models/firewall.rb +22 -0
- data/lib/deltacloud/models/firewall_rule.rb +23 -0
- data/lib/deltacloud/models/image.rb +12 -0
- data/lib/deltacloud/models/instance.rb +20 -2
- data/lib/deltacloud/models/key.rb +1 -1
- data/lib/deltacloud/runner.rb +3 -3
- data/lib/deltacloud/validation.rb +3 -7
- data/lib/drivers.rb +7 -1
- data/lib/sinatra/body_proxy.rb +34 -0
- data/lib/sinatra/lazy_auth.rb +5 -0
- data/lib/sinatra/rabbit.rb +54 -31
- data/lib/sinatra/rack_accept.rb +157 -0
- data/lib/sinatra/rack_date.rb +38 -0
- data/lib/sinatra/rack_etag.rb +2 -3
- data/lib/sinatra/rack_matrix_params.rb +51 -29
- data/lib/sinatra/rack_runtime.rb +1 -1
- data/lib/sinatra/rack_syslog.rb +86 -0
- data/lib/sinatra/url_for.rb +14 -1
- data/public/images/address.png +0 -0
- data/public/images/balancer.png +0 -0
- data/public/images/blob.png +0 -0
- data/public/images/bucket.png +0 -0
- data/public/images/cloud.png +0 -0
- data/public/images/firewall.png +0 -0
- data/public/images/image.png +0 -0
- data/public/images/key.png +0 -0
- data/public/images/machine.png +0 -0
- data/public/images/profile.png +0 -0
- data/public/images/realm.png +0 -0
- data/public/images/snapshot.png +0 -0
- data/public/images/volume.png +0 -0
- data/public/javascripts/application.js +119 -16
- data/public/javascripts/jquery.min.js +18 -0
- data/public/javascripts/jquery.mobile-1.0b1.min.js +146 -0
- data/public/stylesheets/compiled/application.css +8 -0
- data/public/stylesheets/images/ajax-loader.png +0 -0
- data/public/{images → stylesheets/images}/bread-bg.png +0 -0
- data/public/{images → stylesheets/images}/error.png +0 -0
- data/public/{images → stylesheets/images}/grid.png +0 -0
- data/public/stylesheets/images/icon-search-black.png +0 -0
- data/public/stylesheets/images/icons-18-black.png +0 -0
- data/public/stylesheets/images/icons-18-white.png +0 -0
- data/public/stylesheets/images/icons-36-black.png +0 -0
- data/public/stylesheets/images/icons-36-white.png +0 -0
- data/public/{images → stylesheets/images}/logo-wide.png +0 -0
- data/public/{images → stylesheets/images}/pending.png +0 -0
- data/public/{images → stylesheets/images}/rails.png +0 -0
- data/public/{images → stylesheets/images}/running.png +0 -0
- data/public/{images → stylesheets/images}/stopped.png +0 -0
- data/public/{images → stylesheets/images}/topbar-bg.png +0 -0
- data/public/stylesheets/jquery.mobile-1.0b1.min.css +8 -0
- data/public/stylesheets/new.css +53 -0
- data/server.rb +487 -175
- data/support/condor/bash/cached_images.sh +8 -0
- data/support/condor/bash/cloud_exit_hook.sh +17 -0
- data/support/condor/bash/cloud_functions +175 -0
- data/support/condor/bash/cloud_prepare_hook.sh +20 -0
- data/support/condor/bash/libvirt_cloud_script.sh +13 -0
- data/support/condor/config/50condor_cloud.config +37 -0
- data/support/condor/config/50condor_cloud_node.config +37 -0
- data/support/condor/config/condor-cloud +2 -0
- data/support/condor/config/condor_config.local +44 -0
- data/support/fedora/deltacloud-core +48 -26
- data/support/fedora/deltacloud-core-config +26 -0
- data/support/fedora/deltacloud-core.spec +314 -68
- data/support/fedora/deltacloudd-fedora +5 -0
- data/tests/common.rb +34 -4
- data/tests/drivers/mock/api_test.rb +3 -3
- data/tests/drivers/mock/images_test.rb +12 -0
- data/tests/drivers/mock/instances_test.rb +2 -0
- data/tests/rabbit_test.rb +2 -2
- data/views/addresses/_address.html.haml +6 -0
- data/views/addresses/associate.html.haml +12 -0
- data/views/addresses/index.html.haml +9 -0
- data/views/addresses/index.xml.haml +4 -0
- data/views/addresses/show.html.haml +21 -0
- data/views/addresses/show.xml.haml +14 -0
- data/views/api/show.html.haml +6 -11
- data/views/api/show.xml.haml +2 -0
- data/views/blobs/new.html.haml +24 -23
- data/views/blobs/show.html.haml +30 -31
- data/views/buckets/index.html.haml +9 -21
- data/views/buckets/index.xml.haml +3 -7
- data/views/buckets/new.html.haml +13 -12
- data/views/buckets/show.html.haml +22 -22
- data/views/buckets/show.xml.haml +5 -3
- data/views/docs/collection.html.haml +23 -34
- data/views/docs/collection.xml.haml +2 -2
- data/views/docs/index.html.haml +9 -13
- data/views/docs/index.xml.haml +1 -1
- data/views/docs/operation.html.haml +28 -38
- data/views/docs/operation.xml.haml +1 -1
- data/views/drivers/index.html.haml +8 -13
- data/views/drivers/show.html.haml +18 -18
- data/views/error.html.haml +32 -27
- data/views/errors/400.html.haml +41 -0
- data/views/errors/{validation_failure.xml.haml → 400.xml.haml} +0 -4
- data/views/errors/401.html.haml +41 -0
- data/views/errors/{auth_exception.xml.haml → 401.xml.haml} +0 -0
- data/views/errors/403.html.haml +42 -0
- data/views/errors/{not_allowed.xml.haml → 403.xml.haml} +0 -0
- data/views/errors/404.html.haml +29 -0
- data/views/errors/{not_found.xml.haml → 404.xml.haml} +1 -1
- data/views/errors/405.html.haml +29 -0
- data/views/errors/405.xml.haml +5 -0
- data/views/errors/500.html.haml +43 -0
- data/views/errors/500.xml.haml +5 -0
- data/views/errors/502.html.haml +43 -0
- data/views/errors/{backend_error.xml.haml → 502.xml.haml} +1 -2
- data/views/errors/backend_capability_failure.html.haml +27 -9
- data/views/firewalls/index.html.haml +15 -0
- data/views/firewalls/index.xml.haml +28 -0
- data/views/firewalls/new.html.haml +11 -0
- data/views/firewalls/new_rule.html.haml +20 -0
- data/views/firewalls/show.html.haml +42 -0
- data/views/firewalls/show.xml.haml +26 -0
- data/views/hardware_profiles/index.html.haml +15 -23
- data/views/hardware_profiles/show.html.haml +22 -18
- data/views/images/index.html.haml +11 -23
- data/views/images/index.xml.haml +4 -13
- data/views/images/new.html.haml +12 -13
- data/views/images/show.html.haml +26 -20
- data/views/images/show.xml.haml +2 -1
- data/views/instance_states/show.html.haml +21 -25
- data/views/instances/index.html.haml +13 -30
- data/views/instances/index.xml.haml +2 -23
- data/views/instances/new.html.haml +83 -88
- data/views/instances/show.html.haml +53 -55
- data/views/instances/show.xml.haml +12 -10
- data/views/keys/index.html.haml +13 -24
- data/views/keys/new.html.haml +7 -7
- data/views/keys/show.html.haml +26 -21
- data/views/layout.html.haml +28 -27
- data/views/load_balancers/index.html.haml +11 -31
- data/views/load_balancers/index.xml.haml +0 -1
- data/views/load_balancers/new.html.haml +1 -1
- data/views/load_balancers/show.html.haml +33 -34
- data/views/load_balancers/show.xml.haml +2 -2
- data/views/realms/index.html.haml +11 -24
- data/views/realms/index.xml.haml +2 -8
- data/views/realms/show.html.haml +17 -15
- data/views/realms/show.xml.haml +2 -1
- data/views/storage_snapshots/index.html.haml +11 -21
- data/views/storage_snapshots/index.xml.haml +2 -5
- data/views/storage_snapshots/new.html.haml +1 -1
- data/views/storage_snapshots/show.html.haml +21 -13
- data/views/storage_snapshots/show.xml.haml +2 -1
- data/views/storage_volumes/index.html.haml +11 -34
- data/views/storage_volumes/new.html.haml +1 -1
- data/views/storage_volumes/show.html.haml +33 -27
- data/views/storage_volumes/show.xml.haml +2 -1
- metadata +266 -178
- data/lib/sinatra/respond_to.rb +0 -248
- data/support/fedora/deltacloudd +0 -128
- data/support/fedora/rubygem-deltacloud-core.spec +0 -127
- data/views/accounts/index.html.haml +0 -11
- data/views/accounts/show.html.haml +0 -30
- data/views/errors/auth_exception.html.haml +0 -8
- data/views/errors/backend_error.html.haml +0 -22
- data/views/errors/not_allowed.html.haml +0 -6
- data/views/errors/not_found.html.haml +0 -6
- data/views/errors/validation_failure.html.haml +0 -11
@@ -0,0 +1,157 @@
|
|
1
|
+
# respond_to (The MIT License)
|
2
|
+
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
4
|
+
# and associated documentation files (the 'Software'), to deal in the Software without restriction,
|
5
|
+
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
6
|
+
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
7
|
+
# furnished to do so, subject to the following conditions:
|
8
|
+
#
|
9
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
10
|
+
# NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
11
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
12
|
+
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
13
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE
|
14
|
+
|
15
|
+
require 'sinatra/base'
|
16
|
+
require 'rack/accept'
|
17
|
+
|
18
|
+
use Rack::Accept
|
19
|
+
|
20
|
+
module Rack
|
21
|
+
|
22
|
+
module RespondTo
|
23
|
+
|
24
|
+
# This method is triggered after this helper is registred
|
25
|
+
# within Sinatra.
|
26
|
+
# We need to overide the default render method to supply correct path to the
|
27
|
+
# template, since Sinatra is by default looking in the current __FILE__ path
|
28
|
+
def self.registered(app)
|
29
|
+
app.helpers Rack::RespondTo::Helpers
|
30
|
+
app.class_eval do
|
31
|
+
alias :render_without_format :render
|
32
|
+
def render(*args, &block)
|
33
|
+
begin
|
34
|
+
assumed_layout = args[1] == :layout
|
35
|
+
args[1] = "#{args[1]}.#{@media_type}".to_sym if args[1].is_a?(::Symbol)
|
36
|
+
render_without_format *args, &block
|
37
|
+
rescue Errno::ENOENT => e
|
38
|
+
raise "ERROR: Missing template: #{args[1]}.#{args[0]}" unless assumed_layout
|
39
|
+
raise e
|
40
|
+
end
|
41
|
+
end
|
42
|
+
private :render
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
module Helpers
|
47
|
+
|
48
|
+
# This code was inherited from respond_to plugin
|
49
|
+
# http://github.com/cehoffman/sinatra-respond_to
|
50
|
+
#
|
51
|
+
# This method is used to overide the default content_type returned from
|
52
|
+
# rack-accept middleware.
|
53
|
+
def self.included(klass)
|
54
|
+
klass.class_eval do
|
55
|
+
alias :content_type_without_save :content_type
|
56
|
+
def content_type(*args)
|
57
|
+
content_type_without_save *args
|
58
|
+
request.env['rack-accept.formats'] = { args.first.to_sym => 1 }
|
59
|
+
response['Content-Type']
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def accepting_formats
|
65
|
+
request.env['rack-accept.formats']
|
66
|
+
end
|
67
|
+
|
68
|
+
def static_file?(path)
|
69
|
+
public_dir = File.expand_path(options.public)
|
70
|
+
path = File.expand_path(File.join(public_dir, unescape(path)))
|
71
|
+
path[0, public_dir.length] == public_dir && File.file?(path)
|
72
|
+
end
|
73
|
+
|
74
|
+
def respond_to(&block)
|
75
|
+
wants = {}
|
76
|
+
def wants.method_missing(type, *args, &handler)
|
77
|
+
self[type] = handler
|
78
|
+
end
|
79
|
+
yield wants
|
80
|
+
@media_type = accepting_formats.to_a.sort { |a,b| a[1]<=>b[1] }.reverse.select do |format, priority|
|
81
|
+
wants.keys.include?(format) == true
|
82
|
+
end.first
|
83
|
+
if @media_type and @media_type[0]
|
84
|
+
@media_type = @media_type[0]
|
85
|
+
headers 'Content-Type' => Rack::MediaType::ACCEPTED_MEDIA_TYPES[@media_type][:return]
|
86
|
+
wants[@media_type.to_sym].call if wants[@media_type.to_sym]
|
87
|
+
else
|
88
|
+
headers 'Content-Type' => nil
|
89
|
+
status 406
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
class MediaType < Sinatra::Base
|
98
|
+
|
99
|
+
include Rack::RespondTo::Helpers
|
100
|
+
|
101
|
+
# Define supported media types here
|
102
|
+
# The :return key stands for content-type which will be returned
|
103
|
+
# The :match key stands for the matching Accept header
|
104
|
+
ACCEPTED_MEDIA_TYPES = {
|
105
|
+
:xml => { :return => 'application/xml', :match => ['application/xml', 'text/xml'] },
|
106
|
+
:json => { :return => 'application/json', :match => ['application/json'] },
|
107
|
+
:html => { :return => 'text/html', :match => ['application/xhtml+xml', 'text/html', '*/*'] },
|
108
|
+
:png => { :return => 'image/png', :match => ['image/png'] },
|
109
|
+
:gv => { :return => 'application/ghostscript', :match => ['application/ghostscript'] }
|
110
|
+
}
|
111
|
+
|
112
|
+
def call(env)
|
113
|
+
accept, index = env['rack-accept.request'], {}
|
114
|
+
|
115
|
+
# Skip everything when 'format' parameter is set in URL
|
116
|
+
if env['rack.request.query_hash']["format"]
|
117
|
+
media_type = case env['rack.request.query_hash']["format"]
|
118
|
+
when 'html' then :html
|
119
|
+
when 'xml' then :xml
|
120
|
+
when 'json' then :json
|
121
|
+
when 'gv' then :gv
|
122
|
+
when 'png' then :png
|
123
|
+
end
|
124
|
+
index[media_type] = 1 if media_type
|
125
|
+
else
|
126
|
+
# Sort all requested media types in Accept using their 'q' values
|
127
|
+
sorted_media_types = accept.media_type.qvalues.to_a.sort{ |a,b| a[1]<=>b[1] }.collect { |t| t.first }
|
128
|
+
# If Accept header is missing or is empty, fallback to XML format
|
129
|
+
sorted_media_types << 'application/xml' if sorted_media_types.empty?
|
130
|
+
# Choose the right format with the media type according to the priority
|
131
|
+
ACCEPTED_MEDIA_TYPES.each do |format, definition|
|
132
|
+
definition[:match].each do |media_type|
|
133
|
+
break if index[format] = sorted_media_types.index(media_type)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
# Reject formats with no/nil priority
|
137
|
+
index.reject! { |format, priority| not priority }
|
138
|
+
end
|
139
|
+
|
140
|
+
#puts sorted_media_types.inspect
|
141
|
+
#puts index.inspect
|
142
|
+
|
143
|
+
# If after all we don't have any matching format assume that client has
|
144
|
+
# requested unknown/wrong media type and throw an 406 error with no body
|
145
|
+
if index.keys.empty?
|
146
|
+
status, headers, response = 406, {}, ""
|
147
|
+
else
|
148
|
+
env['rack-accept.formats'] = index
|
149
|
+
status, headers, response = @app.call(env)
|
150
|
+
end
|
151
|
+
[status, headers, response]
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
# Copyright (c) 2008 The Committers
|
3
|
+
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
5
|
+
# of this software and associated documentation files (the "Software"), to
|
6
|
+
# deal in the Software without restriction, including without limitation the
|
7
|
+
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
8
|
+
# sell copies of the Software, and to permit persons to whom the Software is
|
9
|
+
# furnished to do so, subject to the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be included in
|
12
|
+
# all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
15
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
16
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
17
|
+
# THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
18
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
19
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
20
|
+
|
21
|
+
require 'time'
|
22
|
+
|
23
|
+
module Rack
|
24
|
+
class Date
|
25
|
+
|
26
|
+
def initialize(app, no_cache_control = nil, cache_control = nil)
|
27
|
+
@app = app
|
28
|
+
end
|
29
|
+
|
30
|
+
def call(env)
|
31
|
+
status, headers, body = @app.call(env)
|
32
|
+
headers['Date'] = Time.new.httpdate if not headers['Date']
|
33
|
+
[status, headers, body]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/lib/sinatra/rack_etag.rb
CHANGED
@@ -30,11 +30,10 @@ module Rack
|
|
30
30
|
# used when Etag is absent and a directive when it is present. The first
|
31
31
|
# defaults to nil, while the second defaults to "max-age=0, privaute, must-revalidate"
|
32
32
|
class ETag
|
33
|
-
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate".freeze
|
34
33
|
|
35
|
-
def initialize(app, no_cache_control = nil, cache_control =
|
34
|
+
def initialize(app, no_cache_control = nil, cache_control = nil)
|
36
35
|
@app = app
|
37
|
-
@cache_control = cache_control
|
36
|
+
@cache_control = cache_control || "max-age=0, private, must-revalidate"
|
38
37
|
@no_cache_control = no_cache_control
|
39
38
|
end
|
40
39
|
|
@@ -36,46 +36,68 @@ module Rack
|
|
36
36
|
#
|
37
37
|
# All HTTP methods are supported, in case of POST they will be passed as a
|
38
38
|
# regular <form> parameters.
|
39
|
-
|
39
|
+
|
40
40
|
def call(env)
|
41
41
|
# Copy PATH_INFO to REQUEST_URI if Rack::Test
|
42
42
|
env['REQUEST_URI'] = env['PATH_INFO'] if env['rack.test']
|
43
|
+
env['REQUEST_PATH'] = env['PATH_INFO'] if env['rack.test']
|
43
44
|
|
44
45
|
# Split URI to components and then extract ;var=value pairs
|
45
46
|
uri_components = env['REQUEST_URI'].split('/')
|
46
47
|
matrix_params = {}
|
47
48
|
uri_components.each do |component|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
49
|
+
sub_components, value = component.split(/\;(\w+)\=/), nil
|
50
|
+
next unless sub_components.first # Skip subcomponent if it's empty (usually /)
|
51
|
+
while param=sub_components.pop do
|
52
|
+
if value
|
53
|
+
matrix_params[sub_components.first] ||= {}
|
54
|
+
matrix_params[sub_components.first].merge!(
|
55
|
+
param => value
|
56
|
+
)
|
57
|
+
value=nil
|
58
|
+
next
|
59
|
+
else
|
60
|
+
value = param.gsub(/\?.*$/, '')
|
61
|
+
end
|
62
|
+
end
|
62
63
|
end
|
63
64
|
|
64
|
-
#
|
65
|
-
|
65
|
+
# Two things need to happen to make matrix params work:
|
66
|
+
# (1) the parameters need to be appended to the 'normal' params
|
67
|
+
# for the request. 'Normal' really depends on the content
|
68
|
+
# type of the request, which does not seem accessible from
|
69
|
+
# Middleware, so we use the existence of
|
70
|
+
# rack.request.form_hash in the environment to distinguish
|
71
|
+
# between basic and application/x-www-form-urlencoded
|
72
|
+
# requests
|
73
|
+
# (2) the parameters need to be stripped from the appropriate
|
74
|
+
# path related env variables, so that request dispatching
|
75
|
+
# does not trip over them
|
76
|
+
|
77
|
+
# (1) Rewrite current path by stripping all matrix params from it
|
78
|
+
if env['REQUEST_PATH'] == '/'
|
79
|
+
env['REQUEST_URI'] = env['REQUEST_PATH']
|
80
|
+
env['REQUEST_PATH'] = env['PATH_INFO']
|
81
|
+
end
|
82
|
+
env['REQUEST_PATH'] = env['REQUEST_PATH'].gsub(/;([^\/]*)/, '').gsub(/\?(.*)$/, '')
|
83
|
+
env['PATH_INFO'] = env['REQUEST_PATH']
|
66
84
|
|
67
|
-
#
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
85
|
+
# (2) Append the matrix params to the 'normal' request params
|
86
|
+
# FIXME: Make this work for multipart/form-data
|
87
|
+
if env['rack.request.form_hash']
|
88
|
+
# application/x-www-form-urlencoded, most likely a POST
|
89
|
+
env['rack.request.form_hash'].merge!(matrix_params)
|
90
|
+
else
|
91
|
+
# For other methods it's more complicated
|
92
|
+
if env['REQUEST_METHOD']!='POST' and not matrix_params.keys.empty?
|
93
|
+
env['QUERY_STRING'].gsub!(/;([^\/]*)/, '')
|
94
|
+
new_params = matrix_params.collect do |component, params|
|
95
|
+
params.collect { |k,v| "#{component}[#{k}]=#{CGI::escape(v.to_s)}" }
|
96
|
+
end.flatten
|
97
|
+
# Add matrix params as a regular GET params
|
98
|
+
env['QUERY_STRING'] += '&' if not env['QUERY_STRING'].empty?
|
99
|
+
env['QUERY_STRING'] += "#{new_params.join('&')}"
|
100
|
+
end
|
79
101
|
end
|
80
102
|
@app.call(env)
|
81
103
|
end
|
data/lib/sinatra/rack_runtime.rb
CHANGED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'syslog'
|
2
|
+
require 'lib/sinatra/body_proxy'
|
3
|
+
|
4
|
+
class SyslogFile < File
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@log = Syslog.open($0, Syslog::LOG_PID | Syslog::LOG_LOCAL5)
|
8
|
+
end
|
9
|
+
|
10
|
+
def write(string)
|
11
|
+
@log.warning(string) if string.strip.length > 0
|
12
|
+
return string.chars.count
|
13
|
+
end
|
14
|
+
|
15
|
+
def info(msg)
|
16
|
+
@log.info(msg)
|
17
|
+
end
|
18
|
+
|
19
|
+
def err(msg)
|
20
|
+
@log.err(msg)
|
21
|
+
end
|
22
|
+
|
23
|
+
alias :warning :err
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
# Code bellow was originaly copied from Rack::CommonLogger
|
28
|
+
# https://raw.github.com/rack/rack/master/lib/rack/commonlogger.rb
|
29
|
+
|
30
|
+
module Rack
|
31
|
+
# Rack::CommonLogger forwards every request to an +app+ given, and
|
32
|
+
# logs a line in the Apache common log format to the +logger+, or
|
33
|
+
# rack.errors by default.
|
34
|
+
class SyslogLogger
|
35
|
+
|
36
|
+
# Common Log Format: http://httpd.apache.org/docs/1.3/logs.html#common
|
37
|
+
# lilith.local - - [07/Aug/2006 23:58:02] "GET / HTTP/1.1" 500 -
|
38
|
+
# %{%s - %s [%s] "%s %s%s %s" %d %s\n} %
|
39
|
+
FORMAT = %{%s - %s [%s] "%s %s%s %s" %d %s %0.4f\n}
|
40
|
+
|
41
|
+
def initialize(app, logger=nil)
|
42
|
+
@app = app
|
43
|
+
@logger = logger || $stdout
|
44
|
+
end
|
45
|
+
|
46
|
+
def call(env)
|
47
|
+
began_at = Time.now
|
48
|
+
status, header, body = @app.call(env)
|
49
|
+
header = Utils::HeaderHash.new(header)
|
50
|
+
body = Rack::BodyProxy.new(body) { log(env, status, header, began_at) }
|
51
|
+
[status, header, body]
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def log(env, status, header, began_at)
|
57
|
+
now = Time.now
|
58
|
+
length = extract_content_length(header)
|
59
|
+
|
60
|
+
if status.to_s =~ /5(\d{2})/
|
61
|
+
method = :err
|
62
|
+
else
|
63
|
+
method = :info
|
64
|
+
end
|
65
|
+
|
66
|
+
logger = @logger || env['rack.errors']
|
67
|
+
logger.send(method, FORMAT % [
|
68
|
+
env['HTTP_X_FORWARDED_FOR'] || env["REMOTE_ADDR"] || "-",
|
69
|
+
env["REMOTE_USER"] || "-",
|
70
|
+
now.strftime("%d/%b/%Y %H:%M:%S"),
|
71
|
+
env["REQUEST_METHOD"],
|
72
|
+
env["PATH_INFO"],
|
73
|
+
env["QUERY_STRING"].empty? ? "" : "?"+env["QUERY_STRING"],
|
74
|
+
env["HTTP_VERSION"],
|
75
|
+
status.to_s[0..3],
|
76
|
+
length,
|
77
|
+
now - began_at ])
|
78
|
+
end
|
79
|
+
|
80
|
+
def extract_content_length(headers)
|
81
|
+
value = headers['Content-Length'] or return '-'
|
82
|
+
value.to_s == '0' ? '-' : value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
data/lib/sinatra/url_for.rb
CHANGED
@@ -28,6 +28,19 @@ require 'uri'
|
|
28
28
|
|
29
29
|
module Sinatra
|
30
30
|
module UrlForHelper
|
31
|
+
|
32
|
+
DEFAULT_URI_PREFIX = "/api"
|
33
|
+
|
34
|
+
def api_url_for(url_fragment, mode=:path_only)
|
35
|
+
matrix_params = ''
|
36
|
+
if request.params['api']
|
37
|
+
matrix_params += ";provider=%s" % request.params['api']['provider'] if request.params['api']['provider']
|
38
|
+
matrix_params += ";driver=%s" % request.params['api']['driver'] if request.params['api']['driver']
|
39
|
+
end
|
40
|
+
url_fragment = "/#{url_fragment}" unless url_fragment =~ /^\// # There is no need to prefix URI with '/'
|
41
|
+
url_for "#{DEFAULT_URI_PREFIX}#{matrix_params}#{url_fragment}", mode
|
42
|
+
end
|
43
|
+
|
31
44
|
# Construct a link to +url_fragment+, which should be given relative to
|
32
45
|
# the base of this Sinatra app. The mode should be either
|
33
46
|
# <code>:path_only</code>, which will generate an absolute path within
|
@@ -70,7 +83,7 @@ module Sinatra
|
|
70
83
|
end
|
71
84
|
|
72
85
|
def root_url
|
73
|
-
|
86
|
+
DEFAULT_URI_PREFIX
|
74
87
|
end
|
75
88
|
end
|
76
89
|
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|