forked from olivere/elastic
-
Notifications
You must be signed in to change notification settings - Fork 0
/
errors.go
121 lines (112 loc) · 3.98 KB
/
errors.go
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
// Copyright 2012-2015 Oliver Eilhard. All rights reserved.
// Use of this source code is governed by a MIT-license.
// See http://olivere.mit-license.org/license.txt for details.
package elastic
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
)
var (
// ErrPluginNotFound is returned when using a service that requires a plugin that is not available.
ErrPluginNotFound = errors.New("elastic: plugin not found")
)
// checkResponse will return an error if the request/response indicates
// an error returned from Elasticsearch.
//
// HTTP status codes between in the range [200..299] are considered successful.
// Also, HTTP requests with method HEAD that return 404 are considered
// to be no errors. All other request/response combinations return an error.
//
// The func tries to parse error details as returned from Elasticsearch
// and encapsulates them in type elastic.Error.
func checkResponse(req *http.Request, res *http.Response) error {
// 200-299 are valid status codes
if res.StatusCode >= 200 && res.StatusCode <= 299 {
return nil
}
// HEAD requests with 404 are not an error
if req.Method == "HEAD" && res.StatusCode == 404 {
return nil
}
if res.Body == nil {
return &Error{Status: res.StatusCode}
}
slurp, err := ioutil.ReadAll(res.Body)
if err != nil {
return &Error{Status: res.StatusCode}
}
errReply := new(Error)
err = json.Unmarshal(slurp, errReply)
if err != nil {
return &Error{Status: res.StatusCode}
}
if errReply != nil {
if errReply.Status == 0 {
errReply.Status = res.StatusCode
}
return errReply
}
return &Error{Status: res.StatusCode}
}
// Error encapsulates error details as returned from Elasticsearch.
type Error struct {
Status int `json:"status"`
Details *ErrorDetails `json:"error,omitempty"`
}
// ErrorDetails encapsulate error details from Elasticsearch.
// It is used in e.g. elastic.Error and elastic.BulkResponseItem.
type ErrorDetails struct {
Type string `json:"type"`
Reason string `json:"reason"`
ResourceType string `json:"resource.type,omitempty"`
ResourceId string `json:"resource.id,omitempty"`
Index string `json:"index,omitempty"`
Phase string `json:"phase,omitempty"`
Grouped bool `json:"grouped,omitempty"`
CausedBy map[string]interface{} `json:"caused_by,omitempty"`
RootCause []*ErrorDetails `json:"root_cause,omitempty"`
FailedShards []map[string]interface{} `json:"failed_shards,omitempty"`
}
// Error returns a string representation of the error.
func (e *Error) Error() string {
if e.Details != nil && e.Details.Reason != "" {
return fmt.Sprintf("elastic: Error %d (%s): %s [type=%s]", e.Status, http.StatusText(e.Status), e.Details.Reason, e.Details.Type)
} else {
return fmt.Sprintf("elastic: Error %d (%s)", e.Status, http.StatusText(e.Status))
}
}
// IsNotFound returns true if the given error indicates that Elasticsearch
// returned HTTP status 404. The err parameter can be of type *elastic.Error,
// elastic.Error, *http.Response or int (indicating the HTTP status code).
func IsNotFound(err interface{}) bool {
switch e := err.(type) {
case *http.Response:
return e.StatusCode == http.StatusNotFound
case *Error:
return e.Status == http.StatusNotFound
case Error:
return e.Status == http.StatusNotFound
case int:
return e == http.StatusNotFound
}
return false
}
// IsTimeout returns true if the given error indicates that Elasticsearch
// returned HTTP status 408. The err parameter can be of type *elastic.Error,
// elastic.Error, *http.Response or int (indicating the HTTP status code).
func IsTimeout(err interface{}) bool {
switch e := err.(type) {
case *http.Response:
return e.StatusCode == http.StatusRequestTimeout
case *Error:
return e.Status == http.StatusRequestTimeout
case Error:
return e.Status == http.StatusRequestTimeout
case int:
return e == http.StatusRequestTimeout
}
return false
}