@@ -17,6 +17,7 @@ use juniper::FieldResult;
17
17
use std :: path :: PathBuf ;
18
18
use std :: fs :: File ;
19
19
use std :: io :: Read ;
20
+ use std :: str ;
20
21
21
22
struct Example {
22
23
filename : PathBuf ,
@@ -29,6 +30,15 @@ graphql_object!(Example: () |&self| {
29
30
file . read_to_string (& mut contents )? ;
30
31
Ok (contents )
31
32
}
33
+ field foo () -> FieldResult <Option <String >> {
34
+ // Some invalid bytes.
35
+ let invalid = vec! [128 , 223 ];
36
+
37
+ match str :: from_utf8 (& invalid ) {
38
+ Ok (s ) => Ok (Some (s . to_string ())),
39
+ Err (e ) => Err (e )? ,
40
+ }
41
+ }
32
42
});
33
43
34
44
# fn main () {}
@@ -41,6 +51,118 @@ there - those errors are automatically converted into `FieldError`.
41
51
42
52
When a field returns an error, the field's result is replaced by ` null ` , an
43
53
additional ` errors ` object is created at the top level of the response, and the
44
- execution is resumed. If an error is returned from a non-null field, such as the
54
+ execution is resumed. For example, with the previous example and the following
55
+ query:
56
+
57
+ ``` graphql
58
+ {
59
+ example {
60
+ contents
61
+ foo
62
+ }
63
+ }
64
+ ```
65
+
66
+ If ` str::from_utf8 ` resulted in a ` std::str::Utf8Error ` , the following would be
67
+ returned:
68
+
69
+ !FILENAME Response for nullable field with error
70
+
71
+ ``` js
72
+ {
73
+ " data" : {
74
+ " example" : {
75
+ contents: " <Contents of the file>" ,
76
+ foo: null ,
77
+ }
78
+ },
79
+ " errors" : [
80
+ " message" : " invalid utf-8 sequence of 2 bytes from index 0" ,
81
+ " locations" : [{ " line" : 2 , " column" : 4 }])
82
+ ]
83
+ }
84
+ ```
85
+
86
+ If an error is returned from a non-null field, such as the
45
87
example above, the ` null ` value is propagated up to the first nullable parent
46
88
field, or the root ` data ` object if there are no nullable fields.
89
+
90
+ For example, with the following query:
91
+
92
+ ``` graphql
93
+ {
94
+ example {
95
+ contents
96
+ }
97
+ }
98
+ ```
99
+
100
+ If ` File::open() ` above resulted in ` std::io::ErrorKind::PermissionDenied ` , the
101
+ following would be returned:
102
+
103
+ !FILENAME Response for non-null field with error and no nullable parent
104
+
105
+ ``` js
106
+ {
107
+ " errors" : [
108
+ " message" : " Permission denied (os error 13)" ,
109
+ " locations" : [{ " line" : 2 , " column" : 4 }])
110
+ ]
111
+ }
112
+ ```
113
+
114
+ ## Structured errors
115
+
116
+ Sometimes it is desirable to return additional structured error information
117
+ to clients. This can be accomplished by implementing [ ` IntoFieldError ` ] ( https://docs.rs/juniper/latest/juniper/trait.IntoFieldError.html ) :
118
+
119
+ ``` rust
120
+ # #[macro_use] extern crate juniper;
121
+ use juniper :: {FieldError , IntoFieldError };
122
+
123
+ enum CustomError {
124
+ WhateverNotSet ,
125
+ }
126
+
127
+ impl IntoFieldError for CustomError {
128
+ fn into_field_error (self ) -> FieldError {
129
+ match self {
130
+ CustomError :: WhateverNotSet => FieldError :: new (
131
+ " Whatever does not exist" ,
132
+ graphql_value! ({
133
+ " type" : " NO_WHATEVER"
134
+ }),
135
+ ),
136
+ }
137
+ }
138
+ }
139
+
140
+ struct Example {
141
+ whatever : Option <bool >,
142
+ }
143
+
144
+ graphql_object! (Example : () | & self | {
145
+ field whatever () -> Result <bool , CustomError > {
146
+ if let Some (value ) = self . whatever {
147
+ return Ok (value );
148
+ }
149
+ Err (CustomError :: WhateverNotSet )
150
+ }
151
+ });
152
+
153
+ # fn main () {}
154
+ ```
155
+
156
+ The specified structured error information is included in the [ ` extensions ` ] ( https://facebook.github.io/graphql/June2018/#sec-Errors ) key:
157
+
158
+ ``` js
159
+ {
160
+ " errors" : [
161
+ " message" : " Whatever does not exist" ,
162
+ " locations" : [{ " line" : 2 , " column" : 4 }]),
163
+ " extensions" : {
164
+ " type" : " NO_WHATEVER"
165
+ }
166
+ ]
167
+ }
168
+ ```
0 commit comments