io.reactivex.netty.contexts.http.HttpRequestIdProvider Maven / Gradle / Ivy
/*
* Copyright 2014 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 io.reactivex.netty.contexts.http;
import io.netty.util.AttributeKey;
import io.netty.util.AttributeMap;
import io.reactivex.netty.contexts.ContextKeySupplier;
import io.reactivex.netty.contexts.RequestCorrelator;
import io.reactivex.netty.contexts.RequestIdGenerator;
import io.reactivex.netty.contexts.RequestIdProvider;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;
/**
* An implementation of {@link RequestIdProvider} for HTTP protocol.
* This implementation honors HTTP pipelining and hence maintains a queue of request Ids generated on the same
* connection. The request Ids from the queue are removed when a response is set in the order they were received.
* Since, HTTP pipelining defines that the responses should be sent from the server in the same order they were received,
* this implementation uses a Queue to store and find request Ids for the responses sent from here.
*
* @author Nitesh Kant
*/
public class HttpRequestIdProvider implements RequestIdProvider {
public static final AttributeKey> REQUEST_IDS_KEY =
AttributeKey.valueOf("rxnetty_http_request_ids_queue");
private final RequestIdGenerator requestIdGenerator;
private final RequestCorrelator requestCorrelator;
private final String requestIdHeaderName;
public HttpRequestIdProvider(RequestIdGenerator requestIdGenerator, RequestCorrelator requestCorrelator,
String requestIdHeaderName) {
this.requestIdGenerator = requestIdGenerator;
this.requestCorrelator = requestCorrelator;
this.requestIdHeaderName = requestIdHeaderName;
}
public HttpRequestIdProvider(String requestIdHeaderName, RequestCorrelator requestCorrelator) {
this(new RequestIdGenerator() {
@Override
public String newRequestId(ContextKeySupplier keySupplier, AttributeMap channelAttributeMap) {
return UUID.randomUUID().toString();
}
}, requestCorrelator, requestIdHeaderName);
}
@Override
public String newRequestId(ContextKeySupplier keySupplier, AttributeMap channelAttributeMap) {
String requestId = requestIdGenerator.newRequestId(keySupplier, channelAttributeMap);
addRequestId(channelAttributeMap, requestId);
return requestId;
}
@Override
public String onServerRequest(ContextKeySupplier keySupplier, AttributeMap channelAttributeMap) {
String requestId = keySupplier.getContextValue(requestIdHeaderName);
if (null != requestId) {
addRequestId(channelAttributeMap, requestId);
}
return requestId;
}
@Override
public String beforeServerResponse(ContextKeySupplier responseKeySupplier, AttributeMap channelAttributeMap) {
return getRequestIdFromQueue(channelAttributeMap);
}
@Override
public String beforeClientRequest(AttributeMap clientAttributeMap) {
String requestId = requestCorrelator.getRequestIdForClientRequest();
if (null != requestId) {
addRequestId(clientAttributeMap, requestId);
}
return requestId;
}
@Override
public String onClientResponse(AttributeMap clientAttributeMap) {
return getRequestIdFromQueue(clientAttributeMap);
}
@Override
public String getRequestIdContextKeyName() {
return requestIdHeaderName;
}
private static void addRequestId(AttributeMap channelAttributeMap, String requestId) {
ConcurrentLinkedQueue requestIdsQueue = channelAttributeMap.attr(REQUEST_IDS_KEY).get();
if (null == requestIdsQueue) {
requestIdsQueue = new ConcurrentLinkedQueue();
ConcurrentLinkedQueue existingQueue = channelAttributeMap.attr(REQUEST_IDS_KEY).setIfAbsent(requestIdsQueue);
if (null != existingQueue) {
requestIdsQueue = existingQueue;
}
}
if (null != requestIdsQueue) {
requestIdsQueue.offer(requestId); // We can even use add() as this is a lock-free queue. Just using offer() to not confuse folks.
}
}
private static String getRequestIdFromQueue(AttributeMap channelAttributeMap) {
ConcurrentLinkedQueue requestIdsQueue = channelAttributeMap.attr(REQUEST_IDS_KEY).get();
if (null != requestIdsQueue) {
return requestIdsQueue.poll(); // Responses should be sent in the same order as the requests were received (HTTP pipelining)
}
return null;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy