001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.http.remote; 018 019import static java.lang.annotation.ElementType.*; 020import static java.lang.annotation.RetentionPolicy.*; 021 022import java.lang.annotation.*; 023 024/** 025 * Identifies a proxy against a REST interface. 026 * 027 * <h5 class='section'>See Also:</h5><ul> 028 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestProxies">REST Proxies</a> 029 * </ul> 030 */ 031@Documented 032@Target({ TYPE }) 033@Retention(RUNTIME) 034@Inherited 035public @interface Remote { 036 037 /** 038 * Default request header list. 039 * 040 * <p> 041 * Specifies a supplier of headers to set on all requests. The value is interpreted by the active REST client: 042 * the classic Apache-HttpClient transport accepts subclasses of 043 * <c>org.apache.juneau.http.classic.header.HeaderList</c>; other transports may ignore the value. 044 * 045 * <h5 class='section'>Notes:</h5><ul> 046 * <li class='note'> 047 * Supplier class must provide a public no-arg constructor. 048 * <li class='note'> 049 * Default <c>Void.class</c> means no default header list is supplied. 050 * </ul> 051 * 052 * @return The annotation value. 053 */ 054 Class<?> headerList() default Void.class; 055 056 /** 057 * Default request headers. 058 * 059 * <p> 060 * Specifies headers to set on all requests. 061 * 062 * <h5 class='section'>Notes:</h5><ul> 063 * <li class='note'> 064 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 065 * (e.g. <js>"$P{mySystemProperty}"</js>). 066 * </ul> 067 * 068 * @return The annotation value. 069 */ 070 String[] headers() default {}; 071 072 /** 073 * Default request query parameters. 074 * 075 * <p> 076 * Specifies always-applied constant query parameters emitted on <i>every</i> request the proxy makes — no 077 * corresponding method parameter is required. Each entry uses the <js>"name=value"</js> form (the first 078 * <js>'='</js> separates name from value), mirroring the URL-query convention and the {@link #headers()} 079 * <js>"Name: value"</js> precedent. 080 * 081 * <p> 082 * A caller-supplied parameter value for the same name still composes with the constant (the constant is not 083 * suppressed). A method-level constant of the same name (see {@code @RemoteOp(queryData=...)} and the verb 084 * annotations) takes precedence over the interface-level value declared here. 085 * 086 * <h5 class='section'>Notes:</h5><ul> 087 * <li class='note'> 088 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 089 * (e.g. <js>"$S{mySystemProperty}"</js>). 090 * <li class='note'> 091 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 092 * (<c>RestClient.getRemote(...)</c>). 093 * </ul> 094 * 095 * @return The annotation value. 096 */ 097 String[] queryData() default {}; 098 099 /** 100 * Default request form-data parameters. 101 * 102 * <p> 103 * Specifies always-applied constant form-data fields emitted on <i>every</i> request the proxy makes — no 104 * corresponding method parameter is required. Each entry uses the <js>"name=value"</js> form (the first 105 * <js>'='</js> separates name from value), mirroring the form-encoded convention and the {@link #headers()} 106 * <js>"Name: value"</js> precedent. 107 * 108 * <p> 109 * A caller-supplied parameter value for the same name still composes with the constant (the constant is not 110 * suppressed). A method-level constant of the same name (see {@code @RemoteOp(formData=...)} and the verb 111 * annotations) takes precedence over the interface-level value declared here. 112 * 113 * <h5 class='section'>Notes:</h5><ul> 114 * <li class='note'> 115 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 116 * (e.g. <js>"$S{mySystemProperty}"</js>). 117 * <li class='note'> 118 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 119 * (<c>RestClient.getRemote(...)</c>). 120 * </ul> 121 * 122 * @return The annotation value. 123 */ 124 String[] formData() default {}; 125 126 /** 127 * REST service path. 128 * 129 * <ul class='values'> 130 * <li>An absolute URL. 131 * <li>A relative URL interpreted as relative to the root URL defined on the <c>RestClient</c> 132 * <li>No path interpreted as the class name (e.g. <js>"http://localhost/root-url/org.foo.MyInterface"</js>) 133 * </ul> 134 * 135 * <h5 class='section'>Notes:</h5><ul> 136 * <li class='note'> 137 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 138 * (e.g. <js>"$P{mySystemProperty}"</js>). 139 * </ul> 140 * 141 * @return The annotation value. 142 */ 143 String path() default ""; 144 145 /** 146 * Alias for {@link #path()}. 147 * 148 * <p> 149 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 150 * (e.g. <js>"$P{mySystemProperty}"</js>). 151 * </p> 152 * 153 * @return The annotation value. 154 */ 155 String value() default ""; 156 157 /** 158 * Base/host override applied to every request the proxy makes. 159 * 160 * <p> 161 * Replaces only the authority+root portion of the request URL — in effect, an annotation-declared substitute 162 * for the client's root URL — while <i>preserving</i> the interface base path, the method path, and any 163 * <c>{var}</c> templating. For example, with <c>baseUrl=<js>"http://other-host"</js></c>, an interface path of 164 * <js>"/api"</js> and a method path of <js>"/users/{id}"</js>, the effective URL is 165 * <js>"http://other-host/api/users/{id}"</js>. 166 * 167 * <p> 168 * Precedence (most-specific first): an {@link org.apache.juneau.http.Url @Url} parameter, then a method-level 169 * {@code baseUrl} (see {@code @RemoteOp(baseUrl=...)} and the verb annotations), then this interface-level value, 170 * then the client root URL. 171 * 172 * <h5 class='section'>Notes:</h5><ul> 173 * <li class='note'> 174 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 175 * (e.g. <js>"$S{mySystemProperty}"</js>). 176 * <li class='note'> 177 * Only <c>http</c>/<c>https</c> schemes are permitted when the override yields an absolute URL; other schemes 178 * are rejected (SSRF guardrail). 179 * <li class='note'> 180 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 181 * (<c>RestClient.getRemote(...)</c>), with the same http/https-only scheme guard on both. 182 * </ul> 183 * 184 * @return The annotation value. 185 */ 186 String baseUrl() default ""; 187 188 /** 189 * Interface-level default request body format (and {@code Content-Type} header) for all methods. 190 * 191 * <p> 192 * Names a media type (e.g. <js>"application/xml"</js>) used as the default for every method on this interface. The 193 * next-generation engine selects the matching registered request serializer from the client's serializer set so the 194 * request body bytes are actually written in that format, and sets the {@code Content-Type} header to this media 195 * type — cleanly replacing the serializer's default content type (exactly one {@code Content-Type} header is 196 * sent). If no registered serializer matches, the client's default serializer is used but this media type is still 197 * sent as the label (supporting vendor media types). 198 * 199 * <p> 200 * A method-level {@link RemoteOp#contentType()} (or verb-annotation equivalent) overrides this default. 201 * 202 * <h5 class='section'>Notes:</h5><ul> 203 * <li class='note'> 204 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 205 * (<c>RestClient.getRemote(...)</c>). 206 * </ul> 207 * 208 * @return The annotation value. 209 */ 210 String contentType() default ""; 211 212 /** 213 * Interface-level default {@code Accept} header (and response parser fallback) for all methods. 214 * 215 * <p> 216 * Names a media type (e.g. <js>"application/xml"</js>) sent as the default {@code Accept} header for every method on 217 * this interface. Response parsing remains driven by the <i>response</i> {@code Content-Type}; this media type is 218 * the fallback parser only when the response is unlabeled or its {@code Content-Type} matches no registered parser. 219 * 220 * <p> 221 * A method-level {@link RemoteOp#accept()} (or verb-annotation equivalent) overrides this default. 222 * 223 * <h5 class='section'>Notes:</h5><ul> 224 * <li class='note'> 225 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 226 * (<c>RestClient.getRemote(...)</c>). 227 * </ul> 228 * 229 * @return The annotation value. 230 */ 231 String accept() default ""; 232 233 /** 234 * Specifies the client version of this interface. 235 * 236 * <p> 237 * Used to populate the <js>"Client-Version"</js> header that identifies what version of client this is 238 * so that the server side can handle older versions accordingly. 239 * 240 * <p> 241 * The format of this is a string of the format <c>#[.#[.#[...]]</c> (e.g. <js>"1.2.3"</js>). 242 * 243 * <p> 244 * The server side then uses an OSGi-version matching pattern to identify which methods to call: 245 * <p class='bjava'> 246 * <jc>// Call this method if Client-Version is at least 2.0. 247 * // Note that this also matches 2.0.1.</jc> 248 * <ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"2.0"</js>) 249 * <jk>public</jk> Object method1() {...} 250 * 251 * <jc>// Call this method if Client-Version is at least 1.1, but less than 2.0.</jc> 252 * <ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"[1.1,2.0)"</js>) 253 * <jk>public</jk> Object method2() {...} 254 * 255 * <jc>// Call this method if Client-Version is less than 1.1.</jc> 256 * <ja>@RestGet</ja>(path=<js>"/foobar"</js>, clientVersion=<js>"[0,1.1)"</js>) 257 * <jk>public</jk> Object method3() {...} 258 * </p> 259 * 260 * <h5 class='section'>Notes:</h5><ul> 261 * <li class='note'> 262 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 263 * (e.g. <js>"$P{mySystemProperty}"</js>). 264 * </ul> 265 * 266 * @return The annotation value. 267 */ 268 String version() default ""; 269 270 /** 271 * Specifies the client version header name. 272 * 273 * <p> 274 * The default value is <js>"Client-Version"</js>. 275 * 276 * <h5 class='section'>Notes:</h5><ul> 277 * <li class='note'> 278 * Supports <a class="doclink" href="https://juneau.apache.org/docs/topics/DefaultVarResolver">VarResolver.DEFAULT</a> 279 * (e.g. <js>"$P{mySystemProperty}"</js>). 280 * </ul> 281 * 282 * @return The annotation value. 283 */ 284 String versionHeader() default ""; 285 286 /** 287 * Default lifecycle interceptors applied to every request the proxy makes. 288 * 289 * <p> 290 * Each class must implement the next-generation <c>RestCallInterceptor</c> SPI and provide a public no-arg 291 * constructor. Interface-level interceptors run <i>after</i> the builder-configured interceptors and <i>before</i> 292 * any method-level ({@code @RemoteOp/@RemoteGet/...(interceptors=...)}) interceptors; the three sets are unioned in 293 * the order builder → interface → method (method-level runs closest to the call). 294 * 295 * <h5 class='section'>Notes:</h5><ul> 296 * <li class='note'> 297 * The member type is {@code Class<?>[]} (not {@code Class<? extends RestCallInterceptor>[]}) because 298 * <c>RestCallInterceptor</c> lives in the {@code juneau-rest-client} module, which this annotation's module 299 * must not depend on; each element is resolved to a <c>RestCallInterceptor</c> at proxy-build time. 300 * <li class='note'> 301 * Honored by the next-generation engine (<c>RestClient.remote(...)</c>) only; the classic engine currently 302 * ignores this attribute. 303 * </ul> 304 * 305 * @return The annotation value. 306 */ 307 Class<?>[] interceptors() default {}; 308 309 /** 310 * Default per-call response/read timeout applied to every request the proxy makes. 311 * 312 * <p> 313 * Expressed as a duration string (e.g. <js>"30s"</js>, <js>"1500ms"</js>, <js>"1m"</js>) parsed by Juneau's 314 * duration parser. A method-level {@code timeout} ({@code @RemoteOp/@RemoteGet/...}) overrides this default. 315 * Connect timeouts remain a client-level setting (not configurable per call). 316 * 317 * <h5 class='section'>Notes:</h5><ul> 318 * <li class='note'> 319 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 320 * (<c>RestClient.getRemote(...)</c>). 321 * </ul> 322 * 323 * @return The annotation value. 324 */ 325 String timeout() default ""; 326 327 /** 328 * Default maximum number of automatic retry attempts applied to every request the proxy makes. 329 * 330 * <p> 331 * A value of {@code 0} (the default) disables retries. A positive method-level {@code retries} overrides this 332 * default. See {@code @RemoteOp(retries=...)} for the retry trigger statuses and the (hard) safety gating rules. 333 * 334 * <h5 class='section'>Notes:</h5><ul> 335 * <li class='note'> 336 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 337 * (<c>RestClient.getRemote(...)</c>). 338 * </ul> 339 * 340 * @return The annotation value. 341 */ 342 int retries() default 0; 343 344 /** 345 * Opts non-idempotent verbs (<c>POST</c>/<c>PATCH</c>) into automatic retries for every method on the proxy. 346 * 347 * <p> 348 * Has no effect unless {@link #retries()} (or a method-level {@code retries}) is positive. Even when enabled, a 349 * request with a non-repeatable body is never retried. The effective value is the logical OR of this default and 350 * the method-level value. 351 * 352 * <h5 class='section'>Notes:</h5><ul> 353 * <li class='note'> 354 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 355 * (<c>RestClient.getRemote(...)</c>). 356 * </ul> 357 * 358 * @return The annotation value. 359 */ 360 boolean retryNonIdempotent() default false; 361 362 /** 363 * Default for throwing a generic exception on an error response, applied to every method on the proxy. 364 * 365 * <p> 366 * When <jk>true</jk> and the response status is an error ({@code >=400}) and no typed exception from the method's 367 * {@code throws} clause matched, a generic exception is thrown. The effective value is the logical OR of this 368 * default and the method-level value. See {@code @RemoteOp(throwOnError=...)}. 369 * 370 * <h5 class='section'>Notes:</h5><ul> 371 * <li class='note'> 372 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 373 * (<c>RestClient.getRemote(...)</c>). 374 * </ul> 375 * 376 * @return The annotation value. 377 */ 378 boolean throwOnError() default false; 379 380 /** 381 * Opts this interface's absolute {@code @Remote}/{@code @Url}/{@code baseUrl()} targets out of the default 382 * deny-private SSRF guardrail, applied to every method on the proxy. 383 * 384 * <p> 385 * By default, an absolute <c>http</c>/<c>https</c> URL supplied via {@link #baseUrl()}, an {@code @Url} 386 * parameter, or an already-absolute {@link #path()}/{@link #value()} is rejected — both at pre-check time 387 * and at connect time via resolved-address pinning, re-checked on every followed redirect — when it targets 388 * a loopback, RFC1918/link-local, IPv6 unique-local, or cloud-metadata address. Setting this to <jk>true</jk> 389 * disables that check for local-dev/intranet targets that are intentionally private. 390 * 391 * <p> 392 * The effective value is the logical OR of this annotation value, the {@code RestClient} builder's 393 * {@code allowPrivateUrls(...)} setting, and the <js>"RestClient.allowPrivateUrls"</js> system property: any one 394 * of the three opting in is sufficient. 395 * 396 * <h5 class='section'>Notes:</h5><ul> 397 * <li class='note'> 398 * Honored by both the next-generation engine (<c>RestClient.remote(...)</c>) and the classic engine 399 * (<c>RestClient.getRemote(...)</c>). 400 * <li class='note'> 401 * Does not affect the http/https-only scheme guard, which always applies. 402 * </ul> 403 * 404 * @return The annotation value. 405 */ 406 boolean allowPrivateUrls() default false; 407}