com.netflix.zuul.context.RxNettySessionContextFactory Maven / Gradle / Ivy
/**
* Copyright 2015 Netflix, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.netflix.zuul.context;
import com.netflix.zuul.rx.UnicastDisposableCachingSubject;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.reactivex.netty.protocol.http.server.HttpServerRequest;
import io.reactivex.netty.protocol.http.server.HttpServerResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rx.Observable;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import java.util.Map;
/**
* User: [email protected]
* Date: 2/25/15
* Time: 4:03 PM
*/
public class RxNettySessionContextFactory implements SessionContextFactory
{
private static final Logger LOG = LoggerFactory.getLogger(RxNettySessionContextFactory.class);
@Override
public ZuulMessage create(SessionContext context, HttpServerRequest httpServerRequest)
{
// Get the client IP (ignore XFF headers at this point, as that can be app specific).
String clientIp = getIpAddress(httpServerRequest.getNettyChannel());
// TODO - How to get uri scheme from the netty request?
String scheme = "http";
// This is the only way I found to get the port of the request with netty...
int port = ((InetSocketAddress) httpServerRequest.getNettyChannel().localAddress()).getPort();
String serverName = ((InetSocketAddress) httpServerRequest.getNettyChannel().localAddress()).getHostString();
// Setup the req/resp message objects.
HttpRequestMessage request = new HttpRequestMessage(
context,
httpServerRequest.getHttpVersion().text(),
httpServerRequest.getHttpMethod().name().toLowerCase(),
httpServerRequest.getUri(),
copyQueryParams(httpServerRequest),
copyHeaders(httpServerRequest),
clientIp,
scheme,
port,
serverName
);
// Store this original request info for future reference (ie. for metrics and access logging purposes).
request.storeOriginalRequestInfo();
return wrapBody(request, httpServerRequest);
}
@Override
public Observable write(ZuulMessage msg, HttpServerResponse nativeResponse)
{
HttpResponseMessage zuulResp = (HttpResponseMessage) msg;
// Set the response status code.
nativeResponse.setStatus(HttpResponseStatus.valueOf(zuulResp.getStatus()));
// Now set all of the response headers - note this is a multi-set in keeping with HTTP semantics
for (Map.Entry entry : zuulResp.getHeaders().entries()) {
nativeResponse.getHeaders().add(entry.getKey(), entry.getValue());
}
// Write response body stream as received.
Observable chain;
Observable bodyStream = zuulResp.getBodyStream();
if (bodyStream != null) {
chain = bodyStream
.doOnNext(bb -> nativeResponse.writeBytesAndFlush(bb))
.ignoreElements()
.doOnCompleted(() -> nativeResponse.close())
.map(bb -> msg);
}
else {
chain = Observable.just(msg);
}
return chain;
}
private ZuulMessage wrapBody(HttpRequestMessage request, HttpServerRequest nettyServerRequest)
{
//PublishSubject cachedContent = PublishSubject.create();
UnicastDisposableCachingSubject cachedContent = UnicastDisposableCachingSubject.create();
// Subscribe to the response-content observable (retaining the ByteBufS first).
nettyServerRequest.getContent().map(ByteBuf::retain).subscribe(cachedContent);
request.setBodyStream(cachedContent);
return request;
}
private Headers copyHeaders(HttpServerRequest httpServerRequest)
{
Headers headers = new Headers();
for (Map.Entry entry : httpServerRequest.getHeaders().entries()) {
headers.add(entry.getKey(), entry.getValue());
}
return headers;
}
private HttpQueryParams copyQueryParams(HttpServerRequest httpServerRequest)
{
HttpQueryParams queryParams = new HttpQueryParams();
Map> serverQueryParams = httpServerRequest.getQueryParameters();
for (String key : serverQueryParams.keySet()) {
for (String value : serverQueryParams.get(key)) {
queryParams.add(key, value);
}
}
return queryParams;
}
private static String getIpAddress(Channel channel) {
if (null == channel) {
return "";
}
SocketAddress localSocketAddress = channel.localAddress();
if (null != localSocketAddress && InetSocketAddress.class.isAssignableFrom(localSocketAddress.getClass())) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) localSocketAddress;
if (inetSocketAddress.getAddress() != null) {
return inetSocketAddress.getAddress().getHostAddress();
}
}
SocketAddress remoteSocketAddr = channel.remoteAddress();
if (null != remoteSocketAddr && InetSocketAddress.class.isAssignableFrom(remoteSocketAddr.getClass())) {
InetSocketAddress inetSocketAddress = (InetSocketAddress) remoteSocketAddr;
if (inetSocketAddress.getAddress() != null) {
return inetSocketAddress.getAddress().getHostAddress();
}
}
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy