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.rest.client; 018 019/** 020 * Lifecycle interceptor for REST calls made by {@link RestClient}. 021 * 022 * <p> 023 * Registered on the client builder via {@link RestClient.Builder#interceptors(RestCallInterceptor...)}. 024 * All callbacks have default no-op implementations so implementations only need to override the hooks they care about. 025 * 026 * <h5 class='section'>Example:</h5> 027 * <p class='bjava'> 028 * RestClient <jv>client</jv> = RestClient.<jsm>builder</jsm>() 029 * .transport(<jv>transport</jv>) 030 * .interceptors(new RestCallInterceptor() { 031 * @Override 032 * <jk>public void</jk> onConnect(RestRequest req, RestResponse res) { 033 * System.<jf>out</jf>.println(<js>"Response: "</js> + res.getStatusCode()); 034 * } 035 * }) 036 * .build(); 037 * </p> 038 * 039 * <h5 class='section'>See Also:</h5><ul> 040 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/NextGenRestClient">Next-Generation REST Client</a> 041 * </ul> 042 * 043 * @since 9.2.1 044 */ 045@SuppressWarnings({ 046 "java:S112" // Interceptor SPI callbacks intentionally declare 'throws Exception' so implementations may abort a call with any exception type. 047}) 048public interface RestCallInterceptor { 049 050 /** 051 * Called before the transport request is built and sent. 052 * 053 * <p> 054 * Use this hook to add headers, modify query parameters, or short-circuit the call. 055 * 056 * @param req The request being built. Never <jk>null</jk>. 057 * @throws Exception If the call should be aborted. 058 */ 059 default void onInit(RestRequest req) throws Exception {} 060 061 /** 062 * Called after a response has been received from the transport. 063 * 064 * <p> 065 * Use this hook to inspect status codes, validate headers, or modify how the response is interpreted. 066 * 067 * @param req The request that was sent. Never <jk>null</jk>. 068 * @param res The response received. Never <jk>null</jk>. 069 * @throws Exception If a post-connect error should be raised. 070 */ 071 default void onConnect(RestRequest req, RestResponse res) throws Exception {} 072 073 /** 074 * Called when the request is being closed (in the {@code finally} block of {@link RestRequest#run()}). 075 * 076 * <p> 077 * This is called regardless of whether the call succeeded or failed, and is always invoked before 078 * the logger receives its entry. Use it for cleanup, metrics recording, or span/trace finalization. 079 * 080 * @param req The request. Never <jk>null</jk>. 081 * @param res The response, or <jk>null</jk> if the transport failed before a response was received. 082 * @throws Exception If an error occurs during close handling. 083 */ 084 default void onClose(RestRequest req, RestResponse res) throws Exception {} 085}