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 }