1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.rest.annotation;
18
19 import static org.apache.juneau.TestUtils.*;
20 import static org.apache.juneau.common.utils.IOUtils.*;
21 import static org.apache.juneau.http.header.ContentType.*;
22 import static org.junit.jupiter.api.Assertions.*;
23
24 import java.io.*;
25 import java.util.*;
26
27 import org.apache.juneau.*;
28 import org.apache.juneau.annotation.*;
29 import org.apache.juneau.http.annotation.*;
30 import org.apache.juneau.json.*;
31 import org.apache.juneau.marshaller.*;
32 import org.apache.juneau.rest.mock.*;
33 import org.apache.juneau.testutils.pojos.*;
34 import org.apache.juneau.uon.*;
35 import org.apache.juneau.urlencoding.*;
36 import org.apache.juneau.urlencoding.annotation.*;
37 import org.apache.juneau.urlencoding.annotation.UrlEncoding;
38 import org.junit.jupiter.api.*;
39
40 class Content_Test extends TestBase {
41
42
43
44
45
46 @Rest(serializers=Json5Serializer.class, parsers=JsonParser.class, defaultAccept="text/json")
47 public static class A {
48 @RestPut(path="/String")
49 public String a(@Content String b) {
50 return b;
51 }
52 @RestPut(path="/Integer")
53 public Integer b(@Content Integer b) {
54 return b;
55 }
56 @RestPut(path="/int")
57 public Integer c(@Content int b) {
58 return b;
59 }
60 @RestPut(path="/Boolean")
61 public Boolean d(@Content Boolean b) {
62 return b;
63 }
64 @RestPut(path="/boolean")
65 public Boolean e(@Content boolean b) {
66 return b;
67 }
68 @RestPut(path="/float")
69 public float f(@Content float f) {
70 return f;
71 }
72 @RestPut(path="/Float")
73 public Float g(@Content Float f) {
74 return f;
75 }
76 @RestPut(path="/Map")
77 public TreeMap<String,Integer> h(@Content TreeMap<String,Integer> m) {
78 return m;
79 }
80 @RestPut(path="/enum")
81 public TestEnum i(@Content TestEnum e) {
82 return e;
83 }
84 public static class A11 {
85 public String f1;
86 }
87 @RestPut(path="/Bean")
88 public A11 j(@Content A11 b) {
89 return b;
90 }
91 @RestPut(path="/InputStream")
92 public String k(@Content InputStream b) throws Exception {
93 return read(b);
94 }
95 @RestPut(path="/Reader")
96 public String l(@Content Reader b) throws Exception {
97 return read(b);
98 }
99 @RestPut(path="/InputStreamTransform")
100 public A14 m(@Content A14 b) {
101 return b;
102 }
103 public static class A14 {
104 String s;
105 public A14(InputStream in) throws Exception { this.s = read(in); }
106 @Override public String toString() { return s; }
107 }
108 @RestPut(path="/ReaderTransform")
109 public A15 n(@Content A15 b) {
110 return b;
111 }
112 public static class A15 {
113 private String s;
114 public A15(Reader in) throws Exception { this.s = read(in); }
115 @Override public String toString() { return s; }
116 }
117 @RestPut(path="/StringTransform")
118 public A16 o(@Content A16 b) { return b; }
119 public static class A16 {
120 private String s;
121 public A16(String s) { this.s = s; }
122 @Override public String toString() { return s; }
123 }
124 }
125
126 @Test void a01_onParameters() throws Exception {
127 var a = MockRestClient.buildLax(A.class);
128
129 a.put("/String", "foo")
130 .json()
131 .run()
132 .assertContent("'foo'");
133
134 a.put("/String", "'foo'")
135 .run()
136 .assertContent("'\\'foo\\''");
137
138 a.put("/String", "'foo'").contentType("")
139 .run()
140 .assertContent("'\\'foo\\''");
141 a.put("/String", "'foo'").contentType("text/plain")
142 .run()
143 .assertContent("'\\'foo\\''");
144 a.put("/String?content=foo", null)
145 .run()
146 .assertContent("'foo'");
147 a.put("/String?content=null", null)
148 .run()
149 .assertContent("null");
150 a.put("/String?content=", null)
151 .run()
152 .assertContent("''");
153
154 a.put("/Integer", "123").json()
155 .run()
156 .assertContent("123");
157
158 a.put("/Integer", "123")
159 .run()
160 .assertContent("123");
161 a.put("/Integer?content=123", null)
162 .run()
163 .assertContent("123");
164 a.put("/Integer?content=-123", null)
165 .run()
166 .assertContent("-123");
167 a.put("/Integer?content=null", null)
168 .run()
169 .assertContent("null");
170 a.put("/Integer?content=", null)
171 .run()
172 .assertContent("null");
173 a.put("/Integer?content=bad&noTrace=true", null)
174 .run()
175 .assertStatus(400);
176
177 a.put("/int", "123").json()
178 .run()
179 .assertContent("123");
180 a.put("/int", "123")
181 .run()
182 .assertContent("123");
183 a.put("/int?content=123", null)
184 .run()
185 .assertContent("123");
186 a.put("/int?content=-123", null)
187 .run()
188 .assertContent("-123");
189 a.put("/int?content=null", null)
190 .run()
191 .assertContent("0");
192 a.put("/int?content=", null)
193 .run()
194 .assertContent("0");
195 a.put("/int?content=bad&noTrace=true", null)
196 .run()
197 .assertStatus(400);
198
199 a.put("/Boolean", "true").json()
200 .run()
201 .assertContent("true");
202
203 a.put("/Boolean", "true")
204 .run()
205 .assertContent("true");
206 a.put("/Boolean?content=true", null)
207 .run()
208 .assertContent("true");
209 a.put("/Boolean?content=false", null)
210 .run()
211 .assertContent("false");
212 a.put("/Boolean?content=null", null)
213 .run()
214 .assertContent("null");
215 a.put("/Boolean?content=", null)
216 .run()
217 .assertContent("null");
218 a.put("/Boolean?content=bad&noTrace=true", null)
219 .run()
220 .assertStatus(400);
221
222 a.put("/boolean", "true").json()
223 .run()
224 .assertContent("true");
225 a.put("/boolean", "true")
226 .run()
227 .assertContent("true");
228 a.put("/boolean?content=true", null)
229 .run()
230 .assertContent("true");
231 a.put("/boolean?content=false", null)
232 .run()
233 .assertContent("false");
234 a.put("/boolean?content=null", null)
235 .run()
236 .assertContent("false");
237 a.put("/boolean?content=", null)
238 .run()
239 .assertContent("false");
240 a.put("/boolean?content=bad&noTrace=true", null)
241 .run()
242 .assertStatus(400);
243
244 a.put("/float", "1.23").json()
245 .run()
246 .assertContent("1.23");
247 a.put("/float", "1.23")
248 .run()
249 .assertContent("1.23");
250 a.put("/float?content=1.23", null)
251 .run()
252 .assertContent("1.23");
253 a.put("/float?content=-1.23", null)
254 .run()
255 .assertContent("-1.23");
256 a.put("/float?content=null", null)
257 .run()
258 .assertContent("0.0");
259 a.put("/float?content=", null)
260 .run()
261 .assertContent("0.0");
262 a.put("/float?content=bad&noTrace=true", null)
263 .run()
264 .assertStatus(400);
265
266 a.put("/Float", "1.23").json()
267 .run()
268 .assertContent("1.23");
269
270 a.put("/Float", "1.23")
271 .run()
272 .assertContent("1.23");
273 a.put("/Float?content=1.23", null)
274 .run()
275 .assertContent("1.23");
276 a.put("/Float?content=-1.23", null)
277 .run()
278 .assertContent("-1.23");
279 a.put("/Float?content=null", null)
280 .run()
281 .assertContent("null");
282 a.put("/Float?content=", null)
283 .run()
284 .assertContent("null");
285 a.put("/Float?content=bad&noTrace=true", null)
286 .run()
287 .assertStatus(400);
288
289 a.put("/Map", "{foo:123}", APPLICATION_JSON)
290 .run()
291 .assertContent("{foo:123}");
292 a.put("/Map", "(foo=123)", TEXT_OPENAPI)
293 .run()
294 .assertStatus(415);
295 a.put("/Map?content=(foo=123)", null)
296 .run()
297 .assertContent("{foo:123}");
298 a.put("/Map?content=()", null)
299 .run()
300 .assertContent("{}");
301 a.put("/Map?content=null", null)
302 .run()
303 .assertContent("null");
304 a.put("/Map?content=", null)
305 .run()
306 .assertContent("null");
307 a.put("/Map?content=bad&noTrace=true", null)
308 .run()
309 .assertStatus(400);
310
311 a.put("/enum", "'ONE'", APPLICATION_JSON)
312 .run()
313 .assertContent("'ONE'");
314 a.put("/enum", "ONE")
315 .run()
316 .assertContent("'ONE'");
317 a.put("/enum?content=ONE", null)
318 .run()
319 .assertContent("'ONE'");
320 a.put("/enum?content=TWO", null)
321 .run()
322 .assertContent("'TWO'");
323 a.put("/enum?content=null", null)
324 .run()
325 .assertContent("null");
326 a.put("/enum?content=", null)
327 .run()
328 .assertContent("null");
329 a.put("/enum?content=bad&noTrace=true", null)
330 .run()
331 .assertStatus(400);
332
333 a.put("/Bean", "{f1:'a'}", APPLICATION_JSON)
334 .run()
335 .assertContent("{f1:'a'}");
336 a.put("/Bean", "(f1=a)", TEXT_OPENAPI)
337 .run()
338 .assertStatus(415);
339 a.put("/Bean?content=(f1=a)", null)
340 .run()
341 .assertContent("{f1:'a'}");
342 a.put("/Bean?content=()", null)
343 .run()
344 .assertContent("{}");
345 a.put("/Bean?content=null", null)
346 .run()
347 .assertContent("null");
348 a.put("/Bean?content=", null)
349 .run()
350 .assertContent("null");
351 a.put("/Bean?content=bad&noTrace=true", null)
352 .run()
353 .assertStatus(400);
354
355
356 a.put("/InputStream", "'a'", APPLICATION_JSON)
357 .run()
358 .assertContent("'\\'a\\''");
359 a.put("/InputStream", "'a'")
360 .run()
361 .assertContent("'\\'a\\''");
362 a.put("/InputStream?content=a", null)
363 .run()
364 .assertContent("'a'");
365 a.put("/InputStream?content=null", null)
366 .run()
367 .assertContent("'null'");
368 a.put("/InputStream?content=", null)
369 .run()
370 .assertContent("''");
371
372
373 a.put("/Reader", "'a'", APPLICATION_JSON)
374 .run()
375 .assertContent("'\\'a\\''");
376 a.put("/Reader", "'a'")
377 .run()
378 .assertContent("'\\'a\\''");
379 a.put("/Reader?content=a", null)
380 .run()
381 .assertContent("'a'");
382 a.put("/Reader?content=null", null)
383 .run()
384 .assertContent("'null'");
385 a.put("/Reader?content=", null)
386 .run()
387 .assertContent("''");
388
389
390
391
392 a.put("/InputStreamTransform?noTrace=true", "'a'", APPLICATION_JSON)
393 .run()
394 .assertContent().isContains("Bad Request");
395 a.put("/InputStreamTransform", "'a'")
396 .run()
397 .assertContent("'\\'a\\''");
398
399
400 a.put("/ReaderTransform?noTrace=true", "'a'", APPLICATION_JSON)
401 .run()
402 .assertContent().isContains("Bad Request");
403 a.put("/ReaderTransform", "'a'")
404 .run()
405 .assertContent("'\\'a\\''");
406
407
408 a.put("/StringTransform", "'a'", APPLICATION_JSON)
409 .run()
410 .assertContent("'a'");
411
412 a.put("/StringTransform", "'a'")
413 .run()
414 .assertContent("'\\'a\\''");
415 }
416
417
418
419
420
421 @Rest(serializers=Json5Serializer.class, parsers=JsonParser.class, defaultAccept="application/json")
422 public static class B {
423 @RestPut(path="/StringTransform")
424 public B1 a(B1 b) {
425 return b;
426 }
427 @Content
428 public static class B1 {
429 private String val;
430 public B1(String val) { this.val = val; }
431 @Override public String toString() { return val; }
432 }
433 @RestPut(path="/Bean")
434 public B2 b(B2 b) {
435 return b;
436 }
437 @Content
438 public static class B2 {
439 public String f1;
440 }
441 @RestPut(path="/BeanList")
442 public B3 c(B3 b) {
443 return b;
444 }
445 @SuppressWarnings("serial")
446 @Content
447 public static class B3 extends LinkedList<B2> {}
448 @RestPut(path="/InputStreamTransform")
449 public B4 d(B4 b) {
450 return b;
451 }
452 @Content
453 public static class B4 {
454 String s;
455 public B4(InputStream in) throws Exception { this.s = read(in); }
456 @Override public String toString() { return s; }
457 }
458 @RestPut(path="/ReaderTransform")
459 public B5 e(B5 b) {
460 return b;
461 }
462 @Content
463 public static class B5 {
464 private String s;
465 public B5(Reader in) throws Exception { this.s = read(in); }
466 @Override public String toString() { return s; }
467 }
468 }
469
470 @Test void b01_onPojos() throws Exception {
471 var b = MockRestClient.buildLax(B.class);
472 b.put("/StringTransform", "'foo'", APPLICATION_JSON)
473 .run()
474 .assertContent("'foo'");
475
476 b.put("/StringTransform", "'foo'")
477 .run()
478 .assertContent("'\\'foo\\''");
479 b.put("/Bean", "{f1:'a'}", APPLICATION_JSON)
480 .run()
481 .assertContent("{f1:'a'}");
482 b.put("/Bean", "(f1=a)", TEXT_OPENAPI)
483 .run()
484 .assertStatus(415);
485 b.put("/BeanList", "[{f1:'a'}]", APPLICATION_JSON)
486 .run()
487 .assertContent("[{f1:'a'}]");
488 b.put("/BeanList", "(f1=a)", TEXT_OPENAPI)
489 .run()
490 .assertStatus(415);
491 b.put("/InputStreamTransform", "a")
492 .run()
493 .assertContent("'a'");
494
495 b.put("/InputStreamTransform?noTrace=true", "a", APPLICATION_JSON)
496 .run()
497 .assertContent().isContains("Bad Request");
498 b.put("/ReaderTransform", "a")
499 .run()
500 .assertContent("'a'");
501
502 b.put("/ReaderTransform?noTrace=true", "a", APPLICATION_JSON)
503 .run()
504 .assertContent().isContains("Bad Request");
505 }
506
507
508
509
510
511 @Rest
512 public static class D {
513 @RestPut(path="/String")
514 public Reader a(@Content Reader b) {
515 return b;
516 }
517 @RestPut(path="/InputStream")
518 public InputStream b(@Content InputStream b) {
519 return b;
520 }
521 @RestPut(path="/Reader")
522 public Reader c(@Content Reader b) {
523 return b;
524 }
525 @RestPut(path="/StringTransform")
526 public Reader d(@Content D1 b) {
527 return reader(b.toString());
528 }
529 public static class D1 {
530 private String s;
531 public D1(String in) { this.s = in; }
532 @Override public String toString() { return s; }
533 }
534 @RestPut(path="/InputStreamTransform")
535 public Reader e(@Content D2 b) {
536 return reader(b.toString());
537 }
538 public static class D2 {
539 String s;
540 public D2(InputStream in) throws Exception { this.s = read(in); }
541 @Override public String toString() { return s; }
542 }
543 @RestPut(path="/ReaderTransform")
544 public Reader f(@Content D3 b) {
545 return reader(b.toString());
546 }
547 public static class D3 {
548 private String s;
549 public D3(Reader in) throws Exception{ this.s = read(in); }
550 @Override public String toString() { return s; }
551 }
552 @RestPut(path="/StringTransformBodyOnPojo")
553 public Reader g(D4 b) {
554 return reader(b.toString());
555 }
556 @Content
557 public static class D4 {
558 private String s;
559 public D4(String in) { this.s = in; }
560 @Override public String toString() { return s; }
561 }
562 @RestPut(path="/InputStreamTransformBodyOnPojo")
563 public Reader h(D5 b) {
564 return reader(b.toString());
565 }
566 @Content
567 public static class D5 {
568 String s;
569 public D5(InputStream in) throws Exception { this.s = read(in); }
570 @Override public String toString() { return s; }
571 }
572
573 @RestPut(path="/ReaderTransformBodyOnPojo")
574 public Reader i(D6 b) {
575 return reader(b.toString());
576 }
577 @Content
578 public static class D6 {
579 private String s;
580 public D6(Reader in) throws Exception{ this.s = read(in); }
581 @Override public String toString() { return s; }
582 }
583 }
584
585 @Test void d01_noMediaTypesOnStreams() throws Exception {
586 var d = MockRestClient.buildLax(D.class);
587 d.put("/String", "a")
588 .run()
589 .assertContent("a");
590 d.put("/String", "a", APPLICATION_JSON)
591 .run()
592 .assertContent("a");
593 d.put("/InputStream", "a")
594 .run()
595 .assertContent("a");
596 d.put("/InputStream", "a", APPLICATION_JSON)
597 .run()
598 .assertContent("a");
599 d.put("/Reader", "a")
600 .run()
601 .assertContent("a");
602 d.put("/Reader", "a", APPLICATION_JSON)
603 .run()
604 .assertContent("a");
605 d.put("/StringTransform", "a")
606 .run()
607 .assertContent("a");
608 d.put("/StringTransform?noTrace=true", "a", APPLICATION_JSON)
609 .run()
610 .assertStatus(415);
611 d.put("/InputStreamTransform", "a")
612 .run()
613 .assertContent("a");
614 d.put("/InputStreamTransform", "a", APPLICATION_JSON)
615 .run()
616 .assertContent("a");
617 d.put("/ReaderTransform", "a")
618 .run()
619 .assertContent("a");
620 d.put("/ReaderTransform", "a", APPLICATION_JSON)
621 .run()
622 .assertContent("a");
623 d.put("/StringTransformBodyOnPojo", "a")
624 .run()
625 .assertContent("a");
626 d.put("/StringTransformBodyOnPojo?noTrace=true", "a", APPLICATION_JSON)
627 .run()
628 .assertStatus(415);
629 d.put("/InputStreamTransformBodyOnPojo", "a")
630 .run()
631 .assertContent("a");
632 d.put("/InputStreamTransformBodyOnPojo", "a", APPLICATION_JSON)
633 .run()
634 .assertContent("a");
635 d.put("/ReaderTransformBodyOnPojo", "a")
636 .run()
637 .assertContent("a");
638 d.put("/ReaderTransformBodyOnPojo", "a", APPLICATION_JSON)
639 .run()
640 .assertContent("a");
641 }
642
643
644
645
646
647 @Rest(serializers=Json5Serializer.class, parsers=JsonParser.class, defaultAccept="application/json")
648 public static class E {
649 @RestPut(path="/B")
650 public XBeans.XB a(@Content XBeans.XB b) {
651 return b;
652 }
653 @RestPut(path="/C")
654 public XBeans.XC b(@Content XBeans.XC c) {
655 return c;
656 }
657 }
658
659 @Test void e01_complexPojos() throws Exception {
660 var e = MockRestClient.build(E.class);
661 var expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
662
663 e.put("/B", Json5Serializer.DEFAULT.toString(XBeans.XB.INSTANCE), APPLICATION_JSON)
664 .run()
665 .assertContent(expected);
666
667 expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
668 e.put("/B?content=" + UonSerializer.DEFAULT.serialize(XBeans.XB.INSTANCE), "a")
669 .run()
670 .assertContent(expected);
671
672 expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
673 e.put("/C", Json5Serializer.DEFAULT.toString(XBeans.XB.INSTANCE), APPLICATION_JSON)
674 .run()
675 .assertContent(expected);
676
677 expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
678 e.put("/C?content=" + UonSerializer.DEFAULT.serialize(XBeans.XB.INSTANCE), "a")
679 .run()
680 .assertContent(expected);
681 }
682
683 @Rest(serializers=Json5Serializer.class, parsers=JsonParser.class, defaultAccept="application/json")
684 @Bean(on="A,B,C",sort=true)
685 @UrlEncoding(on="C",expandedParams=true)
686 public static class E2 {
687 @RestPut(path="/B")
688 public XBeans.XE a(@Content XBeans.XE b) {
689 return b;
690 }
691 @RestPut(path="/C")
692 public XBeans.XF b(@Content XBeans.XF c) {
693 return c;
694 }
695 }
696
697 @Test void e02_complexPojos() throws Exception {
698 var e2 = MockRestClient.build(E2.class);
699 var expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
700
701 e2.put("/B", Json5Serializer.DEFAULT.copy().applyAnnotations(XBeans.Annotations.class).build().toString(XBeans.XE.INSTANCE), APPLICATION_JSON)
702 .run()
703 .assertContent(expected);
704
705 expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
706 e2.put("/B?content=" + UonSerializer.DEFAULT.copy().applyAnnotations(XBeans.Annotations.class).build().serialize(XBeans.XE.INSTANCE), "a")
707 .run()
708 .assertContent(expected);
709
710 expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
711 e2.put("/C", Json5Serializer.DEFAULT.copy().applyAnnotations(XBeans.Annotations.class).build().toString(XBeans.XE.INSTANCE), APPLICATION_JSON)
712 .run()
713 .assertContent(expected);
714
715 expected = "{f01:['a','b'],f02:['c','d'],f03:[1,2],f04:[3,4],f05:[['e','f'],['g','h']],f06:[['i','j'],['k','l']],f07:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f08:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f09:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f10:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f11:['a','b'],f12:['c','d'],f13:[1,2],f14:[3,4],f15:[['e','f'],['g','h']],f16:[['i','j'],['k','l']],f17:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f18:[{a:'a',b:1,c:true},{a:'a',b:1,c:true}],f19:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]],f20:[[{a:'a',b:1,c:true}],[{a:'a',b:1,c:true}]]}";
716 e2.put("/C?content=" + UonSerializer.DEFAULT.copy().applyAnnotations(XBeans.Annotations.class).build().serialize(XBeans.XE.INSTANCE), "a")
717 .run()
718 .assertContent(expected);
719 }
720
721
722
723
724
725 @Rest(serializers=JsonSerializer.class,parsers=JsonParser.class)
726 public static class F {
727 @RestPost(path="/*")
728 public Reader a(
729 @Content F1 bean,
730 @HasQuery("p1") boolean hqp1, @HasQuery("p2") boolean hqp2,
731 @Query("p1") String qp1, @Query("p2") int qp2) {
732 return reader("bean=["+Json5Serializer.DEFAULT.toString(bean)+"],qp1=["+qp1+"],qp2=["+qp2+"],hqp1=["+hqp1+"],hqp2=["+hqp2+"]");
733 }
734 public static class F1 {
735 public String p1;
736 public int p2;
737 }
738 }
739
740 @Test void f01_formPostAsContent() throws Exception {
741 var f = MockRestClient.build(F.class);
742 f.post("/", "{p1:'p1',p2:2}", APPLICATION_JSON)
743 .run()
744 .assertContent("bean=[{p1:'p1',p2:2}],qp1=[null],qp2=[0],hqp1=[false],hqp2=[false]");
745 f.post("/", "{}", APPLICATION_JSON)
746 .run()
747 .assertContent("bean=[{p2:0}],qp1=[null],qp2=[0],hqp1=[false],hqp2=[false]");
748 f.post("?p1=p3&p2=4", "{p1:'p1',p2:2}", APPLICATION_JSON)
749 .run()
750 .assertContent("bean=[{p1:'p1',p2:2}],qp1=[p3],qp2=[4],hqp1=[true],hqp2=[true]");
751 f.post("?p1=p3&p2=4", "{}", APPLICATION_JSON)
752 .run()
753 .assertContent("bean=[{p2:0}],qp1=[p3],qp2=[4],hqp1=[true],hqp2=[true]");
754 }
755
756
757
758
759
760
761
762 @Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
763 public static class G {
764 @RestPost(path="/")
765 public XBeans.XC a(@Content XBeans.XC content) {
766 return content;
767 }
768 }
769
770 @Test void g01_multiPartParameterKeysOnCollections() throws Exception {
771 var g = MockRestClient.build(G.class);
772 var in = ""
773 + "f01=a&f01=b"
774 + "&f02=c&f02=d"
775 + "&f03=1&f03=2"
776 + "&f04=3&f04=4"
777 + "&f05=@(e,f)&f05=@(g,h)"
778 + "&f06=@(i,j)&f06=@(k,l)"
779 + "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
780 + "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
781 + "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
782 + "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
783 + "&f11=a&f11=b"
784 + "&f12=c&f12=d"
785 + "&f13=1&f13=2"
786 + "&f14=3&f14=4"
787 + "&f15=@(e,f)&f15=@(g,h)"
788 + "&f16=@(i,j)&f16=@(k,l)"
789 + "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
790 + "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
791 + "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
792 + "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
793 g.post("/", in, APPLICATION_FORM_URLENCODED)
794 .run()
795 .assertContent(in);
796 }
797
798
799
800
801
802
803
804 @Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
805 public static class H {
806 @RestPost(path="/")
807 @UrlEncodingConfig(expandedParams="true")
808 public XBeans.XB a(@Content XBeans.XB content) {
809 return content;
810 }
811 }
812
813 @Test void h01_multiPartParameterKeysOnCollections_usingExpandedParams() throws Exception {
814 var h = MockRestClient.build(H.class);
815 var in = ""
816 + "f01=a&f01=b"
817 + "&f02=c&f02=d"
818 + "&f03=1&f03=2"
819 + "&f04=3&f04=4"
820 + "&f05=@(e,f)&f05=@(g,h)"
821 + "&f06=@(i,j)&f06=@(k,l)"
822 + "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
823 + "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
824 + "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
825 + "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
826 + "&f11=a&f11=b"
827 + "&f12=c&f12=d"
828 + "&f13=1&f13=2"
829 + "&f14=3&f14=4"
830 + "&f15=@(e,f)&f15=@(g,h)"
831 + "&f16=@(i,j)&f16=@(k,l)"
832 + "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
833 + "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
834 + "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
835 + "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
836 h.post("/", in, APPLICATION_FORM_URLENCODED)
837 .run()
838 .assertContent(in);
839 }
840
841 @Rest(serializers=UrlEncodingSerializer.class,parsers=UrlEncodingParser.class)
842 @Bean(on="A,B,C",sort=true)
843 @UrlEncoding(on="C",expandedParams=true)
844 public static class H2 {
845 @RestPost(path="/")
846 @UrlEncodingConfig(expandedParams="true")
847 public XBeans.XE a(@Content XBeans.XE content) {
848 return content;
849 }
850 }
851
852 @Test void h02_multiPartParameterKeysOnCollections_usingExpandedParams() throws Exception {
853 var h2 = MockRestClient.build(H2.class);
854 var in = ""
855 + "f01=a&f01=b"
856 + "&f02=c&f02=d"
857 + "&f03=1&f03=2"
858 + "&f04=3&f04=4"
859 + "&f05=@(e,f)&f05=@(g,h)"
860 + "&f06=@(i,j)&f06=@(k,l)"
861 + "&f07=(a=a,b=1,c=true)&f07=(a=b,b=2,c=false)"
862 + "&f08=(a=a,b=1,c=true)&f08=(a=b,b=2,c=false)"
863 + "&f09=@((a=a,b=1,c=true))&f09=@((a=b,b=2,c=false))"
864 + "&f10=@((a=a,b=1,c=true))&f10=@((a=b,b=2,c=false))"
865 + "&f11=a&f11=b"
866 + "&f12=c&f12=d"
867 + "&f13=1&f13=2"
868 + "&f14=3&f14=4"
869 + "&f15=@(e,f)&f15=@(g,h)"
870 + "&f16=@(i,j)&f16=@(k,l)"
871 + "&f17=(a=a,b=1,c=true)&f17=(a=b,b=2,c=false)"
872 + "&f18=(a=a,b=1,c=true)&f18=(a=b,b=2,c=false)"
873 + "&f19=@((a=a,b=1,c=true))&f19=@((a=b,b=2,c=false))"
874 + "&f20=@((a=a,b=1,c=true))&f20=@((a=b,b=2,c=false))";
875 h2.post("/", in, APPLICATION_FORM_URLENCODED)
876 .run()
877 .assertContent(in);
878 }
879
880
881
882
883
884 @Rest(serializers=JsonSerializer.class,parsers=JsonParser.class)
885 public static class I {
886 @RestPost
887 public XBeans.XB a(@Content @Schema(r=true) XBeans.XB content) {
888 return content;
889 }
890 @RestPost
891 @Bean(on="A,B,C",sort=true)
892 @UrlEncoding(on="C",expandedParams=true)
893 public XBeans.XE b(@Content @Schema(r=true) XBeans.XE content) {
894 return content;
895 }
896 }
897
898 @Test void i01_required() throws Exception {
899 var i = MockRestClient.buildLax(I.class);
900
901 i.post("/a", "", APPLICATION_JSON)
902 .run()
903 .assertStatus(400)
904 .assertContent().isContains("Required value not provided.");
905 i.post("/a", "{}", APPLICATION_JSON)
906 .run()
907 .assertStatus(200);
908
909 i.post("/b", "", APPLICATION_JSON)
910 .run()
911 .assertStatus(400)
912 .assertContent().isContains("Required value not provided.");
913 i.post("/b", "{}", APPLICATION_JSON)
914 .run()
915 .assertStatus(200);
916 }
917
918
919
920
921
922 @Rest(serializers=Json5Serializer.class,parsers=JsonParser.class)
923 public static class J {
924 @RestPost
925 public Object a(@Content Optional<Integer> body) {
926 assertNotNull(body);
927 return body;
928 }
929 @RestPost
930 public Object b(@Content Optional<ABean> body) {
931 assertNotNull(body);
932 return body;
933 }
934 @RestPost
935 public Object c(@Content Optional<List<ABean>> body) {
936 assertNotNull(body);
937 return body;
938 }
939 @RestPost
940 public Object d(@Content List<Optional<ABean>> body) {
941 return body;
942 }
943 }
944
945 @Test void j01_optionalParams() throws Exception {
946 var j = MockRestClient.buildJson(J.class);
947 j.post("/a", 123)
948 .run()
949 .assertStatus(200)
950 .assertContent("123");
951 j.post("/a", null)
952 .run()
953 .assertStatus(200)
954 .assertContent("null");
955
956 j.post("/b", ABean.get())
957 .run()
958 .assertStatus(200)
959 .assertContent("{a:1,b:'foo'}");
960 j.post("/b", null)
961 .run()
962 .assertStatus(200)
963 .assertContent("null");
964
965 var body1 = Json5.of(list(ABean.get()));
966 j.post("/c", body1, APPLICATION_JSON)
967 .run()
968 .assertStatus(200)
969 .assertContent("[{a:1,b:'foo'}]");
970 j.post("/c", null)
971 .run()
972 .assertStatus(200)
973 .assertContent("null");
974
975 var body2 = Json5.of(list(opt(ABean.get())));
976 j.post("/d", body2, APPLICATION_JSON)
977 .run()
978 .assertStatus(200)
979 .assertContent("[{a:1,b:'foo'}]");
980 j.post("/d", null)
981 .run()
982 .assertStatus(200)
983 .assertContent("null");
984 }
985 }