Skip to content
This repository has been archived by the owner on Dec 16, 2023. It is now read-only.

Commit

Permalink
Merge pull request #4 from jeromegn/https
Browse files Browse the repository at this point in the history
Added HTTPS support
  • Loading branch information
assaf committed May 2, 2012
2 parents b5a278c + b0f2dd0 commit 237bab9
Show file tree
Hide file tree
Showing 10 changed files with 126 additions and 9 deletions.
7 changes: 7 additions & 0 deletions lib/replay/index.coffee
@@ -1,5 +1,6 @@
DNS = require("dns") DNS = require("dns")
HTTP = require("http") HTTP = require("http")
HTTPS = require("https")
ProxyRequest = require("./proxy") ProxyRequest = require("./proxy")
Replay = require("./replay") Replay = require("./replay")


Expand All @@ -20,6 +21,12 @@ HTTP.request = (options, callback)->
return request return request




# Route HTTPS requests
HTTPS.request = (options, callback)->
options.protocol = "https:"
return HTTP.request(options, callback)


# Redirect HTTP requests to 127.0.0.1 for all hosts defined as localhost # Redirect HTTP requests to 127.0.0.1 for all hosts defined as localhost
original_lookup = DNS.lookup original_lookup = DNS.lookup
DNS.lookup = (domain, family, callback)-> DNS.lookup = (domain, family, callback)->
Expand Down
11 changes: 9 additions & 2 deletions lib/replay/pass_through.coffee
@@ -1,7 +1,9 @@
HTTP = require("http") HTTP = require("http")
HTTPS = require("https")


# Capture original HTTP request. PassThrough proxy uses that. # Capture original HTTP request. PassThrough proxy uses that.
httpRequest = HTTP.request httpRequest = HTTP.request
httpsRequest = HTTPS.request


