openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
477 lines (476 loc) • 18 kB
HTML
<html lang="en">
<head>
<title>Code coverage report for src/middleware/requestMatching.coffee</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="../../prettify.css" />
<link rel="stylesheet" href="../../base.css" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type='text/css'>
.coverage-summary .sorter {
background-image: url(../../sort-arrow-sprite.png);
}
</style>
</head>
<body>
<div class='wrapper'>
<div class='pad1'>
<h1>
<a href="../../index.html">All files</a> / <a href="index.html">src/middleware</a> requestMatching.coffee
</h1>
<div class='clearfix'>
<div class='fl pad1y space-right2'>
<span class="strong">42.35% </span>
<span class="quiet">Statements</span>
<span class='fraction'>36/85</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">6.25% </span>
<span class="quiet">Branches</span>
<span class='fraction'>1/16</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">0% </span>
<span class="quiet">Functions</span>
<span class='fraction'>0/16</span>
</div>
<div class='fl pad1y space-right2'>
<span class="strong">41.67% </span>
<span class="quiet">Lines</span>
<span class='fraction'>35/84</span>
</div>
</div>
</div>
<div class='status-line low'></div>
<pre><table class="coverage">
<tr><td class="line-count quiet">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</td><td class="line-coverage quiet"><span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-no"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-neutral"> </span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-yes">2x</span>
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js"><span class="fstat-no" title="function not covered" ><span class="branch-1 cbranch-no" title="branch not covered" >Q = require "q"</span></span>
xpath = require "xpath"
dom = require("xmldom").DOMParser
logger = require "winston"
config = require '../config/config'
utils = require '../utils'
auditing = require '../auditing'
Channels = require('../model/channels')
Channel = Channels.Channel
statsdServer = config.get 'statsd'
application = config.get 'application'
himSourceID = config.get('auditing').auditEvents.auditSourceID
SDC = require 'statsd-client'
os = require 'os'
domain = "#{os.hostname()}.#{application.name}.appMetrics"
sdc = new SDC statsdServer
matchContent = <span class="fstat-no" title="function not covered" >(</span>channel, ctx) ->
if channel.matchContentRegex
<span class="cstat-no" title="statement not covered" > return matchRegex channel.matchContentRegex, ctx.body</span>
else if channel.matchContentXpath and channel.matchContentValue
<span class="cstat-no" title="statement not covered" > return matchXpath channel.matchContentXpath, channel.matchContentValue, ctx.body</span>
else if channel.matchContentJson and channel.matchContentValue
<span class="cstat-no" title="statement not covered" > return matchJsonPath channel.matchContentJson, channel.matchContentValue, ctx.body</span>
else if channel.matchContentXpath or channel.matchContentJson
# if only the match expression is given, deny access
# this is an invalid channel
<span class="cstat-no" title="statement not covered" > logger.error "Channel with name '#{channel.name}' is invalid as it has a content match expression but no value to match"</span>
<span class="cstat-no" title="statement not covered" > return false</span>
else
<span class="cstat-no" title="statement not covered" > return true</span>
matchRegex = <span class="fstat-no" title="function not covered" >(</span>regexPat, body) ->
<span class="cstat-no" title="statement not covered" > regex = new R</span>egExp regexPat
<span class="cstat-no" title="statement not covered" > return r</span>egex.test body.toString()
matchXpath = <span class="fstat-no" title="function not covered" >(</span>xpathStr, val, xml) ->
<span class="cstat-no" title="statement not covered" > doc = new d</span>om().parseFromString(xml.toString())
<span class="cstat-no" title="statement not covered" > xpathVal = x</span>path.select(xpathStr, doc).toString()
<span class="cstat-no" title="statement not covered" > return val == x</span>pathVal
matchJsonPath = <span class="fstat-no" title="function not covered" >(</span>jsonPath, val, json) ->
<span class="cstat-no" title="statement not covered" > jsonObj = J</span>SON.parse json.toString()
<span class="cstat-no" title="statement not covered" > jsonVal = g</span>etJSONValByString jsonObj, jsonPath
<span class="cstat-no" title="statement not covered" > return val == j</span>sonVal.toString()
# taken from http://stackoverflow.com/a/6491621/588776
# readbility improved from the stackoverflow answer
getJSONValByString = <span class="fstat-no" title="function not covered" >(</span>jsonObj, jsonPath) ->
<span class="cstat-no" title="statement not covered" > jsonPath = j</span>sonPath.replace(/\[(\w+)\]/g, '.$1') # convert indexes to properties
<span class="cstat-no" title="statement not covered" > jsonPath = j</span>sonPath.replace(/^\./, '') # strip a leading dot
<span class="cstat-no" title="statement not covered" > parts = j</span>sonPath.split('.')
<span class="cstat-no" title="statement not covered" > while parts.length</span>
<span class="cstat-no" title="statement not covered" > part = p</span>arts.shift()
if part of jsonObj
<span class="cstat-no" title="statement not covered" > jsonObj = jsonObj[part]</span>
else
<span class="cstat-no" title="statement not covered" > return</span>
<span class="cstat-no" title="statement not covered" > return j</span>sonObj
extractContentType = <span class="fstat-no" title="function not covered" >(</span>ctHeader) ->
<span class="cstat-no" title="statement not covered" > index = c</span>tHeader.indexOf ';'
if index isnt -1
<span class="cstat-no" title="statement not covered" > return ctHeader.substring(0, index).trim()</span>
else
<span class="cstat-no" title="statement not covered" > return ctHeader.trim()</span>
matchUrlPattern = <span class="fstat-no" title="function not covered" >(</span>channel, ctx) ->
<span class="cstat-no" title="statement not covered" > pat = new R</span>egExp channel.urlPattern
<span class="cstat-no" title="statement not covered" > return p</span>at.test ctx.request.path
matchContentTypes = <span class="fstat-no" title="function not covered" >(</span>channel, ctx) ->
if channel.matchContentTypes?.length > 0
<span class="cstat-no" title="statement not covered" > if ctx.request.header and ctx.request.header['content-type']</span>
<span class="cstat-no" title="statement not covered" > ct = e</span>xtractContentType ctx.request.header['content-type']
<span class="cstat-no" title="statement not covered" > if ct in channel.matchContentTypes</span>
<span class="cstat-no" title="statement not covered" > return true</span>
else
# deny access to channel if the content type doesnt match
<span class="cstat-no" title="statement not covered" > return false</span>
else
# deny access to channel if the content type isnt set
<span class="cstat-no" title="statement not covered" > return false</span>
else
<span class="cstat-no" title="statement not covered" > return true # don't match on content type if this channel doesn't require it</span>
matchFunctions = [
matchUrlPattern,
matchContent,
matchContentTypes
]
matchChannel = <span class="fstat-no" title="function not covered" >(</span>channel, ctx) ->
matchFunctions.every <span class="fstat-no" title="function not covered" >(</span>matchFunc) ->
<span class="cstat-no" title="statement not covered" > return m</span>atchFunc channel, ctx
findMatchingChannel = <span class="fstat-no" title="function not covered" >(</span>channels, ctx) ->
<span class="cstat-no" title="statement not covered" > return c</span>hannels.find <span class="fstat-no" title="function not covered" >(</span>channel) ->
<span class="cstat-no" title="statement not covered" > return m</span>atchChannel channel, ctx
matchRequest = <span class="fstat-no" title="function not covered" >(</span>ctx, done) ->
utils.getAllChannelsInPriorityOrder <span class="fstat-no" title="function not covered" >(</span>err, channels) ->
if err
<span class="cstat-no" title="statement not covered" > ctx.response.status = 5</span>00
<span class="cstat-no" title="statement not covered" > logger.error 'Could not fetch OpenHIM channels', err</span>
<span class="cstat-no" title="statement not covered" > return done()</span>
<span class="cstat-no" title="statement not covered" > channels = c</span>hannels.filter Channels.isChannelEnabled
<span class="cstat-no" title="statement not covered" > match = f</span>indMatchingChannel channels, ctx
done null, match
exports.koaMiddleware = <span class="fstat-no" title="function not covered" >(</span>next) ->
<span class="cstat-no" title="statement not covered" ></span> startTime = new Date() if statsdServer.enabled
<span class="cstat-no" title="statement not covered" > matchReq = Q</span>.denodeify matchRequest
<span class="cstat-no" title="statement not covered" > match = y</span>ield matchReq this
if match?
<span class="cstat-no" title="statement not covered" > logger.info "The channel that matches the request #{this.request.path} is: #{match.name}"</span>
<span class="cstat-no" title="statement not covered" > this.matchingChannel = match</span>
else
<span class="cstat-no" title="statement not covered" > logger.info "No channel matched the request #{this.request.path}"</span>
<span class="cstat-no" title="statement not covered" ></span> sdc.timing "#{domain}.authorisationMiddleware", startTime if statsdServer.enabled
yield next
# export private functions for unit testing
# note: you cant spy on these method because of this :(
if process.env.NODE_ENV == "test"
exports.matchContent = matchContent
exports.matchRegex = matchRegex
exports.matchXpath = matchXpath
exports.matchJsonPath = matchJsonPath
exports.extractContentType = extractContentType
exports.matchRequest = matchRequest
</pre></td></tr>
</table></pre>
<div class='push'></div><!-- for sticky footer -->
</div><!-- /wrapper -->
<div class='footer quiet pad2 space-top1 center small'>
Code coverage
generated by <a href="http://istanbul-js.org/" target="_blank">istanbul</a> at Mon Oct 10 2016 13:39:22 GMT+0200 (SAST)
</div>
</div>
<script src="../../prettify.js"></script>
<script>
window.onload = function () {
if (typeof prettyPrint === 'function') {
prettyPrint();
}
};
</script>
<script src="../../sorter.js"></script>
</body>
</html>