xhr_server.coffee
5.48 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
express = require 'express'
fs = require 'fs'
http = require 'http'
https = require 'https'
open = require 'open'
# express.js server for testing the Web application.
class XhrServer
# Starts up a HTTP server.
constructor: (@port, @useHttps) ->
@createApp()
# Opens the test URL in a browser.
openBrowser: (appName) ->
open @testUrl(), appName
# The URL that should be used to start the tests.
testUrl: ->
"https://localhost:#{@port}/test/html/browser_test.html"
# The self-signed certificate used by this server.
sslCertificate: ->
return null unless @useHttps
keyMaterial = fs.readFileSync 'test/ssl/cert.pem', 'utf8'
certIndex = keyMaterial.indexOf '-----BEGIN CERTIFICATE-----'
keyMaterial.substring certIndex
# The key for the self-signed certificate used by this server.
sslKey: ->
return null unless @useHttps
keyMaterial = fs.readFileSync 'test/ssl/cert.pem', 'utf8'
certIndex = keyMaterial.indexOf '-----BEGIN CERTIFICATE-----'
keyMaterial.substring 0, certIndex
# The server code.
createApp: ->
@app = express()
## Middleware.
# CORS headers on everything, in case that ever gets implemented.
@app.use (request, response, next) ->
response.header 'Access-Control-Allow-Origin', '*'
response.header 'Access-Control-Allow-Methods', 'DELETE,GET,POST,PUT'
response.header 'Access-Control-Allow-Headers',
'Content-Type, Authorization'
next()
@app.use express.static(fs.realpathSync(__dirname + '/../../../'),
{ dotfiles: 'allow' })
## Routes
@app.all '/_/method', (request, response) ->
body = request.method
response.header 'Content-Type', 'text/plain; charset=utf-8'
response.header 'Content-Length', body.length.toString()
response.end body
# Echoes the request body. Used to test send(data).
@app.post '/_/echo', (request, response) ->
if request.headers['content-type']
response.header 'Content-Type', request.headers['content-type']
if request.headers['content-length']
response.header 'Content-Length', request.headers['content-length']
request.on 'data', (chunk) -> response.write chunk
request.on 'end', -> response.end()
# Lists the request headers. Used to test setRequestHeader().
@app.all '/_/headers', (request, response) ->
body = JSON.stringify request.headers
response.header 'Content-Type', 'application/json'
response.header 'Content-Length', body.length.toString()
response.end body
# Sets the response headers in the request. Used to test getResponse*().
@app.post '/_/get_headers', (request, response) ->
jsonString = ''
request.on 'data', (chunk) -> jsonString += chunk
request.on 'end', ->
headers = JSON.parse jsonString
for name, value of headers
response.header name, value
response.header 'Content-Length', '0'
response.end ''
# Sets every response detail. Used for error testing.
@app.post '/_/response', (request, response) ->
jsonString = ''
request.on 'data', (chunk) -> jsonString += chunk
request.on 'end', ->
json = JSON.parse jsonString
response.writeHead json.code, json.status, json.headers
response.write json.body if json.body
response.end()
# Sends data in small chunks. Used for event testing.
@app.post '/_/drip', (request, response) ->
request.connection.setNoDelay()
jsonString = ''
request.on 'data', (chunk) -> jsonString += chunk
request.on 'end', ->
json = JSON.parse jsonString
sentDrips = 0
drip = new Array(json.size + 1).join '.'
response.header 'Content-Type', 'text/plain'
if json.length
response.header 'Content-Length', (json.drips * json.size).toString()
sendDrip = =>
response.write drip
sentDrips += 1
if sentDrips >= json.drips
response.end()
else
setTimeout sendDrip, json.ms
sendDrip()
# Returns a HTTP redirect. Used to test the redirection handling code.
@app.all '/_/redirect/:status/:next_page', (request, response) =>
response.statusCode = parseInt(request.params.status)
response.header 'Location',
"http://#{request.get('host')}/_/#{request.params.next_page}"
body = "<p>This is supposed to have a redirect link</p>"
response.header 'Content-Type', 'text/html'
response.header 'Content-Length', body.length.toString()
response.header 'X-Redirect-Header', 'should not show up'
response.end body
# Requested when the browser test suite completes.
@app.get '/diediedie', (request, response) =>
if 'failed' of request.query
failed = parseInt request.query['failed']
else
failed = 1
total = parseInt request.query['total'] || 0
passed = total - failed
exitCode = if failed == 0 then 0 else 1
console.log "#{passed} passed, #{failed} failed"
response.header 'Content-Type', 'image/png'
response.header 'Content-Length', '0'
response.end ''
unless 'NO_EXIT' of process.env
@server.close()
process.exit exitCode
if @useHttps
options = key: @sslKey(), cert: @sslCertificate()
@server = https.createServer options, @app
else
@server = http.createServer @app
@server.listen @port
module.exports.https = new XhrServer 8911, true
module.exports.http = new XhrServer 8912, false