passThrough = (allow)-> passThrough = (allow)->
if arguments.length == 0 if arguments.length == 0
Expand All @@ -14,12 +16,17 @@ passThrough = (allow)->
return (request, callback)-> return (request, callback)->
if allow(request) if allow(request)
options = options =
protocol: request.url.protocol
hostname: request.url.hostname hostname: request.url.hostname
port: request.url.port port: request.url.port
path: request.url.path path: request.url.path
method: request.method method: request.method
headers: request.headers headers: request.headers
http = httpRequest(options)
if request.url.protocol == "https:"
http = httpsRequest(options)
else
http = httpRequest(options)
http.on "error", (error)-> http.on "error", (error)->
callback error callback error
http.on "response", (response)-> http.on "response", (response)->
Expand Down
2 changes: 1 addition & 1 deletion lib/replay/proxy.coffee
Expand Up @@ -34,7 +34,7 @@ class ProxyRequest extends HTTP.ClientRequest
constructor: (options = {}, @proxy)-> constructor: (options = {}, @proxy)->
@method = (options.method || "GET").toUpperCase() @method = (options.method || "GET").toUpperCase()
[host, port] = (options.host || options.hostname).split(":") [host, port] = (options.host || options.hostname).split(":")
@url = URL.parse("http://#{host || "localhost"}:#{options.port || port || 80}#{options.path || "/"}") @url = URL.parse("#{options.protocol || "http:"}//#{host || "localhost"}:#{options.port || port || 80}#{options.path || "/"}")
@headers = {} @headers = {}
if options.headers if options.headers
for n,v of options.headers for n,v of options.headers
Expand Down
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -19,7 +19,8 @@
}, },
"devDependencies": { "devDependencies": {
"express": "~2.5.9", "express": "~2.5.9",
"mocha": "~1.0.2" "mocha": "~1.0.2",
"async": "~0.1.18"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/example.com:3443/minimal
@@ -0,0 +1 @@
GET /minimal
34 changes: 31 additions & 3 deletions test/helpers.coffee
Expand Up @@ -2,11 +2,14 @@
# All requests using a hostname are routed to 127.0.0.1 # All requests using a hostname are routed to 127.0.0.1
# Port 3001 has a live server, see below for paths and responses # Port 3001 has a live server, see below for paths and responses
# Port 3002 has no server, connections will be refused # Port 3002 has no server, connections will be refused
# Port 3443 has a live https server




DNS = require("dns") DNS = require("dns")
Express = require("express") Express = require("express")
Replay = require("../lib/replay") Replay = require("../lib/replay")
File = require("fs")
Async = require("async")




# Directory to load fixtures from. # Directory to load fixtures from.
Expand All @@ -21,6 +24,7 @@ DNS.lookup = (domain, callback)->
else else
original_lookup domain, callback original_lookup domain, callback



# Serve pages from localhost. # Serve pages from localhost.
server = Express.createServer() server = Express.createServer()
server.use Express.bodyParser() server.use Express.bodyParser()
Expand All @@ -35,9 +39,32 @@ server.get "/500", (req, res)->
res.send 500, "Boom!" res.send 500, "Boom!"




# SSL Server
ssl_server = Express.createServer(
key: File.readFileSync("#{__dirname}/ssl/privatekey.pem")
cert: File.readFileSync("#{__dirname}/ssl/certificate.pem")
)
ssl_server.use Express.bodyParser()
# Success page.
ssl_server.get "/", (req, res)->
res.send "Success!"
# Not found
ssl_server.get "/404", (req, res)->
res.send 404, "Not found"
# Internal error
ssl_server.get "/500", (req, res)->
res.send 500, "Boom!"


# Setup environment for running tests. # Setup environment for running tests.
setup = (callback)-> setup = (callback)->
server.listen 3001, callback Async.parallel [
(done)->
server.listen 3001, done
(done)->
ssl_server.listen 3443, done
], callback

return return


if server._connected if server._connected
Expand All @@ -53,4 +80,5 @@ setup = (callback)->
exports.assert = require("assert") exports.assert = require("assert")
exports.setup = setup exports.setup = setup
exports.HTTP = require("http") exports.HTTP = require("http")
exports.HTTPS = require("https")
exports.Replay = Replay exports.Replay = Replay
29 changes: 28 additions & 1 deletion test/pass_through_test.coffee
@@ -1,4 +1,4 @@
{ assert, setup, HTTP, Replay } = require("./helpers") { assert, setup, HTTP, HTTPS, Replay } = require("./helpers")




# First batch is testing requests that pass through to the server, no recording/replay. # First batch is testing requests that pass through to the server, no recording/replay.
Expand Down Expand Up @@ -63,6 +63,33 @@ describe "Pass through", ->
assert.deepEqual response.body, "Success!" assert.deepEqual response.body, "Success!"




describe "ssl", ->
before ->
Replay.mode = "bloody"

response = null

before (done)->
request = HTTPS.get(hostname: "pass-through", port: 3443, (_)->
response = _
response.body = ""
response.on "data", (chunk)->
response.body += chunk
response.on "end", done
)
request.on "error", done

it "should return HTTP version", ->
assert.equal response.httpVersion, "1.1"
it "should return status code", ->
assert.equal response.statusCode, 200
it "should return response headers", ->
assert.equal response.headers["content-type"], "text/html; charset=utf-8"
it "should return response trailers", ->
assert.deepEqual response.trailers, { }
it "should return response body", ->
assert.deepEqual response.body, "Success!"

# Send request to the live server on port 3001, but this time network connection disabled. # Send request to the live server on port 3001, but this time network connection disabled.
describe "replay", -> describe "replay", ->
before -> before ->
Expand Down
20 changes: 19 additions & 1 deletion test/replay_test.coffee
@@ -1,4 +1,4 @@
{ assert, HTTP, Replay } = require("./helpers") { assert, HTTP, HTTPS, Replay } = require("./helpers")




# Test replaying results from fixtures in spec/fixtures. # Test replaying results from fixtures in spec/fixtures.
Expand Down Expand Up @@ -50,6 +50,24 @@ describe "Replay", ->
assert.deepEqual response.trailers, { } assert.deepEqual response.trailers, { }




describe "matching an https url", ->
response = null

before (done)->
Replay.mode = "replay"

request = HTTPS.get(hostname: "example.com", port: 3443, path: "/minimal")
request.on "response", (_)->
response = _
done()
request.on "error", done

it "should return HTTP version", ->
assert.equal response.httpVersion, "1.1"
it "should return status code", ->
assert.equal response.statusCode, 200


describe "matching a regexp", -> describe "matching a regexp", ->
body = null body = null


Expand Down
13 changes: 13 additions & 0 deletions test/ssl/certificate.pem
@@ -0,0 +1,13 @@
-----BEGIN CERTIFICATE-----
MIICATCCAWoCCQDwtkmH/OpeXzANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJB
VTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0
cyBQdHkgTHRkMB4XDTEyMDUwMjE2MzA0N1oXDTEyMDYwMTE2MzA0N1owRTELMAkG
A1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0
IFdpZGdpdHMgUHR5IEx0ZDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAzrQa
+3uX+75buOq2zXl8vgOn8DYtZCK1jm6kC17Qak3iHIkzUXSfYRlEWAzJsECjDWaL
6KCh5/B5XsdatIfpVb7SoeAK1Cs5ONTWNSvMTnDToJEJ3nY/cdcg3Nlrld2LkAt6
W7Jh2NZC29e7+t1ro6w5Ok88dkYZul5Qn9Lc6isCAwEAATANBgkqhkiG9w0BAQUF
AAOBgQC5cmtHh6M7rByX3Gm5cMrtM+Gbfg25VP9BOgCCj+DjwY4gStcuhtU4sxZX
7IsoLMi22uiqP9/NSOReVB1gOkWMA5mkqACLerQqFmedXCjiCwgZ5F4G2UVpkXn7
6QYThFtX1umpWcZwtb2n6NatmCcHMfPVAZFxmI/V5kl7lT6sNw==
-----END CERTIFICATE-----
15 changes: 15 additions & 0 deletions test/ssl/privatekey.pem
@@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDOtBr7e5f7vlu46rbNeXy+A6fwNi1kIrWObqQLXtBqTeIciTNR
dJ9hGURYDMmwQKMNZovooKHn8Hlex1q0h+lVvtKh4ArUKzk41NY1K8xOcNOgkQne
dj9x1yDc2WuV3YuQC3pbsmHY1kLb17v63WujrDk6Tzx2Rhm6XlCf0tzqKwIDAQAB
AoGBAKFclkfF9yKOOxpDGMuU0F2hiwOJt6uZMPRsyOEbdkXWYPJ35Ljs+tKZH/JA
oV5XRzJZ4FSMuXfQEV987wFJrEtcQH4GaH+ZUGmoeCmYs1Gal3Pumexvbn5ffduu
HiFkoGhFUQuVGuBE1W7yOk/EmJQZlOBqQCuSW5rxzJGvwu55AkEA+pUgJsdSDMwk
KVNWb2UvDOYwJMa1PP7q32+P8o2S092zGm9HxPhYUhBdx8OqGfKbOUQTPlMOK9f4
6ECD1stgLwJBANMsIIpHwah/B5DJaJEOI2iqc1RwntdpsxYTFsptMDkzi576q7y+
JQXtc3DkfEMc/9oJSG+Tb+LHWdhhWADy+sUCQBU7Z4MBpokhDvtVbWB48VildHTZ
RWgKrXoLKOZDaqp7AX7+6NTeuhUR//A6OwKB1PcwNnU0cmHypcuAE+uyRc8CQCD6
pD5URIdHB2xyN/Vnato+vHI0gGoN5N0OsCF++egFB8oVRdrdKzUIx12bIVjt33sy
tfBO60tUbNChKzhCui0CQQC+8dx4GlJ/AR/51b5zLIQ+XDcfj0SbHAEn/cdrNJb2
x1LSckVayPvaVslesPzicC8cHfFqD3i8GSt6wRs7/fI8
-----END RSA PRIVATE KEY-----

0 comments on commit 237bab9

Please sign in to comment.