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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
DNS = require("dns")
HTTP = require("http")
HTTPS = require("https")
ProxyRequest = require("./proxy")
Replay = require("./replay")

Expand All @@ -20,6 +21,12 @@ HTTP.request = (options, callback)->
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
original_lookup = DNS.lookup
DNS.lookup = (domain, family, callback)->
Expand Down
11 changes: 9 additions & 2 deletions lib/replay/pass_through.coffee
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
HTTP = require("http")
HTTPS = require("https")

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

passThrough = (allow)->
if arguments.length == 0
Expand All @@ -14,12 +16,17 @@ passThrough = (allow)->
return (request, callback)->
if allow(request)
options =
protocol: request.url.protocol
hostname: request.url.hostname
port: request.url.port
path: request.url.path
method: request.method
headers: request.headers
http = httpRequest(options)

if request.url.protocol == "https:"
http = httpsRequest(options)
else
http = httpRequest(options)
http.on "error", (error)->
callback error
http.on "response", (response)->
Expand Down
2 changes: 1 addition & 1 deletion lib/replay/proxy.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class ProxyRequest extends HTTP.ClientRequest
constructor: (options = {}, @proxy)->
@method = (options.method || "GET").toUpperCase()
[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 = {}
if options.headers
for n,v of options.headers
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
},
"devDependencies": {
"express": "~2.5.9",
"mocha": "~1.0.2"
"mocha": "~1.0.2",
"async": "~0.1.18"
},
"repository": {
"type": "git",
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/example.com:3443/minimal
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GET /minimal
34 changes: 31 additions & 3 deletions test/helpers.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
# 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 3002 has no server, connections will be refused
# Port 3443 has a live https server


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


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


# Serve pages from localhost.
server = Express.createServer()
server.use Express.bodyParser()
Expand All @@ -35,9 +39,32 @@ server.get "/500", (req, res)->
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 = (callback)->
server.listen 3001, callback
Async.parallel [
(done)->
server.listen 3001, done
(done)->
ssl_server.listen 3443, done
], callback

return

if server._connected
Expand All @@ -53,4 +80,5 @@ setup = (callback)->
exports.assert = require("assert")
exports.setup = setup
exports.HTTP = require("http")
exports.HTTPS = require("https")
exports.Replay = Replay
29 changes: 28 additions & 1 deletion test/pass_through_test.coffee
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -63,6 +63,33 @@ describe "Pass through", ->
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.
describe "replay", ->
before ->
Expand Down
20 changes: 19 additions & 1 deletion test/replay_test.coffee
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{ assert, HTTP, Replay } = require("./helpers")
{ assert, HTTP, HTTPS, Replay } = require("./helpers")


# Test replaying results from fixtures in spec/fixtures.
Expand Down Expand Up @@ -50,6 +50,24 @@ describe "Replay", ->
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", ->
body = null

Expand Down
13 changes: 13 additions & 0 deletions test/ssl/certificate.pem
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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.