001/* 002 * Copyright 2002-2018 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.http.server.reactive; 018 019import java.net.URISyntaxException; 020import java.util.function.BiFunction; 021 022import io.netty.handler.codec.http.HttpResponseStatus; 023import org.apache.commons.logging.Log; 024import reactor.core.publisher.Mono; 025import reactor.netty.http.server.HttpServerRequest; 026import reactor.netty.http.server.HttpServerResponse; 027 028import org.springframework.core.io.buffer.NettyDataBufferFactory; 029import org.springframework.http.HttpLogging; 030import org.springframework.http.HttpMethod; 031import org.springframework.util.Assert; 032 033/** 034 * Adapt {@link HttpHandler} to the Reactor Netty channel handling function. 035 * 036 * @author Stephane Maldini 037 * @author Rossen Stoyanchev 038 * @since 5.0 039 */ 040public class ReactorHttpHandlerAdapter implements BiFunction<HttpServerRequest, HttpServerResponse, Mono<Void>> { 041 042 private static final Log logger = HttpLogging.forLogName(ReactorHttpHandlerAdapter.class); 043 044 045 private final HttpHandler httpHandler; 046 047 048 public ReactorHttpHandlerAdapter(HttpHandler httpHandler) { 049 Assert.notNull(httpHandler, "HttpHandler must not be null"); 050 this.httpHandler = httpHandler; 051 } 052 053 054 @Override 055 public Mono<Void> apply(HttpServerRequest reactorRequest, HttpServerResponse reactorResponse) { 056 NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(reactorResponse.alloc()); 057 try { 058 ReactorServerHttpRequest request = new ReactorServerHttpRequest(reactorRequest, bufferFactory); 059 ServerHttpResponse response = new ReactorServerHttpResponse(reactorResponse, bufferFactory); 060 061 if (request.getMethod() == HttpMethod.HEAD) { 062 response = new HttpHeadResponseDecorator(response); 063 } 064 065 return this.httpHandler.handle(request, response) 066 .doOnError(ex -> logger.trace(request.getLogPrefix() + "Failed to complete: " + ex.getMessage())) 067 .doOnSuccess(aVoid -> logger.trace(request.getLogPrefix() + "Handling completed")); 068 } 069 catch (URISyntaxException ex) { 070 if (logger.isDebugEnabled()) { 071 logger.debug("Failed to get request URI: " + ex.getMessage()); 072 } 073 reactorResponse.status(HttpResponseStatus.BAD_REQUEST); 074 return Mono.empty(); 075 } 076 } 077 078}