001/*
002 * Copyright 2002-2019 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.filter.reactive;
018
019import java.util.Optional;
020
021import reactor.core.publisher.Mono;
022import reactor.util.context.Context;
023
024import org.springframework.web.server.ServerWebExchange;
025import org.springframework.web.server.WebFilter;
026import org.springframework.web.server.WebFilterChain;
027
028/**
029 * Inserts an attribute in the Reactor {@link Context} that makes the current
030 * {@link ServerWebExchange} available under the attribute name
031 * {@link #EXCHANGE_CONTEXT_ATTRIBUTE}. This is useful for access to the
032 * exchange without explicitly passing it to components that participate in
033 * request processing.
034 *
035 * <p>The convenience method {@link #get(Context)} looks up the exchange.
036 *
037 * @author Rossen Stoyanchev
038 * @since 5.2
039 */
040public class ServerWebExchangeContextFilter implements WebFilter {
041
042        /** Attribute name under which the exchange is saved in the context. */
043        public static final String EXCHANGE_CONTEXT_ATTRIBUTE =
044                        ServerWebExchangeContextFilter.class.getName() + ".EXCHANGE_CONTEXT";
045
046
047        @Override
048        public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
049                return chain.filter(exchange)
050                                .subscriberContext(cxt -> cxt.put(EXCHANGE_CONTEXT_ATTRIBUTE, exchange));
051        }
052
053
054        /**
055         * Access the {@link ServerWebExchange} from the Reactor Context, if available,
056         * which is if {@link ServerWebExchangeContextFilter} is configured for use
057         * and the give context was obtained from a request processing chain.
058         * @param context the context in which to access the exchange
059         * @return the exchange
060         */
061        public static Optional<ServerWebExchange> get(Context context) {
062                return context.getOrEmpty(EXCHANGE_CONTEXT_ATTRIBUTE);
063        }
064
065}