All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.king.platform.net.http.netty.requestbuilder.BuiltNettyClientRequest Maven / Gradle / Ivy

There is a newer version: 3.0.26
Show newest version
// Copyright (C) king.com Ltd 2015
// https://github.com/king/king-http-client
// Author: Magnus Gustafsson
// License: Apache 2.0, https://raw.github.com/king/king-http-client/LICENSE-APACHE

package com.king.platform.net.http.netty.requestbuilder;


import com.king.platform.net.http.HttpResponse;
import com.king.platform.net.http.*;
import com.king.platform.net.http.netty.*;
import com.king.platform.net.http.netty.eventbus.ExternalEventTrigger;
import com.king.platform.net.http.netty.request.HttpBody;
import com.king.platform.net.http.netty.request.NettyHttpClientRequest;
import com.king.platform.net.http.util.Param;
import com.king.platform.net.http.util.UriUtil;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.*;

import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Supplier;

public class BuiltNettyClientRequest implements BuiltClientRequest, BuiltClientRequestWithBody {

	private final HttpClientCaller httpClientCaller;
	private final HttpVersion httpVersion;
	private final HttpMethod httpMethod;
	private final String uri;

	private final String defaultUserAgent;


	private final int idleTimeoutMillis;
	private final int totalRequestTimeoutMillis;

	private final boolean followRedirects;
	private final boolean acceptCompressedResponse;
	private final boolean keepAlive;
	private final boolean automaticallyDecompressResponse;

	private final RequestBodyBuilder requestBodyBuilder;
	private final String contentType;
	private final Charset bodyCharset;

	private final List queryParameters;
	private final List headerParameters;
	private final Executor callbackExecutor;
	private final Supplier> responseBodyConsumer;
	private final WebSocketConf webSocketConf;
	private final ServerInfoValidator serverInfoValidator;

	private HttpCallback httpCallback;
	private NioCallback nioCallback;
	private UploadCallback uploadCallback;

	private Supplier externalEventTriggerSupplier;

	private Supplier> httpCallbackSupplier;
	private Supplier nioCallbackSupplier;
	private Supplier uploadCallbackSupplier;

	private CustomCallbackSubscriber customCallbackSubscriber;


	public BuiltNettyClientRequest(HttpClientCaller httpClientCaller, HttpVersion httpVersion, HttpMethod httpMethod, String uri, String defaultUserAgent, int idleTimeoutMillis, int totalRequestTimeoutMillis, boolean followRedirects, boolean acceptCompressedResponse, boolean keepAlive, boolean automaticallyDecompressResponse, RequestBodyBuilder requestBodyBuilder, String contentType, Charset bodyCharset, List queryParameters, List headerParameters, Executor callbackExecutor, Supplier> responseBodyConsumer, WebSocketConf webSocketConf, ServerInfoValidator serverInfoValidator) {
		this.httpClientCaller = httpClientCaller;
		this.httpVersion = httpVersion;
		this.httpMethod = httpMethod;
		this.uri = uri;
		this.defaultUserAgent = defaultUserAgent;
		this.idleTimeoutMillis = idleTimeoutMillis;
		this.totalRequestTimeoutMillis = totalRequestTimeoutMillis;
		this.followRedirects = followRedirects;
		this.acceptCompressedResponse = acceptCompressedResponse;
		this.keepAlive = keepAlive;
		this.automaticallyDecompressResponse = automaticallyDecompressResponse;
		this.requestBodyBuilder = requestBodyBuilder;
		this.contentType = contentType;
		this.bodyCharset = bodyCharset;
		this.queryParameters = new ArrayList<>(queryParameters);
		this.headerParameters = new ArrayList<>(headerParameters);
		this.callbackExecutor = callbackExecutor;
		this.responseBodyConsumer = responseBodyConsumer;
		this.webSocketConf = webSocketConf;
		this.serverInfoValidator = serverInfoValidator;
	}


	@Override
	public BuiltClientRequest withHttpCallback(HttpCallback httpCallback) {
		if (httpCallbackSupplier != null) {
			throw new IllegalStateException("An Supplier has already been provided");
		}
		this.httpCallback = httpCallback;
		return this;
	}

	@Override
	public BuiltClientRequest withHttpCallback(Supplier> httpCallbackSupplier) {
		if (httpCallback != null) {
			throw new IllegalStateException("An HttpCallback has already been provided");
		}
		this.httpCallbackSupplier = httpCallbackSupplier;
		return this;
	}

	@Override
	public BuiltClientRequest withNioCallback(NioCallback nioCallback) {
		if (nioCallbackSupplier != null) {
			throw new IllegalStateException("An Supplier has already been provided");
		}

		this.nioCallback = nioCallback;
		return this;
	}

	@Override
	public BuiltClientRequest withNioCallback(Supplier nioCallbackSupplier) {
		if (nioCallback != null) {
			throw new IllegalStateException("An NioCallback has already been provided");
		}

		this.nioCallbackSupplier = nioCallbackSupplier;
		return this;
	}

	public BuiltClientRequest withExternalEventTrigger(Supplier externalEventTriggerSupplier) {
		this.externalEventTriggerSupplier = externalEventTriggerSupplier;
		return this;
	}


	@Override
	public BuiltClientRequestWithBody withUploadCallback(UploadCallback uploadCallback) {
		if (uploadCallbackSupplier != null) {
			throw new IllegalStateException("An UploadCallback supplier has already been provided");
		}
		this.uploadCallback = uploadCallback;
		return this;
	}

	@Override
	public BuiltClientRequestWithBody withUploadCallback(Supplier uploadCallbackSupplier) {
		if (uploadCallback != null) {
			throw new IllegalStateException("An UploadCallback has already been provided");
		}
		this.uploadCallbackSupplier = uploadCallbackSupplier;
		return this;
	}

	@Override
	public CompletableFuture> execute() {
		HttpCallback httpCallback = getHttpCallback();

		String completeUri = UriUtil.getUriWithParameters(uri, queryParameters);

		ServerInfo serverInfo = null;
		try {
			serverInfo = ServerInfo.buildFromUri(completeUri);
		} catch (URISyntaxException e) {
			return dispatchError(httpCallback, e);
		}

		if (!serverInfoValidator.isValid(serverInfo)) {
			return dispatchError(httpCallback, new KingHttpException("Invalid server url for this connection!"));
		}

		String relativePath = UriUtil.getRelativeUri(completeUri);


		DefaultHttpRequest defaultHttpRequest = new DefaultHttpRequest(httpVersion, httpMethod, relativePath);

		HttpBody httpBody = null;

		if (requestBodyBuilder != null) {
			httpBody = requestBodyBuilder.createHttpBody(contentType, bodyCharset);
		}

		NettyHttpClientRequest nettyHttpClientRequest = new NettyHttpClientRequest<>(serverInfo, defaultHttpRequest, httpBody);

		HttpHeaders headers = nettyHttpClientRequest.getNettyHeaders();

		for (Param headerParameter : headerParameters) {
			headers.add(headerParameter.getName(), headerParameter.getValue());
		}


		if (acceptCompressedResponse && !headers.contains(HttpHeaderNames.ACCEPT_ENCODING)) {
			headers.set(HttpHeaderNames.ACCEPT_ENCODING, HttpHeaderValues.GZIP + "," + HttpHeaderValues.DEFLATE);
		}

		if (httpBody != null && httpMethod.equals(HttpMethod.TRACE)) {
			return dispatchError(httpCallback, new IllegalStateException("Trace calls are not allowed to have post bodies!"));
		}

		if (httpBody != null) {
			if (httpBody.getContentLength() < 0) {
				headers.set(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
			} else {
				headers.set(HttpHeaderNames.CONTENT_LENGTH, String.valueOf(httpBody.getContentLength()));
			}

			String contentType = httpBody.getContentType();
			if (contentType != null) {
				Charset characterEncoding = httpBody.getCharacterEncoding();
				if (characterEncoding != null && !contentType.contains("charset=")) {
					contentType = contentType + ";charset=" + characterEncoding.name();
				}
				headers.set(HttpHeaderNames.CONTENT_TYPE, contentType);
			}

		}


		if (!headers.contains(HttpHeaderNames.ACCEPT)) {
			headers.set(HttpHeaderNames.ACCEPT, "*/*");
		}

		if (!headers.contains(HttpHeaderNames.USER_AGENT)) {
			headers.set(HttpHeaderNames.USER_AGENT, defaultUserAgent);
		}

		if (!serverInfo.isWebSocket()) {
			nettyHttpClientRequest.setKeepAlive(keepAlive);
		}

		return httpClientCaller.execute(httpMethod, nettyHttpClientRequest, httpCallback, getNioCallback(), getUploadCallback(), responseBodyConsumer.get(),
			callbackExecutor, getExternalEventTrigger(), customCallbackSubscriber, idleTimeoutMillis, totalRequestTimeoutMillis,
			followRedirects, keepAlive, automaticallyDecompressResponse, webSocketConf);
	}


	private NioCallback getNioCallback() {
		NioCallback nioCallback = this.nioCallback;
		if (nioCallbackSupplier != null) {
			nioCallback = nioCallbackSupplier.get();
		}
		return nioCallback;
	}

	private UploadCallback getUploadCallback() {
		UploadCallback uploadCallback = this.uploadCallback;
		if (uploadCallbackSupplier != null) {
			uploadCallback = uploadCallbackSupplier.get();
		}
		return uploadCallback;
	}

	private HttpCallback getHttpCallback() {
		HttpCallback httpCallback = this.httpCallback;
		if (httpCallbackSupplier != null) {
			httpCallback = httpCallbackSupplier.get();
		}
		return httpCallback;
	}

	private ExternalEventTrigger getExternalEventTrigger() {
		ExternalEventTrigger externalEventTrigger = null;
		if (externalEventTriggerSupplier != null) {
			externalEventTrigger = externalEventTriggerSupplier.get();
		}
		return externalEventTrigger;
	}

	private CompletableFuture> dispatchError(final HttpCallback httpCallback, final Exception e) {
		if (httpCallback != null) {
            callbackExecutor.execute(() -> httpCallback.onError(e));
        }

		return ResponseFuture.error(e);
	}

	public int getIdleTimeoutMillis() {
		return idleTimeoutMillis;
	}

	public int getTotalRequestTimeoutMillis() {
		return totalRequestTimeoutMillis;
	}

	public boolean isFollowRedirects() {
		return followRedirects;
	}

	public boolean isAcceptCompressedResponse() {
		return acceptCompressedResponse;
	}

	public boolean isKeepAlive() {
		return keepAlive;
	}


	public BuiltClientRequest withCustomCallbackSupplier(CustomCallbackSubscriber customCallbackSubscriber) {
		this.customCallbackSubscriber = customCallbackSubscriber;
		return this;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy