right_http_connection 1.3.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +25 -1
- data/lib/{net_fix.rb → base/net_fix.rb} +21 -3
- data/lib/{support.rb → base/support.rb} +0 -0
- data/lib/{version.rb → base/version.rb} +1 -1
- data/lib/right_http_connection.rb +112 -38
- data/right_http_connection.gemspec +1 -1
- data/spec/client/cacert.cer +0 -0
- data/spec/client/cacert.pem +17 -0
- data/spec/client/cert.pem +18 -0
- data/spec/client/key.pem +27 -0
- data/spec/really_dumb_webserver.rb +13 -4
- metadata +13 -11
data/History.txt
CHANGED
@@ -57,6 +57,30 @@ Initial public release
|
|
57
57
|
* fixed a bug: <NoMethodError: You have a nil object when you didn't expect it!
|
58
58
|
The error occurred while evaluating nil.body_stream>
|
59
59
|
|
60
|
-
== 1.2.5
|
60
|
+
== 1.2.5
|
61
61
|
|
62
62
|
- ActiveSupport dependency removal
|
63
|
+
|
64
|
+
|
65
|
+
== 1.3.0
|
66
|
+
- Added:
|
67
|
+
- support for using through proxies
|
68
|
+
- functional tests
|
69
|
+
|
70
|
+
== 1.3.1
|
71
|
+
- Added:
|
72
|
+
- SSL certificate handshake support
|
73
|
+
- more specs
|
74
|
+
- ability to give client side key and certificate inline
|
75
|
+
- Fixed: some minor glitches
|
76
|
+
|
77
|
+
== 1.4.0
|
78
|
+
- Added
|
79
|
+
- license
|
80
|
+
- HTTP_PROXY env variable support
|
81
|
+
- Fixed
|
82
|
+
- context-length issue (thx kristianm)
|
83
|
+
- exception handling
|
84
|
+
- connection is now closed on any exception
|
85
|
+
- connection is reestablished when credentials change
|
86
|
+
- some other minor bugs
|
@@ -91,18 +91,30 @@ module Net
|
|
91
91
|
private
|
92
92
|
|
93
93
|
def send_request_with_body(sock, ver, path, body, send_only=nil)
|
94
|
-
self.content_length = body.length
|
94
|
+
self.content_length = body.respond_to?(:bytesize) ? body.bytesize : body.length
|
95
95
|
delete 'Transfer-Encoding'
|
96
96
|
supply_default_content_type
|
97
97
|
write_header(sock, ver, path) unless send_only == :body
|
98
|
-
sock.write(body)
|
98
|
+
sock.write(body && body.to_s) unless send_only == :header
|
99
99
|
end
|
100
100
|
|
101
101
|
def send_request_with_body_stream(sock, ver, path, f, send_only=nil)
|
102
|
+
# KD: Fix 'content-length': it must not be greater than a piece of file left to be read.
|
103
|
+
# Otherwise the connection may behave like crazy causing 4xx or 5xx responses
|
104
|
+
#
|
105
|
+
# Only do this helpful thing if the stream responds to :pos (it may be something
|
106
|
+
# that responds to :read and :size but not :pos).
|
107
|
+
if f.respond_to?(:pos)
|
108
|
+
file_size = f.respond_to?(:lstat) ? f.lstat.size : f.size
|
109
|
+
bytes_to_read = [ file_size - f.pos, self.content_length.to_i ].sort.first
|
110
|
+
self.content_length = bytes_to_read
|
111
|
+
end
|
112
|
+
|
102
113
|
unless content_length() or chunked?
|
103
114
|
raise ArgumentError,
|
104
115
|
"Content-Length not given and Transfer-Encoding is not `chunked'"
|
105
116
|
end
|
117
|
+
bytes_to_read ||= content_length()
|
106
118
|
supply_default_content_type
|
107
119
|
write_header(sock, ver, path) unless send_only == :body
|
108
120
|
unless send_only == :header
|
@@ -112,8 +124,14 @@ module Net
|
|
112
124
|
end
|
113
125
|
sock.write "0\r\n\r\n"
|
114
126
|
else
|
115
|
-
|
127
|
+
# KD: When we read/write over file EOF it sometimes make the connection unstable
|
128
|
+
read_size = [ @@local_read_size, bytes_to_read ].sort.first
|
129
|
+
while s = f.read(read_size)
|
116
130
|
sock.write s
|
131
|
+
# Make sure we do not read over EOF or more than expected content-length
|
132
|
+
bytes_to_read -= read_size
|
133
|
+
break if bytes_to_read <= 0
|
134
|
+
read_size = bytes_to_read if bytes_to_read < read_size
|
117
135
|
end
|
118
136
|
end
|
119
137
|
end
|
File without changes
|
@@ -24,7 +24,7 @@
|
|
24
24
|
module RightHttpConnection #:nodoc:
|
25
25
|
module VERSION #:nodoc:
|
26
26
|
MAJOR = 1 unless defined?(MAJOR)
|
27
|
-
MINOR =
|
27
|
+
MINOR = 4 unless defined?(MINOR)
|
28
28
|
TINY = 0 unless defined?(TINY)
|
29
29
|
|
30
30
|
STRING = [MAJOR, MINOR, TINY].join('.') unless defined?(STRING)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#
|
2
|
-
# Copyright (c) 2007-
|
2
|
+
# Copyright (c) 2007-2011 RightScale Inc
|
3
3
|
#
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
5
5
|
# a copy of this software and associated documentation files (the
|
@@ -27,9 +27,9 @@ require "time"
|
|
27
27
|
require "logger"
|
28
28
|
|
29
29
|
$:.unshift(File.dirname(__FILE__))
|
30
|
-
require 'version'
|
31
|
-
require 'support'
|
32
|
-
require
|
30
|
+
require 'base/version'
|
31
|
+
require 'base/support'
|
32
|
+
require 'base/net_fix'
|
33
33
|
|
34
34
|
module Rightscale
|
35
35
|
|
@@ -137,26 +137,47 @@ them.
|
|
137
137
|
# :raise_on_timeout # do not perform a retry if timeout is received (false by default)
|
138
138
|
def initialize(params={})
|
139
139
|
@params = params
|
140
|
+
|
141
|
+
#set up logging first
|
142
|
+
@logger = get_param(:logger) ||
|
143
|
+
(RAILS_DEFAULT_LOGGER if defined?(RAILS_DEFAULT_LOGGER)) ||
|
144
|
+
Logger.new(STDOUT)
|
145
|
+
|
146
|
+
env_proxy_host, env_proxy_port, env_proxy_username, env_proxy_password = get_proxy_info_for_env if ENV['HTTP_PROXY']
|
147
|
+
|
140
148
|
@params[:http_connection_retry_count] ||= @@params[:http_connection_retry_count]
|
141
149
|
@params[:http_connection_open_timeout] ||= @@params[:http_connection_open_timeout]
|
142
150
|
@params[:http_connection_read_timeout] ||= @@params[:http_connection_read_timeout]
|
143
151
|
@params[:http_connection_retry_delay] ||= @@params[:http_connection_retry_delay]
|
144
|
-
@params[:proxy_host] ||= @@params[:proxy_host]
|
145
|
-
@params[:proxy_port] ||= @@params[:proxy_port]
|
146
|
-
@params[:proxy_username] ||= @@params[:proxy_username]
|
147
|
-
@params[:proxy_password] ||= @@params[:proxy_password]
|
152
|
+
@params[:proxy_host] ||= @@params[:proxy_host] || env_proxy_host
|
153
|
+
@params[:proxy_port] ||= @@params[:proxy_port] || env_proxy_port
|
154
|
+
@params[:proxy_username] ||= @@params[:proxy_username] || env_proxy_username
|
155
|
+
@params[:proxy_password] ||= @@params[:proxy_password] || env_proxy_password
|
156
|
+
|
148
157
|
@http = nil
|
149
158
|
@server = nil
|
150
|
-
@logger = get_param(:logger) ||
|
151
|
-
(RAILS_DEFAULT_LOGGER if defined?(RAILS_DEFAULT_LOGGER)) ||
|
152
|
-
Logger.new(STDOUT)
|
153
159
|
#--------------
|
154
160
|
# Retry state - Keep track of errors on a per-server basis
|
155
161
|
#--------------
|
156
162
|
@state = {} # retry state indexed by server: consecutive error count, error time, and error
|
163
|
+
|
157
164
|
@eof = {}
|
158
165
|
end
|
159
166
|
|
167
|
+
def get_proxy_info_for_env
|
168
|
+
parsed_uri = URI.parse(ENV['HTTP_PROXY'])
|
169
|
+
if parsed_uri.scheme.to_s.downcase == 'http'
|
170
|
+
return parsed_uri.host, parsed_uri.port, parsed_uri.user, parsed_uri.password
|
171
|
+
else
|
172
|
+
@logger.warn "Invalid protocol in ENV['HTTP_PROXY'] URI = #{ENV['HTTP_PROXY'].inspect} expecting 'http' got #{parsed_uri.scheme.inspect}"
|
173
|
+
return
|
174
|
+
end
|
175
|
+
rescue Exception => e
|
176
|
+
@logger.warn "Error parsing ENV['HTTP_PROXY'] with exception: #{e.message}"
|
177
|
+
return
|
178
|
+
end
|
179
|
+
private :get_proxy_info_for_env
|
180
|
+
|
160
181
|
def get_param(name, custom_options={})
|
161
182
|
custom_options [name] || @params[name] || @@params[name]
|
162
183
|
end
|
@@ -207,7 +228,9 @@ them.
|
|
207
228
|
end
|
208
229
|
|
209
230
|
# add an error for a server
|
210
|
-
def error_add(
|
231
|
+
def error_add(error)
|
232
|
+
message = error
|
233
|
+
message = "#{error.class.name}: #{error.message}" if error.is_a?(Exception)
|
211
234
|
@state[@server] = { :count => error_count+1, :time => Time.now, :message => message }
|
212
235
|
end
|
213
236
|
|
@@ -218,7 +241,7 @@ them.
|
|
218
241
|
|
219
242
|
# Error message stuff...
|
220
243
|
def banana_message
|
221
|
-
return "#{@server} temporarily unavailable: (#{error_message})"
|
244
|
+
return "#{@protocol}://#{@server}:#{@port} temporarily unavailable: (#{error_message})"
|
222
245
|
end
|
223
246
|
|
224
247
|
def err_header
|
@@ -280,6 +303,8 @@ them.
|
|
280
303
|
end
|
281
304
|
end
|
282
305
|
|
306
|
+
SECURITY_PARAMS = [:cert, :key, :cert_file, :key_file, :ca_file]
|
307
|
+
|
283
308
|
# Start a fresh connection. The object closes any existing connection and
|
284
309
|
# opens a new one.
|
285
310
|
def start(request_params)
|
@@ -293,10 +318,15 @@ them.
|
|
293
318
|
@proxy_port = request_params[:proxy_port]
|
294
319
|
@proxy_username = request_params[:proxy_username]
|
295
320
|
@proxy_password = request_params[:proxy_password]
|
321
|
+
|
322
|
+
SECURITY_PARAMS.each do |param_name|
|
323
|
+
@params[param_name] = request_params[param_name]
|
324
|
+
end
|
296
325
|
|
297
326
|
@logger.info("Opening new #{@protocol.upcase} connection to #@server:#@port")
|
327
|
+
|
298
328
|
@logger.info("Connecting to proxy #{@proxy_host}:#{@proxy_port} with username" +
|
299
|
-
" #{@proxy_username}") unless @proxy_host.nil?
|
329
|
+
" #{@proxy_username.inspect}") unless @proxy_host.nil?
|
300
330
|
|
301
331
|
@http = Net::HTTP.new(@server, @port, @proxy_host, @proxy_port, @proxy_username,
|
302
332
|
@proxy_password)
|
@@ -305,10 +335,9 @@ them.
|
|
305
335
|
|
306
336
|
if @protocol == 'https'
|
307
337
|
verifyCallbackProc = Proc.new{ |ok, x509_store_ctx|
|
338
|
+
# List of error codes: http://www.openssl.org/docs/apps/verify.html
|
308
339
|
code = x509_store_ctx.error
|
309
340
|
msg = x509_store_ctx.error_string
|
310
|
-
#debugger
|
311
|
-
@logger.warn("##### #{@server} certificate verify failed: #{msg}") unless code == 0
|
312
341
|
if request_params[:fail_if_ca_mismatch] && code != 0
|
313
342
|
false
|
314
343
|
else
|
@@ -316,14 +345,44 @@ them.
|
|
316
345
|
end
|
317
346
|
}
|
318
347
|
@http.use_ssl = true
|
348
|
+
|
319
349
|
ca_file = get_param(:ca_file)
|
320
|
-
if ca_file
|
321
|
-
|
350
|
+
if ca_file && File.exists?(ca_file)
|
351
|
+
# Documentation for 'http.rb':
|
352
|
+
# : verify_mode, verify_mode=((|mode|))
|
353
|
+
# Sets the flags for server the certification verification at
|
354
|
+
# beginning of SSL/TLS session.
|
355
|
+
# OpenSSL::SSL::VERIFY_NONE or OpenSSL::SSL::VERIFY_PEER is acceptable.
|
356
|
+
#
|
357
|
+
# KHRVI: looks like the constant VERIFY_FAIL_IF_NO_PEER_CERT is not acceptable
|
322
358
|
@http.verify_callback = verifyCallbackProc
|
323
|
-
@http.ca_file
|
359
|
+
@http.ca_file= ca_file
|
360
|
+
@http.verify_mode = get_param(:use_server_auth) ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
|
361
|
+
# The depth count is 'level 0:peer certificate', 'level 1: CA certificate', 'level 2: higher level CA certificate', and so on.
|
362
|
+
# Setting the maximum depth to 2 allows the levels 0, 1, and 2. The default depth limit is 9, allowing for the peer certificate and additional 9 CA certificates.
|
363
|
+
@http.verify_depth = 9
|
324
364
|
else
|
325
365
|
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
326
366
|
end
|
367
|
+
|
368
|
+
# CERT
|
369
|
+
cert_file = get_param(:cert_file, request_params)
|
370
|
+
cert = File.read(cert_file) if cert_file && File.exists?(cert_file)
|
371
|
+
cert ||= get_param(:cert, request_params)
|
372
|
+
# KEY
|
373
|
+
key_file = get_param(:key_file, request_params)
|
374
|
+
key = File.read(key_file) if key_file && File.exists?(key_file)
|
375
|
+
key ||= get_param(:key, request_params)
|
376
|
+
if cert && key
|
377
|
+
begin
|
378
|
+
@http.verify_callback = verifyCallbackProc
|
379
|
+
@http.cert = OpenSSL::X509::Certificate.new(cert)
|
380
|
+
@http.key = OpenSSL::PKey::RSA.new(key)
|
381
|
+
rescue OpenSSL::PKey::RSAError, OpenSSL::X509::CertificateError => e
|
382
|
+
@logger.error "##### Error loading SSL client cert or key: #{e.message} :: backtrace #{e.backtrace}"
|
383
|
+
raise e
|
384
|
+
end
|
385
|
+
end
|
327
386
|
end
|
328
387
|
# open connection
|
329
388
|
@http.start
|
@@ -359,14 +418,21 @@ them.
|
|
359
418
|
current_params = @params.merge(request_params)
|
360
419
|
exception = get_param(:exception, current_params) || RuntimeError
|
361
420
|
|
421
|
+
# Re-establish the connection if any of auth params has changed
|
422
|
+
same_auth_params_as_before = SECURITY_PARAMS.select do |param|
|
423
|
+
request_params[param] != get_param(param)
|
424
|
+
end.empty?
|
425
|
+
|
362
426
|
# We save the offset here so that if we need to retry, we can return the file pointer to its initial position
|
363
427
|
mypos = get_fileptr_offset(current_params)
|
364
428
|
loop do
|
429
|
+
|
365
430
|
current_params[:protocol] ||= (current_params[:port] == 443 ? 'https' : 'http')
|
366
431
|
# (re)open connection to server if none exists or params has changed
|
367
|
-
same_server_as_before = @server == current_params[:server]
|
368
|
-
@port == current_params[:port]
|
369
|
-
@protocol == current_params[:protocol]
|
432
|
+
same_server_as_before = @server == current_params[:server] &&
|
433
|
+
@port == current_params[:port] &&
|
434
|
+
@protocol == current_params[:protocol] &&
|
435
|
+
same_auth_params_as_before
|
370
436
|
|
371
437
|
# if we are inside a delay between retries: no requests this time!
|
372
438
|
# (skip this step if the endpoint has changed)
|
@@ -389,6 +455,7 @@ them.
|
|
389
455
|
unless @http &&
|
390
456
|
@http.started? &&
|
391
457
|
same_server_as_before
|
458
|
+
same_auth_params_as_before = true
|
392
459
|
start(current_params)
|
393
460
|
end
|
394
461
|
|
@@ -414,8 +481,9 @@ them.
|
|
414
481
|
|
415
482
|
# EOFError means the server closed the connection on us.
|
416
483
|
rescue EOFError => e
|
484
|
+
finish(e.message)
|
485
|
+
|
417
486
|
@logger.debug("#{err_header} server #{@server} closed connection")
|
418
|
-
@http = nil
|
419
487
|
|
420
488
|
# if we have waited long enough - raise an exception...
|
421
489
|
if raise_on_eof_exception?
|
@@ -427,31 +495,35 @@ them.
|
|
427
495
|
# We will be retrying the request, so reset the file pointer
|
428
496
|
reset_fileptr_offset(request, mypos)
|
429
497
|
end
|
430
|
-
rescue
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
498
|
+
rescue ArgumentError => e
|
499
|
+
finish(e.message)
|
500
|
+
|
501
|
+
if e.message.include?('wrong number of arguments (5 for 4)')
|
502
|
+
# seems our net_fix patch was overriden...
|
503
|
+
raise exception.new('incompatible Net::HTTP monkey-patch')
|
504
|
+
else
|
505
|
+
raise e
|
506
|
+
end
|
507
|
+
|
508
|
+
rescue Timeout::Error, SocketError, SystemCallError, Interrupt => e # See comment at bottom for the list of errors seen...
|
509
|
+
finish(e.message)
|
510
|
+
if e.is_a?(Errno::ETIMEDOUT) || e.is_a?(Timeout::Error)
|
511
|
+
# Omit retries if it was explicitly requested
|
435
512
|
# #6481:
|
436
513
|
# ... When creating a resource in EC2 (instance, volume, snapshot, etc) it is undetermined what happened if the call times out.
|
437
514
|
# The resource may or may not have been created in EC2. Retrying the call may cause multiple resources to be created...
|
438
|
-
raise e
|
439
|
-
|
440
|
-
|
441
|
-
if e.is_a?(Interrupt) && !timeout_exception
|
515
|
+
raise exception.new("#{e.class.name}: #{e.message}") if current_params[:raise_on_timeout]
|
516
|
+
elsif e.is_a?(Interrupt)
|
517
|
+
# if ctrl+c is pressed - we have to reraise exception to terminate proggy
|
442
518
|
@logger.debug( "#{err_header} request to server #{@server} interrupted by ctrl-c")
|
443
|
-
raise
|
444
|
-
elsif e.is_a?(ArgumentError) && e.message.include?('wrong number of arguments (5 for 4)')
|
445
|
-
# seems our net_fix patch was overriden...
|
446
|
-
raise exception.new('incompatible Net::HTTP monkey-patch')
|
519
|
+
raise e
|
447
520
|
end
|
448
521
|
# oops - we got a banana: log it
|
449
|
-
error_add(e
|
522
|
+
error_add(e)
|
450
523
|
@logger.warn("#{err_header} request failure count: #{error_count}, exception: #{e.inspect}")
|
451
524
|
|
452
525
|
# We will be retrying the request, so reset the file pointer
|
453
526
|
reset_fileptr_offset(request, mypos)
|
454
|
-
|
455
527
|
end
|
456
528
|
end
|
457
529
|
end
|
@@ -462,6 +534,8 @@ them.
|
|
462
534
|
@logger.info("Closing #{@http.use_ssl? ? 'HTTPS' : 'HTTP'} connection to #{@http.address}:#{@http.port}#{reason}")
|
463
535
|
@http.finish
|
464
536
|
end
|
537
|
+
ensure
|
538
|
+
@http = nil
|
465
539
|
end
|
466
540
|
|
467
541
|
# Errors received during testing:
|
@@ -22,7 +22,7 @@
|
|
22
22
|
#++
|
23
23
|
|
24
24
|
require 'rubygems'
|
25
|
-
require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'version'))
|
25
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'lib', 'base', 'version'))
|
26
26
|
|
27
27
|
Gem::Specification.new do |spec|
|
28
28
|
spec.name = 'right_http_connection'
|
Binary file
|
@@ -0,0 +1,17 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIICxjCCAa6gAwIBAgIJAJYV+DprCQ1CMA0GCSqGSIb3DQEBBQUAMBMxETAPBgNV
|
3
|
+
BAMTCE15VGVzdENBMB4XDTExMDkxMzIyNTMxMVoXDTEyMDkxMjIyNTMxMVowEzER
|
4
|
+
MA8GA1UEAxMITXlUZXN0Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
|
5
|
+
AQCwmvBNrd7t/Z7ZVo1YfimpGgerOn1vXZY+OGJtqo+pN11Ei7dhVQfWBd2dAkYH
|
6
|
+
B8NlPr5QyxmIT88JIRKEzk7ZZ+nRdfyoocg63FeLn+b6OeR5hwyK38aMRbhqY1Gq
|
7
|
+
aIKMYyEpv0YNbuwoomv5Atl8mwvuUFr2XKndyzsrP1TrTCHH4lA5P0UUzIjVyyz9
|
8
|
+
F4YAjGLjjoVO5R02LmZ/h/LqT6bJQ+cu/2JeIWGVnjKoFvyWHd0TOaOGDHlQc5h8
|
9
|
+
RxgdOFrjsZGpQ5sKlhcI+9p0LOXqVfoC2J2ZWtAjFo0d54E/OarnBPFB6VNtoSmj
|
10
|
+
l0z+OLGMKuDGaLflXNE0STVdAgMBAAGjHTAbMAwGA1UdEwQFMAMBAf8wCwYDVR0P
|
11
|
+
BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAAbVkvPzS59uhX6Ox1ZT92cJXW8yjP
|
12
|
+
IyXrZjcWlaKQSKcn8v5RpebtVA+pL6mCActBE8fMac5ixlwTTnF5LHb9v80XuXMe
|
13
|
+
MXooQZBliyim5lVCp9gjKZYXEeVDphsuwDr5M4qO7tdZTB1ezCULObVF1N7qMwpO
|
14
|
+
yWI6zifRtLsgWmnRyaeVyv2uNRYoAEsAd2Dj4oJjvuyc9U5QUhtsXwD3jvSPsdi6
|
15
|
+
Mbr5tVIcZSpT4W9PSiZw2ZUZXIEbxX+w+FsuehhvoFJCi05R1ashCPxQA13bOJK0
|
16
|
+
BmbHqeLDzJCK0+kQs8CRIGWGTGng84AyJ5MygGzd0WN9jtZslWTPDtbz
|
17
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,18 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIC9TCCAd2gAwIBAgIBAjANBgkqhkiG9w0BAQUFADATMREwDwYDVQQDEwhNeVRl
|
3
|
+
c3RDQTAeFw0xMTA5MTMyMzAxMDVaFw0xMjA5MTIyMzAxMDVaMDgxJTAjBgNVBAMM
|
4
|
+
HE1haGVuZHJhLUt1dGFyZXMtTWFjQm9vay1Qcm8xDzANBgNVBAoMBmNsaWVudDCC
|
5
|
+
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMcEhrVTKKgWVqTUBCGBWJlD
|
6
|
+
u7RIk7kPcGAARy7Ctx+4VReEYlgVRqECzt4itglNdrQkUVCHXE0rwJMOozE8Hsgh
|
7
|
+
rAOQvxzPJhG3hPUJf/VkfB+Dn0xRsPvrE90HpRlSqdT8X6iuryPEmp5RyMaY122P
|
8
|
+
r/+Xs+lHhRlKQPdRpYXHlOwWX/U56Wy7jjGU9lONBEIEV8tD5ExzkCG23nbCvrFr
|
9
|
+
/2c4VjrAwXR2RyYfSDRyc/obky49ydKZ8/HKbS3VdJYAWBI4Wnj2hayCcZggEFB0
|
10
|
+
zg/IDXpOjnr6zV5UEfdaMIH4/K44ISX7xmZWGmQ3464NTmykj5xUMmfy3rVNREsC
|
11
|
+
AwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCB4AwEwYDVR0lBAwwCgYIKwYB
|
12
|
+
BQUHAwIwDQYJKoZIhvcNAQEFBQADggEBACmNyOoCvNsz8N3LN47VZK7aev54tjtd
|
13
|
+
zJilLgAxEGBeaIvHX9LDkgi3sQAvHMHc3VIq4BoEd9TNtyxIrUdc2EG1TCJvHINP
|
14
|
+
7YoHtbajvT3bhVLlnWjB7jHp9jNfZtHL7aEDp+5eqPT6wzaVeiu1nABs7gudCQq1
|
15
|
+
CJw0Mfz1U3mG0sTb5JlRt7toce9dW0R6jfYTmTj6Yzu3kcgYjQKy2k2BCInLOIhz
|
16
|
+
6tyOH51mCGAy1zgcWMvuyKYCeJQxRd46GrR2peyE2wYY6SfSlrK16pjaz48S3uhI
|
17
|
+
01jd+HA1LARcImMhkMa/QFTo4uI7lx9Q+Y06Ny+rMuTNSnBSIgCUPQk=
|
18
|
+
-----END CERTIFICATE-----
|
data/spec/client/key.pem
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIEpAIBAAKCAQEAxwSGtVMoqBZWpNQEIYFYmUO7tEiTuQ9wYABHLsK3H7hVF4Ri
|
3
|
+
WBVGoQLO3iK2CU12tCRRUIdcTSvAkw6jMTweyCGsA5C/HM8mEbeE9Ql/9WR8H4Of
|
4
|
+
TFGw++sT3QelGVKp1PxfqK6vI8SanlHIxpjXbY+v/5ez6UeFGUpA91GlhceU7BZf
|
5
|
+
9TnpbLuOMZT2U40EQgRXy0PkTHOQIbbedsK+sWv/ZzhWOsDBdHZHJh9INHJz+huT
|
6
|
+
Lj3J0pnz8cptLdV0lgBYEjhaePaFrIJxmCAQUHTOD8gNek6OevrNXlQR91owgfj8
|
7
|
+
rjghJfvGZlYaZDfjrg1ObKSPnFQyZ/LetU1ESwIDAQABAoIBAB23pU3KHxYKT+HI
|
8
|
+
7tz57XrlTE/9TmGh1ovfPsHSvXl1Eu+yCuVQN/2u56jv0fLNqF351lKKA9RaJiVP
|
9
|
+
WDrv2UDVFlRp9r+chvi6SJY2Vu8TlB04kD7bK+xSC+NDUvnXCBkPnlEX1HsozlW5
|
10
|
+
rJtLE0/+1q75vhmlXlCKb+z+OhMhmFnaWTf/xLNbkItO5tOf+mv/CoqBUSEk+i9t
|
11
|
+
O6Zjzh02jbpW7xH3jJ/UexKMYOuqxoOMfC/MI6q3Qcu2OeZgl8cEIi94sjafq9ob
|
12
|
+
WcFTrZY+YG5b1SE8ILg69Fkqve5d2Mn1sN8mYZxLeM0C/ATNghM5uSWhdze06bNu
|
13
|
+
fpcgvOECgYEA/L+J/xVgUySUByELEBosY8q0HYG5Msq+GT7L5GMIoEmEp4j6MPRu
|
14
|
+
kF/DihxefcvDyVRLhJh7o/kwR7Vwe4wP9145e3MOe9b7IH6pEwV0nAsBO6ldVToX
|
15
|
+
gvrHOIoySNt/XtRurrbtZ08OtUDCLIRQATTnY9ieh8sxTyl1G9GehoMCgYEAyZQE
|
16
|
+
r4ByBzXjTiuaODH6tPndbKFxRo2iis9CyxqYXAMDkjvF4NEpQyW5ucRxpRqTt51P
|
17
|
+
kR13jdadnOF4t82M0qqEH3G6H4biKisY1jXRNH7mPSbyPbC4vxrQhnAEF3RiqbXz
|
18
|
+
f2LUC4uOtLzW7HeyjEiZy2mg7UKdOfsmmJ//oJkCgYEAxZF/8GqoQjW8lJoKyMp8
|
19
|
+
2oDQLKSDvSVoVdmVjfCwBIOTc1aKpAveBXMmKealIlZOtCj1Yy/CrlmSmOtGgvzo
|
20
|
+
WihIbKxyrPFOmocH6PuBvJyJmTZ5464mRNd9NUApsHQL63fJET+i8feFer+lSSEg
|
21
|
+
XOEa4xyoR2PZJpU0mstPzLsCgYBvcS3F+TURV3F7Xg+80aTROPJ5hCej4dni9ALx
|
22
|
+
Vpq1A9WNmw4i5H/zZ3/ue/R4WuEfuhCrIade+y/X869RrooUTcENwUos891Fgt4Q
|
23
|
+
T2CBrUaMuGNkR7dbr+9o47TfYrDJMpaT7odceqNCuMP5p5NGizy7gII/qXxS+c60
|
24
|
+
woAIwQKBgQCiIfXZtAgYTPL23CQrxIMFwnlO0TiOe0ha0et7hjCh/CStG7NET7KK
|
25
|
+
U1L1kfyl1YDgoJbLXTsG2WwGZRnK1oyEEFj2iY5EvwoMPr0Sv8/CiOIyEfC62s3V
|
26
|
+
MoHemunnFhAj+JAy2HTKV0VYiNNNAxz3CBG8yMLK7YAMgPw1/HQQLQ==
|
27
|
+
-----END RSA PRIVATE KEY-----
|
@@ -23,7 +23,7 @@
|
|
23
23
|
|
24
24
|
require 'webrick'
|
25
25
|
|
26
|
-
ssl_cert, ssl_key = ARGV[0], ARGV[1]
|
26
|
+
ssl_cert, ssl_key, ca_cert = ARGV[0], ARGV[1], ARGV[2]
|
27
27
|
|
28
28
|
# Monkey patch bad User-Agent parsing
|
29
29
|
module WEBrick::AccessLog
|
@@ -52,7 +52,7 @@ module WEBrick::AccessLog
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
logger = WEBrick::Log.new($stderr, WEBrick::Log::WARN)
|
55
|
+
logger = WEBrick::Log.new($stderr, WEBrick::Log::WARN)#WEBrick::Log::DEBUG
|
56
56
|
config = {}
|
57
57
|
config[:Port] = 7890
|
58
58
|
config[:Logger] = logger
|
@@ -60,10 +60,19 @@ config[:AccessLog] = [[$stdout, WEBrick::AccessLog::COMBINED_LOG_FORMAT]]
|
|
60
60
|
unless ssl_cert.nil? || ssl_key.nil?
|
61
61
|
require 'webrick/https'
|
62
62
|
config[:SSLEnable] = true
|
63
|
-
|
63
|
+
# http://www.openssl.org/docs/ssl/SSL_CTX_set_verify.html#
|
64
|
+
# SSL_VERIFY_FAIL_IF_NO_PEER_CERT
|
65
|
+
# => Server mode: if the client did not return a certificate, the TLS/SSL handshake is immediately terminated with a 'handshake failure' alert.
|
66
|
+
# => This flag must be used together with SSL_VERIFY_PEER.
|
67
|
+
config[:SSLVerifyClient] = OpenSSL::SSL::VERIFY_PEER
|
68
|
+
config[:SSLVerifyClient] |= OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT if ca_cert
|
64
69
|
config[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.open(ssl_key).read)
|
65
70
|
config[:SSLCertificate] = OpenSSL::X509::Certificate.new(File.open(ssl_cert).read)
|
66
|
-
config[:SSLCertName]
|
71
|
+
# KHRVI: option config[:SSLCertName] does make sense only when config[:SSLCertificate] isn't specified
|
72
|
+
# see: webrick/ssl.rb method :setup_ssl_context
|
73
|
+
# config[:SSLCertName] = [["CN", "Graham Hughes"]]
|
74
|
+
config[:SSLVerifyDepth] = 9
|
75
|
+
config[:SSLCACertificateFile] = ca_cert if ca_cert
|
67
76
|
end
|
68
77
|
$stdout.sync = true
|
69
78
|
server = WEBrick::HTTPServer.new(config)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: right_http_connection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 7
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 1.
|
10
|
+
version: 1.4.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- RightScale, Inc.
|
@@ -15,8 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
19
|
-
default_executable:
|
18
|
+
date: 2013-06-13 00:00:00 Z
|
20
19
|
dependencies:
|
21
20
|
- !ruby/object:Gem::Dependency
|
22
21
|
name: rake
|
@@ -115,10 +114,10 @@ files:
|
|
115
114
|
- Manifest.txt
|
116
115
|
- README.txt
|
117
116
|
- Rakefile
|
118
|
-
- lib/net_fix.rb
|
117
|
+
- lib/base/net_fix.rb
|
118
|
+
- lib/base/support.rb
|
119
|
+
- lib/base/version.rb
|
119
120
|
- lib/right_http_connection.rb
|
120
|
-
- lib/support.rb
|
121
|
-
- lib/version.rb
|
122
121
|
- right_http_connection.gemspec
|
123
122
|
- spec/bad.ca
|
124
123
|
- spec/ca/Rakefile
|
@@ -128,12 +127,15 @@ files:
|
|
128
127
|
- spec/ca/demoCA/serial
|
129
128
|
- spec/ca/passphrase.txt
|
130
129
|
- spec/ca/server.csr
|
130
|
+
- spec/client/cacert.cer
|
131
|
+
- spec/client/cacert.pem
|
132
|
+
- spec/client/cert.pem
|
133
|
+
- spec/client/key.pem
|
131
134
|
- spec/good.ca
|
132
135
|
- spec/proxy_server.rb
|
133
136
|
- spec/really_dumb_webserver.rb
|
134
137
|
- spec/server.crt
|
135
138
|
- spec/server.key
|
136
|
-
has_rdoc: true
|
137
139
|
homepage: http://rightscale.rubyforge.org/
|
138
140
|
licenses: []
|
139
141
|
|
@@ -173,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
175
|
requirements: []
|
174
176
|
|
175
177
|
rubyforge_project: rightscale
|
176
|
-
rubygems_version: 1.
|
178
|
+
rubygems_version: 1.8.5
|
177
179
|
signing_key:
|
178
180
|
specification_version: 3
|
179
181
|
summary: RightScale's robust HTTP/S connection module
|