Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

okhttp: make okhttp dependencies compile only #8971

Merged
merged 4 commits into from Mar 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion interop-testing/build.gradle
Expand Up @@ -46,7 +46,8 @@ dependencies {
testImplementation project(':grpc-context').sourceSets.test.output,
project(':grpc-api').sourceSets.test.output,
project(':grpc-core').sourceSets.test.output,
libraries.mockito
libraries.mockito,
libraries.okhttp
alpnagent libraries.jetty_alpn_agent
}

Expand Down
8 changes: 5 additions & 3 deletions okhttp/build.gradle
Expand Up @@ -11,16 +11,18 @@ description = "gRPC: OkHttp"
evaluationDependsOn(project(':grpc-core').path)

dependencies {
api project(':grpc-core'),
libraries.okhttp
api project(':grpc-core')
implementation libraries.okio,
libraries.guava,
libraries.perfmark
// Make okhttp dependencies compile only
compileOnly libraries.okhttp
// Tests depend on base class defined by core module.
testImplementation project(':grpc-core').sourceSets.test.output,
project(':grpc-api').sourceSets.test.output,
project(':grpc-testing'),
project(':grpc-netty')
project(':grpc-netty'),
libraries.okhttp
signature "org.codehaus.mojo.signature:java17:1.0@signature"
signature "net.sf.androidscents.signature:android-api-level-14:4.0_r4@signature"
}
Expand Down
11 changes: 6 additions & 5 deletions okhttp/src/main/java/io/grpc/okhttp/OkHttpClientTransport.java
Expand Up @@ -28,10 +28,6 @@
import com.google.common.base.Supplier;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
import com.squareup.okhttp.Credentials;
import com.squareup.okhttp.HttpUrl;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.internal.http.StatusLine;
import io.grpc.Attributes;
import io.grpc.CallOptions;
import io.grpc.ClientStreamTracer;
Expand Down Expand Up @@ -61,6 +57,8 @@
import io.grpc.internal.TransportTracer;
import io.grpc.okhttp.ExceptionHandlingFrameWriter.TransportExceptionHandler;
import io.grpc.okhttp.internal.ConnectionSpec;
import io.grpc.okhttp.internal.Credentials;
import io.grpc.okhttp.internal.StatusLine;
import io.grpc.okhttp.internal.framed.ErrorCode;
import io.grpc.okhttp.internal.framed.FrameReader;
import io.grpc.okhttp.internal.framed.FrameWriter;
Expand All @@ -69,6 +67,8 @@
import io.grpc.okhttp.internal.framed.Http2;
import io.grpc.okhttp.internal.framed.Settings;
import io.grpc.okhttp.internal.framed.Variant;
import io.grpc.okhttp.internal.proxy.HttpUrl;
import io.grpc.okhttp.internal.proxy.Request;
import io.perfmark.PerfMark;
import java.io.EOFException;
import java.io.IOException;
Expand Down Expand Up @@ -709,12 +709,13 @@ private Socket createHttpProxySocket(InetSocketAddress address, InetSocketAddres
}

