package org.mockserver.codec; import com.google.common.base.Strings; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.MessageToMessageEncoder; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.cookie.ClientCookieDecoder; import io.netty.handler.codec.http.cookie.Cookie; import io.netty.handler.codec.http.cookie.DefaultCookie; import io.netty.handler.codec.http.cookie.ServerCookieEncoder; import org.mockserver.mappers.ContentTypeMapper; import org.mockserver.model.*; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_LENGTH; import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE; import static io.netty.handler.codec.http.HttpHeaderNames.SET_COOKIE; import static org.mockserver.model.ConnectionOptions.isFalseOrNull; /** * @author jamesdbloom */ public class MockServerResponseEncoder extends MessageToMessageEncoder<HttpResponse> { @Override protected void encode(ChannelHandlerContext ctx, HttpResponse response, List<Object> out) { DefaultFullHttpResponse defaultFullHttpResponse = new DefaultFullHttpResponse( HttpVersion.HTTP_1_1, HttpResponseStatus.valueOf((response.getStatusCode() != null ? response.getStatusCode() : 200)), getBody(response) ); setHeaders(response, defaultFullHttpResponse); setCookies(response, defaultFullHttpResponse); out.add(defaultFullHttpResponse); } private ByteBuf getBody(HttpResponse response) { ByteBuf content = Unpooled.buffer(0, 0); Body body = response.getBody(); if (body != null) { Object bodyContents = body.getValue(); Charset bodyCharset = body.getCharset(ContentTypeMapper.determineCharsetForMessage(response)); if (bodyContents instanceof byte[]) { content = Unpooled.copiedBuffer((byte[]) bodyContents); } else if (bodyContents instanceof String) { content = Unpooled.copiedBuffer(((String) bodyContents).getBytes(bodyCharset)); } else if (body.toString() != null) { content = Unpooled.copiedBuffer(body.toString().getBytes(bodyCharset)); } } return content; } private void setHeaders(HttpResponse response, DefaultFullHttpResponse defaultFullHttpResponse) { if (response.getHeaders() != null) { for (Header header : response.getHeaders()) { for (NottableString value : header.getValues()) { defaultFullHttpResponse.headers().add(header.getName().getValue(), value.getValue()); } } } // Content-Type if (Strings.isNullOrEmpty(response.getFirstHeader(CONTENT_TYPE.toString()))) { if (response.getBody() != null && response.getBody().getContentType() != null) { defaultFullHttpResponse.headers().set(CONTENT_TYPE, response.getBody().getContentType()); } } // Content-Length if (Strings.isNullOrEmpty(response.getFirstHeader(CONTENT_LENGTH.toString()))) { ConnectionOptions connectionOptions = response.getConnectionOptions(); boolean overrideContentLength = connectionOptions != null && connectionOptions.getContentLengthHeaderOverride() != null; boolean addContentLength = connectionOptions == null || isFalseOrNull(connectionOptions.getSuppressContentLengthHeader()); if (overrideContentLength) { defaultFullHttpResponse.headers().set(CONTENT_LENGTH, connectionOptions.getContentLengthHeaderOverride()); } else if (addContentLength) { Body body = response.getBody(); byte[] bodyBytes = new byte[0]; if (body != null) { Object bodyContents = body.getValue(); Charset bodyCharset = body.getCharset(ContentTypeMapper.determineCharsetForMessage(response)); if (bodyContents instanceof byte[]) { bodyBytes = (byte[]) bodyContents; } else if (bodyContents instanceof String) { bodyBytes = ((String) bodyContents).getBytes(bodyCharset); } else if (body.toString() != null) { bodyBytes = body.toString().getBytes(bodyCharset); } } defaultFullHttpResponse.headers().set(CONTENT_LENGTH, bodyBytes.length); } } } private void setCookies(HttpResponse response, DefaultFullHttpResponse httpServletResponse) { if (response.getCookies() != null) { List<Cookie> cookieValues = new ArrayList<Cookie>(); for (org.mockserver.model.Cookie cookie : response.getCookies()) { if (!cookieHeaderAlreadyExists(response, cookie)) { cookieValues.add(new DefaultCookie(cookie.getName().getValue(), cookie.getValue().getValue())); } } for (Cookie cookieValue : cookieValues) { httpServletResponse.headers().add(SET_COOKIE, ServerCookieEncoder.LAX.encode(cookieValue)); } } } private boolean cookieHeaderAlreadyExists(HttpResponse response, org.mockserver.model.Cookie cookieValue) { List<String> setCookieHeaders = response.getHeader(SET_COOKIE.toString()); for (String setCookieHeader : setCookieHeaders) { String existingCookieName = ClientCookieDecoder.LAX.decode(setCookieHeader).name(); String existingCookieValue = ClientCookieDecoder.LAX.decode(setCookieHeader).value(); if (existingCookieName.equalsIgnoreCase(cookieValue.getName().getValue()) && existingCookieValue.equalsIgnoreCase(cookieValue.getValue().getValue())) { return true; } } return false; } }