
io.vertx.ext.web.client.impl.HttpRequestImpl Maven / Gradle / Ivy
/*
* Copyright (c) 2011-2013 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.ext.web.client.impl;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.UnpooledByteBufAllocator;
import io.netty.handler.codec.http.DefaultFullHttpRequest;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.QueryStringEncoder;
import io.netty.handler.codec.http.multipart.HttpPostRequestEncoder;
import io.vertx.core.AsyncResult;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.core.VertxException;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.CaseInsensitiveHeaders;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;
import io.vertx.core.http.HttpHeaders;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.RequestOptions;
import io.vertx.core.json.Json;
import io.vertx.core.json.JsonObject;
import io.vertx.core.streams.Pump;
import io.vertx.core.streams.ReadStream;
import io.vertx.ext.web.client.HttpRequest;
import io.vertx.ext.web.client.HttpResponse;
import io.vertx.ext.web.client.WebClientOptions;
import io.vertx.ext.web.codec.BodyCodec;
import io.vertx.ext.web.codec.spi.BodyStream;
import java.util.Map;
/**
* @author Julien Viet
*/
class HttpRequestImpl implements HttpRequest {
private final HttpClient client;
private final WebClientOptions options;
private MultiMap params;
private HttpMethod method;
private int port;
private String host;
private String uri;
private MultiMap headers;
private long timeout = -1;
private BodyCodec codec;
private boolean followRedirects;
private boolean ssl;
HttpRequestImpl(HttpClient client, HttpMethod method, boolean ssl, int port, String host, String uri, BodyCodec codec, WebClientOptions options) {
this.client = client;
this.method = method;
this.codec = codec;
this.port = port;
this.host = host;
this.uri = uri;
this.ssl = ssl;
this.followRedirects = options.isFollowRedirects();
this.options = options;
if (options.isUserAgentEnabled()) {
headers = new CaseInsensitiveHeaders().add(HttpHeaders.USER_AGENT, options.getUserAgent());
}
}
private HttpRequestImpl(HttpRequestImpl other) {
this.client = other.client;
this.options = other.options;
this.method = other.method;
this.port = other.port;
this.host = other.host;
this.timeout = other.timeout;
this.uri = other.uri;
this.headers = other.headers != null ? new CaseInsensitiveHeaders().addAll(other.headers) : null;
this.params = other.params != null ? new CaseInsensitiveHeaders().addAll(other.params) : null;
this.codec = other.codec;
this.followRedirects = other.followRedirects;
}
@Override
public HttpRequest as(BodyCodec responseCodec) {
codec = (BodyCodec) responseCodec;
return (HttpRequest) this;
}
@Override
public HttpRequest method(HttpMethod value) {
method = value;
return this;
}
@Override
public HttpRequest port(int value) {
port = value;
return this;
}
@Override
public HttpRequest host(String value) {
host = value;
return this;
}
@Override
public HttpRequest uri(String value) {
params = null;
uri = value;
return this;
}
@Override
public HttpRequest putHeader(String name, String value) {
headers().set(name, value);
return this;
}
@Override
public MultiMap headers() {
if (headers == null) {
headers = new CaseInsensitiveHeaders();
}
return headers;
}
@Override
public HttpRequest ssl(boolean value) {
ssl = value;
return this;
}
@Override
public HttpRequest timeout(long value) {
timeout = value;
return this;
}
@Override
public HttpRequest addQueryParam(String paramName, String paramValue) {
queryParams().add(paramName, paramValue);
return this;
}
@Override
public HttpRequest setQueryParam(String paramName, String paramValue) {
queryParams().set(paramName, paramValue);
return this;
}
@Override
public HttpRequest followRedirects(boolean value) {
followRedirects = value;
return this;
}
@Override
public MultiMap queryParams() {
if (params == null) {
params = new CaseInsensitiveHeaders();
}
if (params.isEmpty()) {
int idx = uri.indexOf('?');
if (idx >= 0) {
QueryStringDecoder dec = new QueryStringDecoder(uri);
dec.parameters().forEach((name, value) -> params.add(name, value));
uri = uri.substring(0, idx);
}
}
return params;
}
@Override
public HttpRequest copy() {
return new HttpRequestImpl(this);
}
@Override
public void sendStream(ReadStream body, Handler>> handler) {
send(null, body, handler);
}
@Override
public void send(Handler>> handler) {
send(null, null, handler);
}
@Override
public void sendBuffer(Buffer body, Handler>> handler) {
send(null, body, handler);
}
@Override
public void sendJsonObject(JsonObject body, Handler>> handler) {
send("application/json", body,handler);
}
@Override
public void sendJson(Object body, Handler>> handler) {
send("application/json", body, handler);
}
@Override
public void sendForm(MultiMap body, Handler>> handler) {
send("application/x-www-form-urlencoded", body, handler);
}
private void send(String contentType, Object body, Handler>> handler) {
Future responseFuture = Future.future().setHandler(ar -> {
if (ar.succeeded()) {
HttpClientResponse resp = ar.result();
Future> fut = Future.future();
fut.setHandler(handler);
resp.exceptionHandler(err -> {
if (!fut.isComplete()) {
fut.fail(err);
}
});
resp.pause();
codec.create(ar2 -> {
resp.resume();
if (ar2.succeeded()) {
BodyStream stream = ar2.result();
stream.exceptionHandler(err -> {
if (!fut.isComplete()) {
fut.fail(err);
}
});
resp.endHandler(v -> {
if (!fut.isComplete()) {
stream.end();
if (stream.result().succeeded()) {
fut.complete(new HttpResponseImpl<>(resp, null, stream.result().result()));
} else {
fut.fail(stream.result().cause());
}
}
});
Pump responsePump = Pump.pump(resp, stream);
responsePump.start();
} else {
handler.handle(Future.failedFuture(ar2.cause()));
}
});
} else {
handler.handle(Future.failedFuture(ar.cause()));
}
});
HttpClientRequest req;
String requestURI;
if (params != null && params.size() > 0) {
QueryStringEncoder enc = new QueryStringEncoder(uri);
params.forEach(param -> {
enc.addParam(param.getKey(), param.getValue());
});
requestURI = enc.toString();
} else {
requestURI = uri;
}
if (ssl != options.isSsl()) {
req = client.request(method, new RequestOptions().setSsl(ssl).setHost(host).setPort(port).setURI(uri));
} else {
req = client.request(method, port, host, requestURI);
}
req.setFollowRedirects(followRedirects);
if (headers != null) {
req.headers().addAll(headers);
}
req.exceptionHandler(err -> {
if (!responseFuture.isComplete()) {
responseFuture.fail(err);
}
});
req.handler(resp -> {
if (!responseFuture.isComplete()) {
responseFuture.complete(resp);
}
});
if (timeout > 0) {
req.setTimeout(timeout);
}
if (body != null) {
if (contentType != null) {
String prev = req.headers().get(HttpHeaders.CONTENT_TYPE);
if (prev == null) {
req.putHeader(HttpHeaders.CONTENT_TYPE, contentType);
} else {
contentType = prev;
}
}
if (body instanceof ReadStream>) {
ReadStream stream = (ReadStream) body;
if (headers == null || !headers.contains(HttpHeaders.CONTENT_LENGTH)) {
req.setChunked(true);
}
Pump pump = Pump.pump(stream, req);
stream.exceptionHandler(err -> {
req.reset();
if (!responseFuture.isComplete()) {
responseFuture.fail(err);
}
});
stream.endHandler(v -> {
pump.stop();
req.end();
});
pump.start();
} else {
Buffer buffer;
if (body instanceof Buffer) {
buffer = (Buffer) body;
} else if (body instanceof MultiMap) {
try {
MultiMap attributes = (MultiMap) body;
boolean multipart = "multipart/form-data".equals(contentType);
DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, io.netty.handler.codec.http.HttpMethod.POST, "/");
HttpPostRequestEncoder encoder = new HttpPostRequestEncoder(request, multipart);
for (Map.Entry attribute : attributes) {
encoder.addBodyAttribute(attribute.getKey(), attribute.getValue());
}
encoder.finalizeRequest();
for (String headerName : request.headers().names()) {
req.putHeader(headerName, request.headers().get(headerName));
}
if (encoder.isChunked()) {
buffer = Buffer.buffer();
while (true) {
HttpContent chunk = encoder.readChunk(new UnpooledByteBufAllocator(false));
ByteBuf content = chunk.content();
if (content.readableBytes() == 0) {
break;
}
buffer.appendBuffer(Buffer.buffer(content));
}
} else {
ByteBuf content = request.content();
buffer = Buffer.buffer(content);
}
} catch (Exception e) {
throw new VertxException(e);
}
} else if (body instanceof JsonObject) {
buffer = Buffer.buffer(((JsonObject)body).encode());
} else {
buffer = Buffer.buffer(Json.encode(body));
}
req.end(buffer);
}
} else {
req.end();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy