Skip to content

Commit

Permalink
Use ClientRequestImpl for the server proxy request
Browse files Browse the repository at this point in the history
Signed-off-by: Jorge Bescos Gascon <[email protected]>
  • Loading branch information
jbescos committed Jul 3, 2023
1 parent 388ec8e commit b2b1085
Showing 1 changed file with 42 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.time.Duration;
import java.util.Collections;
import java.util.HexFormat;
import java.util.Optional;
import java.util.concurrent.LinkedBlockingDeque;
Expand All @@ -38,12 +38,16 @@
import io.helidon.common.buffers.BufferData;
import io.helidon.common.buffers.DataReader;
import io.helidon.common.buffers.DataWriter;
import io.helidon.common.http.Http.Header;
import io.helidon.common.http.Http.Method;
import io.helidon.common.http.Http.Status;
import io.helidon.common.http.WritableHeaders;
import io.helidon.common.socket.HelidonSocket;
import io.helidon.common.socket.PlainSocket;
import io.helidon.common.socket.SocketOptions;
import io.helidon.common.socket.SocketWriter;
import io.helidon.common.socket.TlsSocket;
import io.helidon.common.uri.UriQueryWriteable;
import io.helidon.nima.http.media.MediaContext;
import io.helidon.nima.webclient.ClientConnection;
import io.helidon.nima.webclient.Proxy;
import io.helidon.nima.webclient.Proxy.ProxyType;
Expand Down Expand Up @@ -136,41 +140,52 @@ private InetSocketAddress inetSocketAddress() {
}
}

private int connectToProxy(InetSocketAddress remoteAddress) throws IOException {
String hostPort = remoteAddress.getHostName() + ":" + remoteAddress.getPort();
String newLine = "\r\n";
HelidonSocket tempSocket = PlainSocket.client(socket, createChannelId(socket));
StringBuilder httpConnect = new StringBuilder();
httpConnect.append("CONNECT ").append(hostPort).append(" HTTP/1.1").append(newLine)
.append("Host: ").append(hostPort).append(newLine)
.append("Accept: */*").append(newLine).append(newLine);

DataWriter writer = SocketWriter.create(tempSocket);
BufferData data = BufferData.create(httpConnect.toString().getBytes(StandardCharsets.UTF_8));
writer.writeNow(data);
DataReader reader = new DataReader(tempSocket);
int statusCode = readStatusCode(reader);
return statusCode;
private Http1ClientConnection proxyConnection(InetSocketAddress proxyAddress) {
return new Http1ClientConnection(options, new ConnectionKey("http",
proxyAddress.getHostName(),
proxyAddress.getPort(),
null,
connectionKey.dnsResolver(),
connectionKey.dnsAddressLookup(),
null)).connect();
}

private int readStatusCode(DataReader reader) {
String[] firstLine = reader.readLine().split(" ");
return Integer.parseInt(firstLine[1]);
private int connectToProxy(InetSocketAddress remoteAddress, InetSocketAddress proxyAddress) {
String hostPort = remoteAddress.getHostName() + ":" + remoteAddress.getPort();
Http1ClientConnection proxyConnection = proxyConnection(proxyAddress);
UriHelper uriHelper = UriHelper.create();
uriHelper.scheme("http");
uriHelper.host(proxyAddress.getHostName());
uriHelper.port(proxyAddress.getPort());
Http1ClientConfig clientConfig = Http1ClientConfig.builder().mediaContext(MediaContext.create())
.socketOptions(options).dnsResolver(connectionKey.dnsResolver())
.dnsAddressLookup(connectionKey.dnsAddressLookup()).defaultHeaders(WritableHeaders.create()).build();
ClientRequestImpl httpClient = new ClientRequestImpl(clientConfig,
Method.CONNECT, uriHelper, UriQueryWriteable.create(), Collections.emptyMap());
httpClient.connection(proxyConnection);
httpClient.header(Header.HOST, hostPort);
httpClient.header(Header.ACCEPT, "*/*");
Http1ClientResponse response = httpClient.request();

// Re-use socket
this.socket = proxyConnection.socket;
// Note that Http1StatusParser fails parsing HTTP/1.0 and some proxies will return that.
return response.status().code();
}

private String createChannelId(Socket socket) {
return "0x" + HexFormat.of().toHexDigits(System.identityHashCode(socket));
}

Http1ClientConnection connect() {
StrategyConnection strategy;
try {
socket = new Socket();
socket.setSoTimeout((int) options.readTimeout().toMillis());
options.configureSocket(socket);
InetSocketAddress remoteAddress = inetSocketAddress();
StrategyConnection strategy = StrategyConnection.get(this, remoteAddress);
strategy = StrategyConnection.get(this, remoteAddress);
strategy.connect(this, remoteAddress);
channelId = createChannelId(socket);
} catch (IOException e) {
throw new UncheckedIOException("Could not connect to " + connectionKey.host() + ":" + connectionKey.port(), e);
}
Expand All @@ -181,7 +196,7 @@ Http1ClientConnection connect() {
socket.getLocalAddress(),
Thread.currentThread().getName()));
}

this.channelId = createChannelId(socket);
this.reader = new DataReader(helidonSocket);
this.writer = new DataWriter() {
@Override
Expand Down Expand Up @@ -312,9 +327,8 @@ protected void connect(Http1ClientConnection connection, InetSocketAddress remot
uri.scheme("http");
uri.host(remoteAddress.getHostName());
uri.port(remoteAddress.getPort());
connection.socket.connect(connection.connectionKey.proxy().address(uri).get(),
(int) connection.options.connectTimeout().toMillis());
int responseCode = connection.connectToProxy(remoteAddress);
InetSocketAddress proxyAddress = connection.connectionKey.proxy().address(uri).get();
int responseCode = connection.connectToProxy(remoteAddress, proxyAddress);
if (responseCode != Status.OK_200.code()) {
throw new IllegalStateException("Proxy sent wrong HTTP response code: " + responseCode);
}
Expand All @@ -328,9 +342,8 @@ protected void connect(Http1ClientConnection connection, InetSocketAddress remot
uri.scheme("http");
uri.host(remoteAddress.getHostName());
uri.port(remoteAddress.getPort());
connection.socket.connect(connection.connectionKey.proxy().address(uri).get(),
(int) connection.options.connectTimeout().toMillis());
int responseCode = connection.connectToProxy(remoteAddress);
InetSocketAddress proxyAddress = connection.connectionKey.proxy().address(uri).get();
int responseCode = connection.connectToProxy(remoteAddress, proxyAddress);
if (responseCode != Status.OK_200.code()) {
throw new IllegalStateException("Proxy sent wrong HTTP response code: " + responseCode);
}
Expand Down

0 comments on commit b2b1085

Please sign in to comment.