001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.util; 018 019import java.net.URI; 020import java.util.Collection; 021import java.util.Map; 022 023import org.springframework.lang.Nullable; 024import org.springframework.util.MultiValueMap; 025 026/** 027 * Builder-style methods to prepare and expand a URI template with variables. 028 * 029 * <p>Effectively a generalization of {@link UriComponentsBuilder} but with 030 * shortcuts to expand directly into {@link URI} rather than 031 * {@link UriComponents} and also leaving common concerns such as encoding 032 * preferences, a base URI, and others as implementation concerns. 033 * 034 * <p>Typically obtained via {@link UriBuilderFactory} which serves as a central 035 * component configured once and used to create many URLs. 036 * 037 * @author Rossen Stoyanchev 038 * @since 5.0 039 * @see UriBuilderFactory 040 * @see UriComponentsBuilder 041 */ 042public interface UriBuilder { 043 044 /** 045 * Set the URI scheme which may contain URI template variables, 046 * and may also be {@code null} to clear the scheme of this builder. 047 * @param scheme the URI scheme 048 */ 049 UriBuilder scheme(@Nullable String scheme); 050 051 /** 052 * Set the URI user info which may contain URI template variables, and 053 * may also be {@code null} to clear the user info of this builder. 054 * @param userInfo the URI user info 055 */ 056 UriBuilder userInfo(@Nullable String userInfo); 057 058 /** 059 * Set the URI host which may contain URI template variables, and may also 060 * be {@code null} to clear the host of this builder. 061 * @param host the URI host 062 */ 063 UriBuilder host(@Nullable String host); 064 065 /** 066 * Set the URI port. Passing {@code -1} will clear the port of this builder. 067 * @param port the URI port 068 */ 069 UriBuilder port(int port); 070 071 /** 072 * Set the URI port . Use this method only when the port needs to be 073 * parameterized with a URI variable. Otherwise use {@link #port(int)}. 074 * Passing {@code null} will clear the port of this builder. 075 * @param port the URI port 076 */ 077 UriBuilder port(@Nullable String port); 078 079 /** 080 * Append to the path of this builder. 081 * <p>The given value is appended as-is without any checks for slashes other 082 * than to clean up duplicates. For example: 083 * <pre class="code"> 084 * 085 * builder.path("/first-").path("value/").path("/{id}").build("123") 086 * 087 * // Results is "/first-value/123" 088 * </pre> 089 * <p>By contrast {@link #pathSegment(String...)} builds the path from 090 * individual path segments and in that case slashes are inserted transparently. 091 * In some cases you may use a combination of both {@code pathSegment} and 092 * {@code path}. For example: 093 * <pre class="code"> 094 * 095 * builder.pathSegment("first-value", "second-value").path("/") 096 * 097 * // Results is "/first-value/second-value/" 098 * 099 * </pre> 100 * <p>If a URI variable value contains slashes, whether those are encoded or 101 * not depends on the configured encoding mode. See 102 * {@link UriComponentsBuilder#encode()}, or if using 103 * {@code UriComponentsBuilder} via {@link DefaultUriBuilderFactory} 104 * (e.g. {@code WebClient} or {@code RestTemplate}) see its 105 * {@link DefaultUriBuilderFactory#setEncodingMode encodingMode} property. 106 * Also see the <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#web-uri-encoding"> 107 * URI Encoding</a> section of the reference docs. 108 * @param path the URI path 109 */ 110 UriBuilder path(String path); 111 112 /** 113 * Override the existing path. 114 * @param path the URI path, or {@code null} for an empty path 115 */ 116 UriBuilder replacePath(@Nullable String path); 117 118 /** 119 * Append to the path using path segments. For example: 120 * <pre class="code"> 121 * 122 * builder.pathSegment("first-value", "second-value", "{id}").build("123") 123 * 124 * // Results is "/first-value/second-value/123" 125 * 126 * </pre> 127 * <p>If slashes are present in a path segment, they are encoded: 128 * <pre class="code"> 129 * 130 * builder.pathSegment("ba/z", "{id}").build("a/b") 131 * 132 * // Results is "/ba%2Fz/a%2Fb" 133 * 134 * </pre> 135 * To insert a trailing slash, use the {@link #path} builder method: 136 * <pre class="code"> 137 * 138 * builder.pathSegment("first-value", "second-value").path("/") 139 * 140 * // Results is "/first-value/second-value/" 141 * 142 * </pre> 143 * @param pathSegments the URI path segments 144 */ 145 UriBuilder pathSegment(String... pathSegments) throws IllegalArgumentException; 146 147 /** 148 * Parse the given query string into query parameters where parameters are 149 * separated with {@code '&'} and their values, if any, with {@code '='}. 150 * The query may contain URI template variables. 151 * <p><strong>Note: </strong> please, review the Javadoc of 152 * {@link #queryParam(String, Object...)} for further notes on the treatment 153 * and encoding of individual query parameters. 154 * @param query the query string 155 */ 156 UriBuilder query(String query); 157 158 /** 159 * Clear existing query parameters and then delegate to {@link #query(String)}. 160 * <p><strong>Note: </strong> please, review the Javadoc of 161 * {@link #queryParam(String, Object...)} for further notes on the treatment 162 * and encoding of individual query parameters. 163 * @param query the query string; a {@code null} value removes all query parameters. 164 */ 165 UriBuilder replaceQuery(@Nullable String query); 166 167 /** 168 * Append the given query parameter. Both the parameter name and values may 169 * contain URI template variables to be expanded later from values. If no 170 * values are given, the resulting URI will contain the query parameter name 171 * only, e.g. {@code "?foo"} instead of {@code "?foo=bar"}. 172 * <p><strong>Note:</strong> encoding, if applied, will only encode characters 173 * that are illegal in a query parameter name or value such as {@code "="} 174 * or {@code "&"}. All others that are legal as per syntax rules in 175 * <a href="https://tools.ietf.org/html/rfc3986">RFC 3986</a> are not 176 * encoded. This includes {@code "+"} which sometimes needs to be encoded 177 * to avoid its interpretation as an encoded space. Stricter encoding may 178 * be applied by using a URI template variable along with stricter encoding 179 * on variable values. For more details please read the 180 * <a href="https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#web-uri-encoding">"URI Encoding"</a> 181 * section of the Spring Framework reference. 182 * @param name the query parameter name 183 * @param values the query parameter values 184 * @see #queryParam(String, Collection) 185 */ 186 UriBuilder queryParam(String name, Object... values); 187 188 /** 189 * Variant of {@link #queryParam(String, Object...)} with a Collection. 190 * <p><strong>Note: </strong> please, review the Javadoc of 191 * {@link #queryParam(String, Object...)} for further notes on the treatment 192 * and encoding of individual query parameters. 193 * @param name the query parameter name 194 * @param values the query parameter values 195 * @since 5.2 196 * @see #queryParam(String, Object...) 197 */ 198 UriBuilder queryParam(String name, @Nullable Collection<?> values); 199 200 /** 201 * Add multiple query parameters and values. 202 * <p><strong>Note: </strong> please, review the Javadoc of 203 * {@link #queryParam(String, Object...)} for further notes on the treatment 204 * and encoding of individual query parameters. 205 * @param params the params 206 */ 207 UriBuilder queryParams(MultiValueMap<String, String> params); 208 209 /** 210 * Set the query parameter values replacing existing values, or if no 211 * values are given, the query parameter is removed. 212 * <p><strong>Note: </strong> please, review the Javadoc of 213 * {@link #queryParam(String, Object...)} for further notes on the treatment 214 * and encoding of individual query parameters. 215 * @param name the query parameter name 216 * @param values the query parameter values 217 * @see #replaceQueryParam(String, Collection) 218 */ 219 UriBuilder replaceQueryParam(String name, Object... values); 220 221 /** 222 * Variant of {@link #replaceQueryParam(String, Object...)} with a Collection. 223 * <p><strong>Note: </strong> please, review the Javadoc of 224 * {@link #queryParam(String, Object...)} for further notes on the treatment 225 * and encoding of individual query parameters. 226 * @param name the query parameter name 227 * @param values the query parameter values 228 * @since 5.2 229 * @see #replaceQueryParam(String, Object...) 230 */ 231 UriBuilder replaceQueryParam(String name, @Nullable Collection<?> values); 232 233 /** 234 * Set the query parameter values after removing all existing ones. 235 * <p><strong>Note: </strong> please, review the Javadoc of 236 * {@link #queryParam(String, Object...)} for further notes on the treatment 237 * and encoding of individual query parameters. 238 * @param params the query parameter name 239 */ 240 UriBuilder replaceQueryParams(MultiValueMap<String, String> params); 241 242 /** 243 * Set the URI fragment. The given fragment may contain URI template variables, 244 * and may also be {@code null} to clear the fragment of this builder. 245 * @param fragment the URI fragment 246 */ 247 UriBuilder fragment(@Nullable String fragment); 248 249 /** 250 * Build a {@link URI} instance and replaces URI template variables 251 * with the values from an array. 252 * @param uriVariables the map of URI variables 253 * @return the URI 254 */ 255 URI build(Object... uriVariables); 256 257 /** 258 * Build a {@link URI} instance and replaces URI template variables 259 * with the values from a map. 260 * @param uriVariables the map of URI variables 261 * @return the URI 262 */ 263 URI build(Map<String, ?> uriVariables); 264 265}