forked from defunkt/hurl
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhurl.rb
More file actions
262 lines (204 loc) · 6.01 KB
/
Copy pathhurl.rb
File metadata and controls
262 lines (204 loc) · 6.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
require 'libraries'
module Hurl
class App < Sinatra::Base
register Mustache::Sinatra
helpers Hurl::Helpers
dir = File.dirname(File.expand_path(__FILE__))
set :public, "#{dir}/public"
set :static, true
set :mustache, {
:namespace => Object,
:views => 'views/',
:templates => 'templates/'
}
enable :sessions
set :github_options, { :client_id => ENV['HURL_CLIENT_ID'],
:secret => ENV['HURL_SECRET'],
:scopes => '',
:callback_url => '/login/callback/' }
register ::Sinatra::Auth::Github
def initialize(*args)
super
@debug = ENV['DEBUG']
setup_default_hurls
end
#
# routes
#
before do
check_for_dependencies
if authenticated?
@user = User.new(github_user)
end
@flash = session.delete('flash')
end
get '/' do
@hurl = {}
mustache :index
end
get '/hurls/?' do
redirect('/') and return unless logged_in?
@hurls = @user.hurls
mustache :hurls
end
get '/hurls/:id/?' do
@hurl = find_hurl_or_view(params[:id])
@hurl ? mustache(:index) : not_found
end
delete '/hurls/:id/?' do
redirect('/') and return unless logged_in?
if @hurl = find_hurl_or_view(params[:id])
@user.remove_hurl(@hurl['id'])
end
request.xhr? ? "ok" : redirect('/')
end
get '/hurls/:id/:view_id/?' do
@hurl = find_hurl_or_view(params[:id])
@view = find_hurl_or_view(params[:view_id])
@view_id = params[:view_id]
@hurl && @view ? mustache(:index) : not_found
end
get '/views/:id/?' do
@view = find_hurl_or_view(params[:id])
@view ? mustache(:view, :layout => false) : not_found
end
get '/test.json' do
content_type 'application/json'
File.read('test/json')
end
get '/test.xml' do
content_type 'application/xml'
File.read('test/xml')
end
get '/install/?' do
mustache :install
end
get '/about/?' do
mustache :about
end
get '/stats/?' do
mustache :stats
end
get '/login/?' do
authenticate!
redirect '/'
end
get '/login/callback/?' do
authenticate!
redirect '/'
end
get '/logout/?' do
logout!
session['flash'] = 'see you later!'
redirect '/'
end
post '/' do
return json(:error => "Calm down and try my margarita!") if rate_limited?
url, method, auth = params.values_at(:url, :method, :auth)
return json(:error => "That's... wait.. what?!") if invalid_url?(url)
curl = Curl::Easy.new(url)
sent_headers = []
curl.on_debug do |type, data|
# track request headers
sent_headers << data if type == Curl::CURLINFO_HEADER_OUT
end
curl.follow_location = true if params[:follow_redirects]
# ensure a method is set
method = (method.to_s.empty? ? 'GET' : method).upcase
# update auth
add_auth(auth, curl, params)
# arbitrary headers
add_headers_from_arrays(curl, params["header-keys"], params["header-vals"])
# arbitrary post params
if params['post-body'] && ['POST', 'PUT'].index(method)
post_data = [params['post-body']]
else
post_data = make_fields(method, params["param-keys"], params["param-vals"])
end
begin
debug { puts "#{method} #{url}" }
curl.send("http_#{method.downcase}", *post_data)
debug do
puts sent_headers.join("\n")
puts post_data.join('&') if post_data.any?
puts curl.header_str
end
header = pretty_print_headers(curl.header_str)
type = url =~ /(\.js)/ ? 'js' : curl.content_type
body = pretty_print(type, curl.body_str)
request = pretty_print_requests(sent_headers, post_data)
json :header => header,
:body => body,
:request => request,
:hurl_id => save_hurl(params),
:prev_hurl => @user ? @user.second_to_last_hurl_id : nil,
:view_id => save_view(header, body, request)
rescue => e
json :error => e.to_s
end
end
#
# error handlers
#
not_found do
mustache :"404"
end
error do
mustache :"500"
end
#
# route helpers
#
# is this a url hurl can handle. basically a spam check.
def invalid_url?(url)
url.include? 'hurl.it'
end
# update auth based on auth type
def add_auth(auth, curl, params)
if auth == 'basic'
username, password = params.values_at(:username, :password)
encoded = Base64.encode64("#{username}:#{password}").gsub("\n",'')
curl.headers['Authorization'] = "Basic #{encoded}"
end
end
# headers from non-empty keys and values
def add_headers_from_arrays(curl, keys, values)
keys, values = Array(keys), Array(values)
keys.each_with_index do |key, i|
next if values[i].to_s.empty?
curl.headers[key] = values[i]
end
end
# post params from non-empty keys and values
def make_fields(method, keys, values)
return [] unless method == 'POST'
fields = []
keys, values = Array(keys), Array(values)
keys.each_with_index do |name, i|
value = values[i]
next if name.to_s.empty? || value.to_s.empty?
fields << Curl::PostField.content(name, value)
end
fields
end
def save_view(header, body, request)
hash = { 'header' => header, 'body' => body, 'request' => request }
id = sha(hash.to_s)
DB.save(:views, id, hash)
id
end
def save_hurl(params)
id = sha(params.to_s)
DB.save(:hurls, id, params.merge(:id => id))
@user.add_hurl(id) if @user
id
end
def find_hurl_or_view(id)
DB.find(:hurls, id) || DB.find(:views, id)
end
# has this person made too many requests?
def rate_limited?
false
end
end
end