-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathcmrQuery.js
More file actions
112 lines (94 loc) · 3.29 KB
/
cmrQuery.js
File metadata and controls
112 lines (94 loc) · 3.29 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
import axios from 'axios'
import snakecaseKeys from 'snakecase-keys'
import { downcaseKeys } from './downcaseKeys'
import { pickIgnoringCase } from './pickIgnoringCase'
import { prepKeysForCmr } from './prepKeysForCmr'
/**
* Make a request to CMR and return the promise
* @param {Object} params
* @param {Object} params.headers Headers to send to CMR
* @param {Array} params.nonIndexedKeys Parameter names that should not be indexed before sending to CMR
* @param {Object} params.options Additional Options (format)
* @param {Object} params.params Parameters to send to CMR
* @param {String} params.conceptType Concept type to search
*/
export const cmrQuery = ({
conceptType,
headers = {},
nonIndexedKeys = [],
options = {},
params
}) => {
const {
format = 'json',
path = `search/${conceptType}.${format}`
} = options
// Default headers
const defaultHeaders = {
Accept: 'application/json',
'Content-Type': 'application/json'
}
// Merge default headers into the provided headers and then pick out only permitted values
const permittedHeaders = pickIgnoringCase({
...defaultHeaders,
...headers
}, [
'Accept',
'Authorization',
'Client-Id',
'CMR-Request-Id',
'CMR-Search-After'
])
const {
'client-id': clientId,
'cmr-request-id': requestId
} = downcaseKeys(permittedHeaders)
const requestConfiguration = {
headers: permittedHeaders,
method: 'GET',
url: `${process.env.cmrRootUrl}/${path}`
}
// Create a new object with the original params and add all_revisions if needed
const updatedParams = options.allRevisions
? {
...params,
all_revisions: true
}
: params
// Append any query arguments based on provided params
const cmrParameters = prepKeysForCmr(snakecaseKeys(updatedParams), nonIndexedKeys)
const { env } = process
const { maximumQueryPathLength } = env
if (cmrParameters.length > maximumQueryPathLength) {
requestConfiguration.data = cmrParameters
requestConfiguration.method = 'POST'
} else {
// Join the current url and the query parameters
requestConfiguration.url = [requestConfiguration.url, cmrParameters].filter(Boolean).join('?')
}
// Interceptors require an instance of axios
const instance = axios.create()
const { interceptors } = instance
const {
request: requestInterceptor,
response: responseInterceptor
} = interceptors
// Intercept the request to inject timing information
requestInterceptor.use((config) => {
// eslint-disable-next-line no-param-reassign
config.headers['request-startTime'] = process.hrtime()
return config
})
responseInterceptor.use((response) => {
// Determine total time to complete this request
const start = response.config.headers['request-startTime']
const end = process.hrtime(start)
const milliseconds = Math.round((end[0] * 1000) + (end[1] / 1000000))
// Retrieve the reported timing from CMR
const { 'cmr-took': cmrTook } = downcaseKeys(response.headers)
response.headers['request-duration'] = milliseconds
console.log(`Request ${requestId} from ${clientId} to [concept: ${conceptType}, format: ${format}] completed external request in [reported: ${cmrTook} ms, observed: ${milliseconds} ms]`)
return response
})
return instance.request(requestConfiguration)
}