Skip to content

Commit 5a8c46b

Browse files
committed
doc: mention the HTTP status code used for streaming & fix client code
1 parent b8c79d9 commit 5a8c46b

File tree

1 file changed

+42
-16
lines changed

1 file changed

+42
-16
lines changed

doc/12-icinga2-api.md

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,31 @@ was malformed.
154154
A status in the range of 500 generally means that there was a server-side problem
155155
and Icinga 2 is unable to process your request.
156156

157+
Starting with Icinga 2 v2.16.0 we introduced HTTP chunked transfer encoding for some of the API endpoints.
158+
The `/v1/actions/` and `/v1/objects/` endpoints will always return a `202 Accepted` status code as a general HTTP
159+
status, but their response body will contain the actual status code for each individual result entry. So, even if
160+
the overall HTTP status code is `202 Accepted`, some of the individual result entries may still report `4xx` or `5xx`
161+
status codes. For example, you may see such a response when trying to delete multiple objects.
162+
163+
```json
164+
{
165+
"results": [
166+
{
167+
"code": 200,
168+
"status": "Object was deleted."
169+
},
170+
{
171+
"code": 500,
172+
"status": "Object could not be deleted.",
173+
}
174+
]
175+
}
176+
```
177+
178+
In such cases, you should always check the individual result entries for their status code and not rely solely on the
179+
overall HTTP status code. There are also a bunch of other endpoints which support chunked transfer encoding, but have
180+
no behavioral difference in terms of the overall HTTP status code and will continue to return `200` for successful requests.
181+
157182
### Security <a id="icinga2-api-security"></a>
158183

159184
* HTTPS only.
@@ -2742,7 +2767,7 @@ r = requests.post(request_url,
27422767
print "Request URL: " + str(r.url)
27432768
print "Status code: " + str(r.status_code)
27442769
2745-
if (r.status_code == 200):
2770+
if (r.status_code == 202):
27462771
print "Result: " + json.dumps(r.json())
27472772
else:
27482773
print r.text
@@ -2791,7 +2816,7 @@ rescue => e
27912816
end
27922817
27932818
puts "Status: " + response.code.to_s
2794-
if response.code == 200
2819+
if response.code == 202
27952820
puts "Result: " + (JSON.pretty_generate JSON.parse(response.body))
27962821
else
27972822
puts "Error: " + response
@@ -2846,7 +2871,7 @@ $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
28462871
curl_close($ch);
28472872
print "Status: " . $code . "\n";
28482873
2849-
if ($code == 200) {
2874+
if ($code == 202) {
28502875
$response = json_decode($response, true);
28512876
print_r($response);
28522877
}
@@ -2898,7 +2923,7 @@ $client->POST("/v1/objects/services", $data);
28982923
my $status = $client->responseCode();
28992924
print "Status: " . $status . "\n";
29002925
my $response = $client->responseContent();
2901-
if ($status == 200) {
2926+
if ($status == 202) {
29022927
print "Result: " . Dumper(decode_json($response)) . "\n";
29032928
} else {
29042929
print "Error: " . $response . "\n";
@@ -2921,14 +2946,13 @@ import (
29212946
"bytes"
29222947
"crypto/tls"
29232948
"log"
2924-
"io/ioutil"
29252949
"net/http"
29262950
)
29272951
29282952
func main() {
2929-
var urlBase= "https://localhost:5665"
2930-
var apiUser= "root"
2931-
var apiPass= "icinga"
2953+
var urlBase = "https://localhost:5665"
2954+
var apiUser = "root"
2955+
var apiPass = "icinga"
29322956
29332957
urlEndpoint := urlBase + "/v1/objects/services"
29342958
@@ -2943,7 +2967,7 @@ func main() {
29432967
"filter": "match(\"ping*\", service.name)"
29442968
}`)
29452969
2946-
req, err := http.NewRequest("POST", urlEndpoint, bytes.NewBuffer(requestBody))
2970+
req, err := http.NewRequest("POST", urlEndpoint, bytes.NewReader(requestBody))
29472971
req.Header.Set("Accept", "application/json")
29482972
req.Header.Set("X-HTTP-Method-Override", "GET")
29492973
@@ -2958,22 +2982,24 @@ func main() {
29582982
29592983
log.Print("Response status:", resp.Status)
29602984
2961-
bodyBytes, _ := ioutil.ReadAll(resp.Body)
2962-
bodyString := string(bodyBytes)
2985+
buf := new(bytes.Buffer)
2986+
if _, err := buf.ReadFrom(resp.Body); err != nil {
2987+
log.Fatal("Read error:", err)
2988+
return
2989+
}
29632990
2964-
if resp.StatusCode == http.StatusOK {
2965-
log.Print("Result: " + bodyString)
2991+
if resp.StatusCode == http.StatusAccepted {
2992+
log.Print("Result: " + buf.String())
29662993
} else {
2967-
log.Fatal(bodyString)
2994+
log.Fatal(buf.String())
29682995
}
29692996
}
29702997
```
29712998

29722999
Build the binary:
29733000

29743001
```bash
2975-
go build icinga.go
2976-
./icinga
3002+
go run ./icinga.go
29773003
```
29783004

29793005
#### Example API Client in Powershell <a id="icinga2-api-clients-programmatic-examples-powershell"></a>

0 commit comments

Comments
 (0)