private Request createHttpProxyRequest(InetSocketAddress address, String proxyUsername,
String proxyPassword) {
String proxyPassword) {
HttpUrl tunnelUrl = new HttpUrl.Builder()
.scheme("https")
.host(address.getHostName())
.port(address.getPort())
.build();

Request.Builder request = new Request.Builder()
.url(tunnelUrl)
.header("Host", tunnelUrl.host() + ":" + tunnelUrl.port())
Expand Down
@@ -0,0 +1,40 @@
/*
* Copyright (C) 2014 Square, Inc.
*
* 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.
*/
/*
* Forked from OkHttp 2.7.0
*/
package io.grpc.okhttp.internal;

import java.io.UnsupportedEncodingException;
import okio.ByteString;

/** Factory for HTTP authorization credentials. */
public final class Credentials {
private Credentials() {
}

/** Returns an auth credential for the Basic scheme. */
public static String basic(String userName, String password) {
try {
String usernameAndPassword = userName + ":" + password;
byte[] bytes = usernameAndPassword.getBytes("ISO-8859-1");
String encoded = ByteString.of(bytes).base64();
return "Basic " + encoded;
} catch (UnsupportedEncodingException e) {
throw new AssertionError();
}
}
}
@@ -0,0 +1,152 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/*
* Forked from OkHttp 2.7.0 com.squareup.okhttp.Headers
*/
package io.grpc.okhttp.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* The header fields of a single HTTP message. Values are uninterpreted strings;
*
* <p>This class trims whitespace from values. It never returns values with
* leading or trailing whitespace.
*
* <p>Instances of this class are immutable. Use {@link Builder} to create
* instances.
*/
public final class Headers {
private final String[] namesAndValues;

private Headers(Builder builder) {
this.namesAndValues = builder.namesAndValues.toArray(new String[builder.namesAndValues.size()]);
}

/** Returns the last value corresponding to the specified field, or null. */
public String get(String name) {
return get(namesAndValues, name);
}

/** Returns the number of field values. */
public int size() {
return namesAndValues.length / 2;
}

/** Returns the field at {@code position} or null if that is out of range. */
public String name(int index) {
int nameIndex = index * 2;
if (nameIndex < 0 || nameIndex >= namesAndValues.length) {
return null;
}
return namesAndValues[nameIndex];
}

/** Returns the value at {@code index} or null if that is out of range. */
public String value(int index) {
int valueIndex = index * 2 + 1;
if (valueIndex < 0 || valueIndex >= namesAndValues.length) {
return null;
}
return namesAndValues[valueIndex];
}

public Builder newBuilder() {
Builder result = new Builder();
Collections.addAll(result.namesAndValues, namesAndValues);
return result;
}

@Override public String toString() {
StringBuilder result = new StringBuilder();
for (int i = 0, size = size(); i < size; i++) {
result.append(name(i)).append(": ").append(value(i)).append("\n");
}
return result.toString();
}

private static String get(String[] namesAndValues, String name) {
for (int i = namesAndValues.length - 2; i >= 0; i -= 2) {
if (name.equalsIgnoreCase(namesAndValues[i])) {
return namesAndValues[i + 1];
}
}
return null;
}

public static final class Builder {
private final List<String> namesAndValues = new ArrayList<>(20);

/**
* Add a field with the specified value without any validation. Only
* appropriate for headers from the remote peer or cache.
*/
Builder addLenient(String name, String value) {
namesAndValues.add(name);
namesAndValues.add(value.trim());
return this;
}

public Builder removeAll(String name) {
for (int i = 0; i < namesAndValues.size(); i += 2) {
if (name.equalsIgnoreCase(namesAndValues.get(i))) {
namesAndValues.remove(i); // name
namesAndValues.remove(i); // value
i -= 2;
}
}
return this;
}

/**
* Set a field with the specified value. If the field is not found, it is
* added. If the field is found, the existing values are replaced.
*/
public Builder set(String name, String value) {
checkNameAndValue(name, value);
removeAll(name);
addLenient(name, value);
return this;
}

private void checkNameAndValue(String name, String value) {
if (name == null) throw new IllegalArgumentException("name == null");
if (name.isEmpty()) throw new IllegalArgumentException("name is empty");
for (int i = 0, length = name.length(); i < length; i++) {
char c = name.charAt(i);
if (c <= '\u001f' || c >= '\u007f') {
throw new IllegalArgumentException(String.format(
"Unexpected char %#04x at %d in header name: %s", (int) c, i, name));
}
}
if (value == null) throw new IllegalArgumentException("value == null");
for (int i = 0, length = value.length(); i < length; i++) {
char c = value.charAt(i);
if (c <= '\u001f' || c >= '\u007f') {
throw new IllegalArgumentException(String.format(
"Unexpected char %#04x at %d in header value: %s", (int) c, i, value));
}
}
}

public Headers build() {
return new Headers(this);
}
}
}
@@ -0,0 +1,87 @@
/*
* Forked from OkHttp 2.7.0
*/
package io.grpc.okhttp.internal;

import java.io.IOException;
import java.net.ProtocolException;

/** An HTTP response status line like "HTTP/1.1 200 OK". */
public final class StatusLine {
/** Numeric status code, 307: Temporary Redirect. */
public static final int HTTP_TEMP_REDIRECT = 307;
public static final int HTTP_PERM_REDIRECT = 308;
public static final int HTTP_CONTINUE = 100;

public final Protocol protocol;
public final int code;
public final String message;

public StatusLine(Protocol protocol, int code, String message) {
this.protocol = protocol;
this.code = code;
this.message = message;
}

public static StatusLine parse(String statusLine) throws IOException {
// H T T P / 1 . 1 2 0 0 T e m p o r a r y R e d i r e c t
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0

// Parse protocol like "HTTP/1.1" followed by a space.
int codeStart;
Protocol protocol;
if (statusLine.startsWith("HTTP/1.")) {
if (statusLine.length() < 9 || statusLine.charAt(8) != ' ') {
throw new ProtocolException("Unexpected status line: " + statusLine);
}
int httpMinorVersion = statusLine.charAt(7) - '0';
codeStart = 9;
if (httpMinorVersion == 0) {
protocol = Protocol.HTTP_1_0;
} else if (httpMinorVersion == 1) {
protocol = Protocol.HTTP_1_1;
} else {
throw new ProtocolException("Unexpected status line: " + statusLine);
}
} else if (statusLine.startsWith("ICY ")) {
// Shoutcast uses ICY instead of "HTTP/1.0".
protocol = Protocol.HTTP_1_0;
codeStart = 4;
} else {
throw new ProtocolException("Unexpected status line: " + statusLine);
}

// Parse response code like "200". Always 3 digits.
if (statusLine.length() < codeStart + 3) {
throw new ProtocolException("Unexpected status line: " + statusLine);
}
int code;
try {
code = Integer.parseInt(statusLine.substring(codeStart, codeStart + 3));
} catch (NumberFormatException e) {
throw new ProtocolException("Unexpected status line: " + statusLine);
}

// Parse an optional response message like "OK" or "Not Modified". If it
// exists, it is separated from the response code by a space.
String message = "";
if (statusLine.length() > codeStart + 3) {
if (statusLine.charAt(codeStart + 3) != ' ') {
throw new ProtocolException("Unexpected status line: " + statusLine);
}
message = statusLine.substring(codeStart + 4);
}

return new StatusLine(protocol, code, message);
}

@Override public String toString() {
StringBuilder result = new StringBuilder();
result.append(protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1");
result.append(' ').append(code);
if (message != null) {
result.append(' ').append(message);
}
return result.toString();
}
}