jodd-http/src/main/java/jodd/http/HttpBrowser.java
public HttpResponse sendRequest(HttpRequest httpRequest) {
		elapsedTime = System.currentTimeMillis();

		// send request

		httpRequest.followRedirects(false);

		while (true) {
			this.httpRequest = httpRequest;
			HttpResponse previousResponse = this.httpResponse;
			this.httpResponse = null;

			addDefaultHeaders(httpRequest);
			addCookies(httpRequest);

			// send request
			if (catchTransportExceptions) {
				try {
					this.httpResponse = _sendRequest(httpRequest, previousResponse);
				}
				catch (HttpException httpException) {
					httpResponse = new HttpResponse();
					httpResponse.assignHttpRequest(httpRequest);
					httpResponse.statusCode(503);
					httpResponse.statusPhrase("Service unavailable. " + ExceptionUtil.message(httpException));
				}
			}
			else {
				this.httpResponse =_sendRequest(httpRequest, previousResponse);
			}

			readCookies(httpResponse);

			int statusCode = httpResponse.statusCode();

			// 301: moved permanently
			if (statusCode == 301) {
				String newPath = httpResponse.location();

				if (newPath == null) {
					break;
				}

				httpRequest = HttpRequest.get(newPath);
				continue;
			}

			// 302: redirect, 303: see other
			if (statusCode == 302 || statusCode == 303) {
				String newPath = httpResponse.location();

				if (newPath == null) {
					break;
				}

				httpRequest = HttpRequest.get(newPath);
				continue;
			}

			// 307: temporary redirect, 308: permanent redirect
			if (statusCode == 307 || statusCode == 308) {
				String newPath = httpResponse.location();

				if (newPath == null) {
					break;
				}

				String originalMethod = httpRequest.method();
				httpRequest = new HttpRequest()
						.method(originalMethod)
						.set(newPath);
				continue;
			}

			break;
		}

		elapsedTime = System.currentTimeMillis() - elapsedTime;

		return this.httpResponse;
	}
public HttpResponse sendRequest(HttpRequest httpRequest) {
		elapsedTime = System.currentTimeMillis();

		// send request

		httpRequest.followRedirects(false);

		while (true) {
			this.httpRequest = httpRequest;
			HttpResponse previousResponse = this.httpResponse;
			this.httpResponse = null;

			addDefaultHeaders(httpRequest);
			addCookies(httpRequest);

			// send request
			if (catchTransportExceptions) {
				try {
					this.httpResponse = _sendRequest(httpRequest, previousResponse);
				}
				catch (HttpException httpException) {
					httpResponse = new HttpResponse();
					httpResponse.assignHttpRequest(httpRequest);
					httpResponse.statusCode(503);
					httpResponse.statusPhrase("Service unavailable. " + ExceptionUtil.message(httpException));
				}
			}
			else {
				this.httpResponse =_sendRequest(httpRequest, previousResponse);
			}

			readCookies(httpResponse);

			int statusCode = httpResponse.statusCode();

			// 301: moved permanently
			if (statusCode == 301) {
				String newPath = httpResponse.location();

				if (newPath == null) {
					break;
				}

				httpRequest = HttpRequest.get(newPath);
				continue;
			}

			// 302: redirect, 303: see other
			if (statusCode == 302 || statusCode == 303) {
				String newPath = httpResponse.location();

				if (newPath == null) {
					break;
				}

				httpRequest = HttpRequest.get(newPath);
				continue;
			}

			// 307: temporary redirect, 308: permanent redirect
			if (statusCode == 307 || statusCode == 308) {
				String newPath = httpResponse.location();

				if (newPath == null) {
					break;
				}

				String originalMethod = httpRequest.method();
				httpRequest = new HttpRequest()
						.method(originalMethod)
						.set(newPath);
				continue;
			}

			break;
		}

		elapsedTime = System.currentTimeMillis() - elapsedTime;

		return this.httpResponse;
	}
Sends new request as a browser. Before sending,
all browser cookies are added to the request.
After sending, the cookies are read from the response.
Moreover, status codes 301 and 302 are automatically
handled. Returns very last response.