1 /*
2 * Copyright (c) 2011-2022, jcabi.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met: 1) Redistributions of source code must retain the above
8 * copyright notice, this list of conditions and the following
9 * disclaimer. 2) Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution. 3) Neither the name of the jcabi.com nor
13 * the names of its contributors may be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package com.jcabi.http;
31
32 import com.jcabi.aspects.Immutable;
33 import jakarta.json.JsonStructure;
34 import java.nio.charset.StandardCharsets;
35 import java.util.Map;
36
37 /**
38 * Request body.
39 *
40 * <p>Instance of this interface is returned by {@link Request#body()},
41 * and can be modified using one of the methods below. When modification
42 * is done, method {@code back()} returns a modified instance of
43 * {@link Request}, for example:
44 *
45 * <pre> new JdkRequest("http://my.example.com")
46 * .header("Content-Type", "application/x-www-form-urlencoded")
47 * .body()
48 * .formParam("name", "Jeff Lebowski")
49 * .formParam("age", "37")
50 * .formParam("employment", "none")
51 * .back() // returns a modified instance of Request
52 * .fetch()</pre>
53 *
54 * <p>Instances of this interface are immutable and thread-safe.
55 *
56 * @since 0.8
57 */
58 @Immutable
59 public interface RequestBody {
60
61 /**
62 * Get back to the request it's related to.
63 * @return The request we're in
64 */
65 Request back();
66
67 /**
68 * Get text content.
69 * @return Content in UTF-8
70 */
71 String get();
72
73 /**
74 * Set text content.
75 * @param body Body content
76 * @return New alternated body
77 */
78 RequestBody set(String body);
79
80 /**
81 * Set JSON content.
82 * @param json JSON object
83 * @return New alternated body
84 * @since 0.11
85 */
86 RequestBody set(JsonStructure json);
87
88 /**
89 * Set byte array content.
90 * @param body Body content
91 * @return New alternated body
92 */
93 RequestBody set(byte[] body);
94
95 /**
96 * Add form param.
97 * @param name Query param name
98 * @param value Value of the query param to set
99 * @return New alternated body
100 */
101 RequestBody formParam(String name, Object value);
102
103 /**
104 * Add form params.
105 * @param params Map of params
106 * @return New alternated body
107 * @since 0.10
108 */
109 RequestBody formParams(Map<String, String> params);
110
111 /**
112 * Printer of byte array.
113 *
114 * @since 1.0
115 */
116 @Immutable
117 final class Printable {
118
119 /**
120 * Byte array.
121 */
122 @Immutable.Array
123 private final transient byte[] array;
124
125 /**
126 * Ctor.
127 * @param bytes Bytes to encapsulate
128 */
129 public Printable(final byte[] bytes) {
130 this.array = bytes;
131 }
132
133 @Override
134 public String toString() {
135 final StringBuilder text = new StringBuilder(0);
136 final char[] chrs = new String(
137 this.array, StandardCharsets.UTF_8
138 ).toCharArray();
139 if (chrs.length > 0) {
140 for (final char chr : chrs) {
141 // @checkstyle MagicNumber (1 line)
142 if (chr < 128) {
143 text.append(chr);
144 } else {
145 text.append("\\u").append(
146 Integer.toHexString(chr)
147 );
148 }
149 }
150 } else {
151 text.append("<<empty>>");
152 }
153 return text.toString();
154 }
155 }
156
157 }