/*
* Copyright 2013 BiasedBit
*
* 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.biasedbit.http.client.util;
import com.biasedbit.http.client.future.DataSinkListener;
import com.biasedbit.http.client.future.DefaultRequestFuture;
import com.biasedbit.http.client.processor.ResponseProcessor;
import lombok.Getter;
import lombok.Setter;
import org.jboss.netty.handler.codec.http.HttpMethod;
import org.jboss.netty.handler.codec.http.HttpRequest;
import static com.biasedbit.http.client.util.Utils.ensureValue;
/**
* State holder context for a request.
* <p/>
* This structure is passed between the {@link com.biasedbit.http.client.HttpClient} and the {@link
* com.biasedbit.http.client.connection.Connection} and associates a
* {@link org.jboss.netty.handler.codec.http.HttpRequest} to a {@link com.biasedbit.http.client.processor.ResponseProcessor} and a
* {@link com.biasedbit.http.client.future.RequestFuture}.
* <p/>
* It also contains other information such as the host address to which this request was originally inteded for,
* as well as its port and the timeout for the HTTP request/response operation to complete.
*
* @author <a href="http://biasedbit.com/">Bruno de Carvalho</a>
*/
public class RequestContext<T> {
// properties -----------------------------------------------------------------------------------------------------
@Getter private final String host;
@Getter private final int port;
@Getter private final int timeout;
@Getter private final HttpRequest request;
@Getter private final ResponseProcessor<T> processor;
@Getter private final DefaultRequestFuture<T> future = new DefaultRequestFuture<>();
@Getter @Setter private DataSinkListener dataSinkListener;
// constructors ---------------------------------------------------------------------------------------------------
public RequestContext(String host, int port, int timeout, HttpRequest request, ResponseProcessor<T> processor) {
ensureValue(host != null, "Host cannot be null");
ensureValue(port > 0 && port <= 65536, "Invalid port: " + port);
ensureValue(request != null, "HttpRequest cannot be null");
ensureValue(processor != null, "ResponseProcessor cannot be null");
this.host = host;
this.port = port;
this.timeout = timeout < 0 ? 0 : timeout;
this.request = request;
this.processor = processor;
}
// interface ------------------------------------------------------------------------------------------------------
/**
* Determines (based on request method) if a request is idempotent or not, based on recommendations of the RFC.
* <p/>
* Idempotent requests: GET, HEAD, PUT, DELETE, OPTIONS, TRACE
* Non-idempotent requests: POST, PATCH, CONNECT
* <p/>
* More info: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
*
* @return true if request is idempotent, false otherwise.
*/
public boolean isIdempotent() {
return !(request.getMethod().equals(HttpMethod.POST) ||
request.getMethod().equals(HttpMethod.PATCH) ||
request.getMethod().equals(HttpMethod.CONNECT));
}
// object overrides -----------------------------------------------------------------------------------------------
@Override public String toString() {
return new StringBuilder()
.append(request.getMethod()).append(' ')
.append(request.getUri()).append(" (")
.append(host).append(':')
.append(port).append(')').append("@").append(Integer.toHexString(hashCode())).toString();
}
}