/*
* Copyright 2016 LINE Corporation
*
* LINE Corporation licenses this file to you 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.linecorp.armeria.client;
import static java.util.Objects.requireNonNull;
import java.time.Duration;
import com.linecorp.armeria.common.NonWrappingRequestContext;
import com.linecorp.armeria.common.SessionProtocol;
import com.linecorp.armeria.common.http.DefaultHttpHeaders;
import com.linecorp.armeria.common.http.HttpHeaders;
import com.linecorp.armeria.common.http.HttpSessionProtocols;
import com.linecorp.armeria.common.logging.DefaultRequestLog;
import com.linecorp.armeria.common.logging.RequestLog;
import com.linecorp.armeria.common.logging.RequestLogAvailability;
import com.linecorp.armeria.common.logging.RequestLogBuilder;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.EventLoop;
/**
* Default {@link ClientRequestContext} implementation.
*/
public class DefaultClientRequestContext extends NonWrappingRequestContext implements ClientRequestContext {
private final EventLoop eventLoop;
private final ClientOptions options;
private final Endpoint endpoint;
private final String fragment;
private final DefaultRequestLog log;
private long writeTimeoutMillis;
private long responseTimeoutMillis;
private long maxResponseLength;
private String strVal;
/**
* Creates a new instance.
*
* @param sessionProtocol the {@link SessionProtocol} of the invocation
* @param request the request associated with this context
*/
public DefaultClientRequestContext(
EventLoop eventLoop, SessionProtocol sessionProtocol, Endpoint endpoint,
String method, String path, String fragment, ClientOptions options, Object request) {
super(sessionProtocol, method, path, request);
this.eventLoop = requireNonNull(eventLoop, "eventLoop");
this.options = requireNonNull(options, "options");
this.endpoint = requireNonNull(endpoint, "endpoint");
this.fragment = requireNonNull(fragment, "fragment");
log = new DefaultRequestLog(this);
writeTimeoutMillis = options.defaultWriteTimeoutMillis();
responseTimeoutMillis = options.defaultResponseTimeoutMillis();
maxResponseLength = options.defaultMaxResponseLength();
if (HttpSessionProtocols.isHttp(sessionProtocol)) {
final HttpHeaders headers = options.getOrElse(ClientOption.HTTP_HEADERS, HttpHeaders.EMPTY_HEADERS);
if (!headers.isEmpty()) {
final HttpHeaders headersCopy = new DefaultHttpHeaders(true, headers.size());
headersCopy.set(headers);
attr(HTTP_HEADERS).set(headersCopy);
}
}
}
@Override
protected Channel channel() {
if (log.isAvailable(RequestLogAvailability.REQUEST_START)) {
return log.channel();
} else {
return null;
}
}
@Override
public EventLoop eventLoop() {
return eventLoop;
}
@Override
public ClientOptions options() {
return options;
}
@Override
public Endpoint endpoint() {
return endpoint;
}
@Override
public String fragment() {
return fragment;
}
@Override
public long writeTimeoutMillis() {
return writeTimeoutMillis;
}
@Override
public void setWriteTimeoutMillis(long writeTimeoutMillis) {
if (writeTimeoutMillis < 0) {
throw new IllegalArgumentException(
"writeTimeoutMillis: " + writeTimeoutMillis + " (expected: >= 0)");
}
this.writeTimeoutMillis = writeTimeoutMillis;
}
@Override
public void setWriteTimeout(Duration writeTimeout) {
setWriteTimeoutMillis(requireNonNull(writeTimeout, "writeTimeout").toMillis());
}
@Override
public long responseTimeoutMillis() {
return responseTimeoutMillis;
}
@Override
public void setResponseTimeoutMillis(long responseTimeoutMillis) {
if (responseTimeoutMillis < 0) {
throw new IllegalArgumentException(
"responseTimeoutMillis: " + responseTimeoutMillis + " (expected: >= 0)");
}
this.responseTimeoutMillis = responseTimeoutMillis;
}
@Override
public void setResponseTimeout(Duration responseTimeout) {
setResponseTimeoutMillis(requireNonNull(responseTimeout, "responseTimeout").toMillis());
}
@Override
public long maxResponseLength() {
return maxResponseLength;
}
@Override
public void setMaxResponseLength(long maxResponseLength) {
this.maxResponseLength = maxResponseLength;
}
@Override
public RequestLog log() {
return log;
}
@Override
public RequestLogBuilder logBuilder() {
return log;
}
@Override
public String toString() {
String strVal = this.strVal;
if (strVal != null) {
return strVal;
}
final StringBuilder buf = new StringBuilder(96);
// Prepend the current channel information if available.
final Channel ch = channel();
final boolean hasChannel = ch != null;
if (hasChannel) {
buf.append(ch);
}
buf.append('[')
.append(sessionProtocol().uriText())
.append("://")
.append(endpoint.authority())
.append(path())
.append('#')
.append(method())
.append(']');
strVal = buf.toString();
if (hasChannel) {
this.strVal = strVal;
}
return strVal;
}
@Override
public ByteBufAllocator alloc() {
final Channel channel = channel();
return channel != null ? channel.alloc() : UnpooledByteBufAllocator.DEFAULT;
}
}