@@ -178,7 +178,6 @@ class TransactionRunner
178178 request : transaction .request
179179 @configuration .emitter .emit ' test error' , error, test if error
180180
181-
182181 sandboxedHookResultsHandler : (err , data , results = {}, callback ) ->
183182 return callback err if err
184183 # reference to `transaction` gets lost here if whole object is assigned
@@ -193,7 +192,6 @@ class TransactionRunner
193192 callback ()
194193 return
195194
196-
197195 sandboxedWrappedCode : (hookCode ) ->
198196 return """
199197 // run the hook
@@ -210,7 +208,6 @@ class TransactionRunner
210208 output;
211209 """
212210
213-
214211 runSandboxedHookFromString : (hookString , data , callback ) ->
215212 wrappedCode = @ sandboxedWrappedCode hookString
216213
@@ -229,7 +226,6 @@ class TransactionRunner
229226 sandbox .kill ()
230227 @ sandboxedHookResultsHandler err, data, result, callback
231228
232-
233229 # Will be used runHook instead in next major release, see deprecation warning
234230 runLegacyHook : (hook , data , callback ) ->
235231 # not sandboxed mode - hook is a function
@@ -265,7 +261,6 @@ class TransactionRunner
265261 if typeof (hook) == ' string'
266262 @ runSandboxedHookFromString hook, data, callback
267263
268-
269264 runHook : (hook , data , callback ) ->
270265 # not sandboxed mode - hook is a function
271266 if typeof (hook) == ' function'
@@ -288,25 +283,17 @@ class TransactionRunner
288283 {origin , request , response } = transaction
289284 mediaType = configuration .data [origin .filename ]? .mediaType or ' text/vnd.apiblueprint'
290285
291- # parse the server URL just once
292- @parsedUrl ?= url .parse configuration[' server' ]
293-
294- # Joins paths regardless of slashes. There may be a nice way in the future:
295- # https://github.com/joyent/node/issues/2216 Note that path.join will fail
296- # on windows, and url.resolve can have undesirable behavior depending
297- # on slashes
298- if @parsedUrl [' path' ] is " /"
299- fullPath = request[' uri' ]
300- else
301- fullPath = ' /' + [@parsedUrl [' path' ].replace (/ ^ \/ | \/ $ / g , " " ), request[' uri' ].replace (/ ^ \/ | \/ $ / g , " " )].join (" /" )
286+ # Parse the server URL (just once, caching it in @parsedUrl)
287+ @parsedUrl ?= @ parseServerUrl (configuration .server )
288+ fullPath = @ getFullPath (@parsedUrl .path , request .uri )
302289
303- flatHeaders = flattenHeaders request[' headers' ]
290+ flatHeaders = flattenHeaders ( request[' headers' ])
304291
305- # Add Dredd user agent if no User-Agent present
292+ # Add Dredd User-Agent ( if no User-Agent is already present)
306293 if not flatHeaders[' User-Agent' ]
307294 system = os .type () + ' ' + os .release () + ' ; ' + os .arch ()
308295 flatHeaders[' User-Agent' ] = " Dredd/" + \
309- packageConfig[ ' version' ] + \
296+ packageConfig . version + \
310297 " (" + system + " )"
311298
312299 # Parse and add headers from the config to the transaction
@@ -341,9 +328,9 @@ class TransactionRunner
341328
342329 configuredTransaction =
343330 name : transaction .name
344- id : request[ ' method' ] + ' ' + request[ ' uri' ]
345- host : @parsedUrl [ ' hostname' ]
346- port : @parsedUrl [ ' port' ]
331+ id : request . method + ' ' + request . uri
332+ host : @parsedUrl . hostname
333+ port : @parsedUrl . port
347334 request : request
348335 expected : expected
349336 origin : origin
@@ -353,6 +340,32 @@ class TransactionRunner
353340
354341 return callback (null , configuredTransaction)
355342
343+ parseServerUrl : (serverUrl ) ->
344+ unless serverUrl .match (/ ^ https? :\/\/ / i )
345+ # Protocol is missing. Remove any : or / at the beginning of the URL
346+ # and prepend the URL with 'http://' (assumed as default fallback).
347+ serverUrl = ' http://' + serverUrl .replace (/ ^ [:\/ ] * / , ' ' )
348+ url .parse (serverUrl)
349+
350+ getFullPath : (serverPath , requestPath ) ->
351+ return requestPath if serverPath is ' /'
352+ return serverPath unless requestPath
353+
354+ # Join two paths
355+ #
356+ # How:
357+ # Removes all slashes from the beginning and from the end of each segment.
358+ # Then joins them together with a single slash. Then prepends the whole
359+ # string with a single slash.
360+ #
361+ # Why:
362+ # Note that 'path.join' won't work on Windows and 'url.resolve' can have
363+ # undesirable behavior depending on slashes.
364+ # See also https://github.com/joyent/node/issues/2216
365+ segments = [serverPath, requestPath]
366+ segments = (segment .replace (/ ^ \/ | \/ $ / g , ' ' ) for segment in segments)
367+ return ' /' + segments .join (' /' )
368+
356369 emitResult : (transaction , callback ) ->
357370 # if transaction test was executed and was not skipped or failed
358371 if transaction .test
0 commit comments