@@ -102,36 +102,148 @@ n2k_cloud_signed_query() {
102102 printf ' %s&signature=%s' " ${query} " " ${signature_enc} "
103103}
104104
105+ n2k_cloud_api_prefers_post () {
106+ local command=" $1 "
107+ case " ${command} " in
108+ createDiskOffering|importVolume|deployVirtualMachineForVolume|updateVolume|attachVolume|startVirtualMachine)
109+ return 0
110+ ;;
111+ * )
112+ return 1
113+ ;;
114+ esac
115+ }
116+
117+ n2k_cloud_api_method () {
118+ local command=" $1 " query_len=" $2 "
119+ local requested threshold
120+ requested=" $( printf ' %s' " ${N2K_CLOUD_API_METHOD:- auto} " | tr ' [:lower:]' ' [:upper:]' ) "
121+ threshold=" ${N2K_CLOUD_POST_THRESHOLD:- 1800} "
122+ [[ " ${threshold} " =~ ^[0-9]+$ ]] || threshold=1800
123+
124+ case " ${requested} " in
125+ GET|POST)
126+ printf ' %s' " ${requested} "
127+ return 0
128+ ;;
129+ esac
130+
131+ if n2k_cloud_api_prefers_post " ${command} " || (( query_len >= threshold )) ; then
132+ printf ' %s' " POST"
133+ else
134+ printf ' %s' " GET"
135+ fi
136+ }
137+
105138n2k_cloud_command_params_json () {
106139 local command=" $1 " api_key=" $2 " params_json=" ${3:- } "
107- if [[ -z " ${params_json} " ]]; then
108- params_json=" {}"
109- fi
140+ [[ -n " ${params_json} " ]] || params_json=" {}"
110141 printf ' %s' " ${params_json} " | jq -c \
111142 --arg command " ${command} " \
112143 --arg api_key " ${api_key} " \
113144 ' . + {command:$command, apiKey:$api_key, response:"json"}'
114145}
115146
147+ n2k_cloud_response_error_summary () {
148+ local body_file=" $1 " header_file=" $2 "
149+ local json_summary=" " header_desc=" "
150+
151+ if [[ -s " ${body_file} " ]]; then
152+ json_summary=" $( jq -r '
153+ to_entries[0].value as $v
154+ | [
155+ (if ($v.errorcode // null) != null then "errorcode=" + ($v.errorcode | tostring) else empty end),
156+ (if ($v.cserrorcode // null) != null then "cserrorcode=" + ($v.cserrorcode | tostring) else empty end),
157+ (if (($v.errortext // "") | tostring | length) > 0 then "errortext=" + ($v.errortext | tostring) else empty end)
158+ ]
159+ | join(" ")
160+ ' " ${body_file} " 2> /dev/null || true) "
161+ fi
162+
163+ if [[ -s " ${header_file} " ]]; then
164+ header_desc=" $( awk -F' : *' ' tolower($1) == "x-description" {print substr($0, index($0, $2))}' " ${header_file} " | tail -n 1 | tr -d ' \r' || true) "
165+ fi
166+
167+ if [[ -n " ${json_summary} " && -n " ${header_desc} " && " ${json_summary} " != * " ${header_desc} " * ]]; then
168+ printf ' %s x-description=%s' " ${json_summary} " " ${header_desc} "
169+ elif [[ -n " ${json_summary} " ]]; then
170+ printf ' %s' " ${json_summary} "
171+ elif [[ -n " ${header_desc} " ]]; then
172+ printf ' x-description=%s' " ${header_desc} "
173+ elif [[ -s " ${body_file} " ]]; then
174+ head -c 512 " ${body_file} " | tr ' \n' ' '
175+ fi
176+ }
177+
178+ n2k_cloud_api_report_failure () {
179+ local command=" $1 " method=" $2 " query_len=" $3 " http_status=" $4 " body_file=" $5 " header_file=" $6 " curl_err_file=" $7 "
180+ local summary curl_err
181+
182+ echo " Cloud API request failed: command=${command} method=${method} http_status=${http_status:- 000} query_length=${query_len} " >&2
183+ summary=" $( n2k_cloud_response_error_summary " ${body_file} " " ${header_file} " ) "
184+ if [[ -n " ${summary} " ]]; then
185+ echo " Cloud API error: ${summary} " >&2
186+ fi
187+ if [[ -s " ${curl_err_file} " ]]; then
188+ curl_err=" $( tr ' \n' ' ' < " ${curl_err_file} " ) "
189+ [[ -n " ${curl_err} " ]] && echo " Cloud API curl error: ${curl_err} " >&2
190+ fi
191+ }
192+
116193n2k_cloud_api_get () {
117194 local endpoint=" $1 " api_key=" $2 " secret_key=" $3 " command=" $4 " params_json=" ${5:- } "
118- local connect_timeout max_time body_params query url
119- if [[ -z " ${params_json} " ]]; then
120- params_json=" {}"
121- fi
195+ local connect_timeout max_time body_params query url method query_len
196+ local body_file header_file curl_err_file http_status curl_rc
197+ [[ -n " ${params_json} " ]] || params_json=" {}"
122198 endpoint=" $( n2k_cloud_normalize_endpoint " ${endpoint} " ) "
123199 n2k_cloud_require_credentials " ${endpoint} " " ${api_key} " " ${secret_key} "
124200 connect_timeout=" ${N2K_CLOUD_CONNECT_TIMEOUT:- 10} "
125201 max_time=" ${N2K_CLOUD_MAX_TIME:- 120} "
126202
127203 body_params=" $( n2k_cloud_command_params_json " ${command} " " ${api_key} " " ${params_json} " ) "
128204 query=" $( n2k_cloud_signed_query " ${body_params} " " ${secret_key} " ) "
205+ query_len=" ${# query} "
206+ method=" $( n2k_cloud_api_method " ${command} " " ${query_len} " ) "
129207 url=" ${endpoint} ?${query} "
130208
131- curl --globoff --silent --show-error --fail \
132- --connect-timeout " ${connect_timeout} " \
133- --max-time " ${max_time} " \
134- " ${url} "
209+ body_file=" $( mktemp " ${TMPDIR:-/ tmp} /n2k-cloud-body.XXXXXX" ) "
210+ header_file=" $( mktemp " ${TMPDIR:-/ tmp} /n2k-cloud-headers.XXXXXX" ) "
211+ curl_err_file=" $( mktemp " ${TMPDIR:-/ tmp} /n2k-cloud-curl.XXXXXX" ) "
212+
213+ if [[ " ${method} " == " POST" ]]; then
214+ http_status=" $( curl --globoff --silent --show-error \
215+ --request POST \
216+ --header " Content-Type: application/x-www-form-urlencoded" \
217+ --data-binary " ${query} " \
218+ --connect-timeout " ${connect_timeout} " \
219+ --max-time " ${max_time} " \
220+ --dump-header " ${header_file} " \
221+ --output " ${body_file} " \
222+ --write-out " %{http_code}" \
223+ " ${endpoint} " 2> " ${curl_err_file} " ) "
224+ curl_rc=$?
225+ if (( curl_rc != 0 )) || ! [[ " ${http_status} " =~ ^[0-9]{3}$ ]] || (( http_status >= 400 )) ; then
226+ n2k_cloud_api_report_failure " ${command} " " POST" " ${query_len} " " ${http_status} " " ${body_file} " " ${header_file} " " ${curl_err_file} "
227+ rm -f " ${body_file} " " ${header_file} " " ${curl_err_file} "
228+ return 1
229+ fi
230+ else
231+ http_status=" $( curl --globoff --silent --show-error \
232+ --connect-timeout " ${connect_timeout} " \
233+ --max-time " ${max_time} " \
234+ --dump-header " ${header_file} " \
235+ --output " ${body_file} " \
236+ --write-out " %{http_code}" \
237+ " ${url} " 2> " ${curl_err_file} " ) "
238+ curl_rc=$?
239+ if (( curl_rc != 0 )) || ! [[ " ${http_status} " =~ ^[0-9]{3}$ ]] || (( http_status >= 400 )) ; then
240+ n2k_cloud_api_report_failure " ${command} " " GET" " ${query_len} " " ${http_status} " " ${body_file} " " ${header_file} " " ${curl_err_file} "
241+ rm -f " ${body_file} " " ${header_file} " " ${curl_err_file} "
242+ return 1
243+ fi
244+ fi
245+ cat " ${body_file} "
246+ rm -f " ${body_file} " " ${header_file} " " ${curl_err_file} "
135247}
136248
137249n2k_cloud_response_body () {
0 commit comments