1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.rest.client;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.TestUtils.assertBean;
21 import static org.apache.juneau.TestUtils.assertList;
22 import static org.apache.juneau.TestUtils.assertString;
23 import static org.apache.juneau.assertions.Assertions.*;
24 import static org.apache.juneau.common.utils.IOUtils.*;
25 import static org.apache.juneau.http.HttpHeaders.*;
26 import static org.junit.jupiter.api.Assertions.*;
27
28 import java.io.*;
29 import java.util.*;
30 import java.util.regex.*;
31
32 import org.apache.http.*;
33 import org.apache.http.conn.*;
34 import org.apache.http.entity.*;
35 import org.apache.http.message.*;
36 import org.apache.juneau.*;
37 import org.apache.juneau.common.utils.*;
38 import org.apache.juneau.json.*;
39 import org.apache.juneau.parser.*;
40 import org.apache.juneau.rest.annotation.*;
41 import org.apache.juneau.rest.mock.*;
42 import org.apache.juneau.rest.servlet.*;
43 import org.apache.juneau.xml.*;
44 import org.junit.jupiter.api.*;
45
46 class RestClient_Response_Body_Test extends TestBase {
47
48 public static class ABean {
49 public int f;
50 static ABean get() {
51 var x = new ABean();
52 x.f = 1;
53 return x;
54 }
55 }
56
57 private static ABean bean = ABean.get();
58
59 @Rest
60 public static class A extends BasicRestObject {
61 @RestPost
62 public InputStream echo(InputStream is) {
63 return is;
64 }
65 @RestGet
66 public ABean bean() {
67 return bean;
68 }
69 @RestOp
70 public void head() {}
71 }
72
73 public static class TestClient extends MockRestClient {
74 public HttpEntity responseEntity;
75 public Header[] headers = {};
76 public TestClient entity(HttpEntity entity) {
77 this.responseEntity = entity;
78 return this;
79 }
80 public TestClient headers(Header...o) {
81 this.headers = o;
82 return this;
83 }
84 public TestClient(MockRestClient.Builder builder) {
85 super(builder);
86 }
87 @Override
88 protected MockRestResponse createResponse(RestRequest request, HttpResponse httpResponse, Parser parser) throws RestCallException {
89 var r = new BasicHttpResponse(new ProtocolVersion("http", 1,1),200,"");
90 r.setEntity(responseEntity);
91 for (var h : headers)
92 r.addHeader(h);
93 return new MockRestResponse(this, request, r, parser);
94 }
95 }
96
97 @Test void a01_basic() throws Exception {
98 client().build().post("/echo",bean).run().assertContent().as(ABean.class).asJson().is("{f:1}");
99 client().build().post("/echo",bean).run().assertContent().asBytes().asString().is("{f:1}");
100 }
101
102 @Test void a02_overrideParser() throws Exception {
103 var x = client().build();
104 var b = x.post("/echo",bean).run().getContent().parser(JsonParser.DEFAULT).as(ABean.class);
105 assertBean(b, "f", "1");
106 assertThrowsWithMessage(Exception.class, "ParseError at [row,col]:[1,1]", ()->x.post("/echo",bean).run().getContent().parser(XmlParser.DEFAULT).as(ABean.class));
107 assertThrowsWithMessage(Exception.class, "ParseError at [row,col]:[1,1]", ()->x.post("/echo",bean).run().getContent().parser(XmlParser.DEFAULT).assertValue().as(ABean.class));
108 }
109
110 @Test void a03_asInputStream() throws Exception {
111 var r1 = client().build().get("/bean").run();
112 var is = r1.getContent().asInputStream();
113 assertEquals("{f:1}", StringUtils.toUtf8(is));
114 assertThrowsWithMessage(Exception.class, "Response has already been consumed.", ()->r1.getContent().asInputStream());
115
116
117 var x = testClient().entity(inputStreamEntity("{f:2}"));
118 var r2 = x.get("/bean").run();
119 r2.getContent().asInputStream();
120 assertThrowsWithMessage(Exception.class, "Response has already been consumed", ()->r2.getContent().asInputStream());
121
122
123 x.entity(new StringEntity("{f:2}"));
124 var r3 = x.get("/bean").run();
125 r3.getContent().asInputStream();
126 is = r3.getContent().asInputStream();
127 assertEquals("{f:2}", StringUtils.toUtf8(is));
128 is = x.get("/bean").run().getContent().asInputStream();
129 ((EofSensorInputStream)is).abortConnection();
130
131 var rci = new BasicRestCallInterceptor() {
132 @Override
133 public void onClose(RestRequest req, RestResponse res) throws Exception {
134 throw new NullPointerException("foo");
135 }
136 };
137
138 var x2 = client().interceptors(rci).build(TestClient.class).entity(new StringEntity("{f:2}"));
139 assertThrowsWithMessage(NullPointerException.class, "foo", ()->x2.get("/bean").run().getContent().cache().asInputStream());
140 assertThrowsWithMessage(NullPointerException.class, "foo", ()->x2.get("/bean").run().getContent().asInputStream().close());
141 assertThrowsWithMessage(NullPointerException.class, "foo", ()->((EofSensorInputStream)x2.get("/bean").run().getContent().asInputStream()).abortConnection());
142 }
143
144 @Test void a04_asReader() throws Exception {
145 var x = testClient();
146 x.entity(inputStreamEntity("{f:1}"));
147 var r = x.get("/bean").run().getContent().asReader();
148 assertString("{f:1}", r);
149
150 x.entity(inputStreamEntity("{f:1}"));
151 r = x.get("/bean").run().getContent().asReader(UTF8);
152 assertString("{f:1}", r);
153
154 x.entity(inputStreamEntity("{f:1}"));
155 r = x.get("/bean").run().getContent().asReader(null);
156 assertString("{f:1}", r);
157 }
158
159 @Test void a05_asBytes() throws Exception {
160 var x = client().build().get("/bean").run().getContent().asBytes();
161 assertEquals("{f:1}", StringUtils.toUtf8(x));
162
163 x = client().build().get("/bean").run().assertContent().asBytes().asString().is("{f:1}").getContent().asBytes();
164 assertEquals("{f:1}", StringUtils.toUtf8(x));
165
166 assertThrowsWithMessage(Exception.class, "foo", ()->testClient().entity(new InputStreamEntity(badStream())).get().run().getContent().asBytes());
167 }
168
169 @Test void a06_pipeTo() throws Exception {
170 var baos = new ByteArrayOutputStream();
171 client().build().get("/bean").run().getContent().pipeTo(baos);
172 assertEquals("{f:1}", StringUtils.toUtf8(baos.toByteArray()));
173
174 var sw = new StringWriter();
175 client().build().get("/bean").run().getContent().pipeTo(sw);
176 assertEquals("{f:1}", sw.toString());
177
178 sw = new StringWriter();
179 client().build().get("/bean").run().getContent().pipeTo(sw,UTF8);
180 assertEquals("{f:1}", sw.toString());
181 }
182
183 public static class A7a {
184 String x;
185 public static A7a fromReader(Reader r) throws IOException {
186 var x = new A7a();
187 x.x = read(r);
188 return x;
189 }
190 }
191
192 public static class A7b {
193 String x;
194 public static A7b fromInputStream(InputStream is) throws IOException {
195 var x = new A7b();
196 x.x = read(is);
197 return x;
198 }
199 }
200
201 public static class A7c {
202 public A7c() {
203 throw new RuntimeException("foo");
204 }
205 }
206
207 @Test void a07_asType() throws Exception {
208 var x1 = testClient().entity(stringEntity("[1,2]")).get().run().getContent().as(List.class,Integer.class);
209 assertList(x1, "1", "2");
210
211 var x3 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().as(ABean.class);
212 assertBean(x3, "f", "1");
213
214 testClient().entity(stringEntity("{f:1}")).get().run().getContent().as(ResponseContent.class);
215
216 var x6 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().as(HttpEntity.class);
217 assertTrue(x6 instanceof ResponseContent);
218
219 plainTestClient().entity(stringEntity("foo")).get().run().assertContent().as(A7a.class).is(x->x.x.equals("foo"));
220 plainTestClient().entity(stringEntity("foo")).get().run().assertContent().as(A7b.class).is(x->x.x.equals("foo"));
221 assertThrowsWithMessage(Exception.class, "Unsupported media-type", ()->plainTestClient().entity(stringEntity("foo")).headers(header("Content-Type","foo")).get().run().getContent().as(A7c.class));
222 assertThrowsWithMessage(Exception.class, "foo", ()->testClient().entity(stringEntity("")).get().run().getContent().as(A7c.class));
223
224 var x8 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().asFuture(ABean.class);
225 assertBean(x8.get(), "f", "1");
226
227 var x10 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().asFuture(cm(ABean.class));
228 assertBean(x10.get(), "f", "1");
229
230 var x12 = testClient().entity(stringEntity("[1,2]")).get().run().getContent().asFuture(List.class,Integer.class);
231 assertList(x12.get(), "1", "2");
232
233 var x14 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().asString();
234 assertEquals("{f:1}", x14);
235
236 assertThrowsWithMessage(Exception.class, "foo", ()->testClient().entity(new InputStreamEntity(badStream())).get().run().getContent().asString());
237
238 var x16 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().asStringFuture();
239 assertEquals("{f:1}", x16.get());
240
241 var x18 = testClient().entity(stringEntity("12345")).get().run().getContent().asAbbreviatedString(4);
242 assertEquals("1...", x18);
243
244 var x20 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().asObjectRest(ABean.class);
245 assertString("1", x20.get("f"));
246
247 var x22 = testClient().entity(stringEntity("{f:1}")).get().run().getContent().asObjectRest();
248 assertString("1", x22.get("f"));
249
250 var x24 = testClient().entity(stringEntity("foo=123")).get().run().getContent().asMatcher(Pattern.compile("foo=(.*)"));
251 assertTrue(x24.matches());
252 assertEquals("123", x24.group(1));
253
254 var x26 = testClient().entity(stringEntity("foo=123")).get().run().getContent().asMatcher("foo=(.*)");
255 assertTrue(x26.matches());
256 assertEquals("123", x26.group(1));
257 }
258
259
260
261
262
263 @SuppressWarnings("deprecation")
264 @Test void b01_httpEntityMethods() throws Exception {
265 var x1 = testClient().entity(stringEntity("foo")).get().run().getContent();
266 assertTrue(x1.isRepeatable());
267
268 var x2 = testClient().entity(inputStreamEntity("foo")).get().run().getContent();
269 assertFalse(x2.isRepeatable());
270 assertEquals(-1L, x2.getContentLength());
271 x2.cache().asString();
272 assertTrue(x2.isRepeatable());
273 assertEquals(3L, x2.getContentLength());
274
275 assertFalse(x2.isChunked());
276
277 testClient().entity(inputStreamEntity("foo")).get().run().getContent().getContentEncoding().assertValue().isNull();
278
279 var x3 = inputStreamEntity("foo");
280 x3.setContentType("text/foo");
281 x3.setContentEncoding("identity");
282 testClient().entity(x3).get().run().getContent().response()
283 .getContent().getContentType().assertValue().is("text/foo").response()
284 .getContent().getContentEncoding().assertValue().is("identity");
285
286 var x4 = testClient().entity(inputStreamEntity("foo")).get().run().getContent().asInputStream();
287 assertBytes(x4).asString().is("foo");
288
289 var x5 = new ByteArrayOutputStream();
290 testClient().entity(inputStreamEntity("foo")).get().run().getContent().writeTo(x5);
291 assertBytes(x5.toByteArray()).asString().is("foo");
292
293 assertTrue(testClient().entity(inputStreamEntity("foo")).get().run().getContent().isStreaming());
294 assertFalse(testClient().entity(inputStreamEntity("foo")).get().run().getContent().cache().isStreaming());
295 assertFalse(testClient().entity(stringEntity("foo")).get().run().getContent().isStreaming());
296
297 testClient().entity(inputStreamEntity("foo")).get().run().getContent().consumeContent();
298 }
299
300 @SuppressWarnings("deprecation")
301 @Test void b02_head() throws Exception {
302 assertFalse(client().build().head("").run().getContent().isRepeatable());
303 assertFalse(client().build().head("").run().getContent().isChunked());
304 assertEquals(-1L, client().build().head("").run().getContent().getContentLength());
305 client().build().head("").run().getContent().getContentType().assertValue().isNull();
306 client().build().head("").run().getContent().getContentEncoding().assertValue().isNull();
307 client().build().head("").run().getContent().writeTo(new ByteArrayOutputStream());
308 assertFalse(client().build().head("").run().getContent().isStreaming());
309 client().build().head("").run().getContent().consumeContent();
310 }
311
312
313
314
315
316 private static RestClient.Builder client() {
317 return MockRestClient.create(A.class).json5();
318 }
319
320 private static TestClient plainTestClient() {
321 return MockRestClient.create(A.class).noTrace().build(TestClient.class);
322 }
323
324 private static TestClient testClient() {
325 return MockRestClient.create(A.class).json5().noTrace().build(TestClient.class);
326 }
327
328 private static StringEntity stringEntity(String in) {
329 return new StringEntity(in, (ContentType)null);
330 }
331
332 private static Header header(String name, Object val) {
333 return basicHeader(name, val);
334 }
335
336 private static InputStreamEntity inputStreamEntity(String in) {
337 return new InputStreamEntity(inputStream(in));
338 }
339
340 private static <T> ClassMeta<T> cm(Class<T> t) {
341 return BeanContext.DEFAULT.getClassMeta(t);
342 }
343
344 private static InputStream badStream() {
345 return new InputStream() {
346 @Override
347 public int read() throws IOException {
348 throw new IOException("foo");
349 }
350 };
351 }
352 }