src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java
changeset 50681 4254bed3c09d
parent 49765 ee6f7a61f3a5
child 53521 41fa3e6f2785
child 56795 03ece2518428
equal deleted inserted replaced
50678:818a23db260c 50681:4254bed3c09d
    39 import java.util.Objects;
    39 import java.util.Objects;
    40 import java.util.Optional;
    40 import java.util.Optional;
    41 import java.net.http.HttpClient;
    41 import java.net.http.HttpClient;
    42 import java.net.http.HttpHeaders;
    42 import java.net.http.HttpHeaders;
    43 import java.net.http.HttpRequest;
    43 import java.net.http.HttpRequest;
    44 import jdk.internal.net.http.common.HttpHeadersImpl;
    44 import jdk.internal.net.http.common.HttpHeadersBuilder;
    45 import jdk.internal.net.http.common.Utils;
    45 import jdk.internal.net.http.common.Utils;
    46 import jdk.internal.net.http.websocket.WebSocketRequest;
    46 import jdk.internal.net.http.websocket.WebSocketRequest;
    47 
    47 
    48 import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
    48 import static jdk.internal.net.http.common.Utils.ALLOWED_HEADERS;
    49 
    49 
    50 class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
    50 public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
    51 
    51 
    52     private final HttpHeaders userHeaders;
    52     private final HttpHeaders userHeaders;
    53     private final HttpHeadersImpl systemHeaders;
    53     private final HttpHeadersBuilder systemHeadersBuilder;
    54     private final URI uri;
    54     private final URI uri;
    55     private volatile Proxy proxy; // ensure safe publishing
    55     private volatile Proxy proxy; // ensure safe publishing
    56     private final InetSocketAddress authority; // only used when URI not specified
    56     private final InetSocketAddress authority; // only used when URI not specified
    57     private final String method;
    57     private final String method;
    58     final BodyPublisher requestPublisher;
    58     final BodyPublisher requestPublisher;
    76      * Creates an HttpRequestImpl from the given builder.
    76      * Creates an HttpRequestImpl from the given builder.
    77      */
    77      */
    78     public HttpRequestImpl(HttpRequestBuilderImpl builder) {
    78     public HttpRequestImpl(HttpRequestBuilderImpl builder) {
    79         String method = builder.method();
    79         String method = builder.method();
    80         this.method = method == null ? "GET" : method;
    80         this.method = method == null ? "GET" : method;
    81         this.userHeaders = ImmutableHeaders.of(builder.headers().map(), ALLOWED_HEADERS);
    81         this.userHeaders = HttpHeaders.of(builder.headersBuilder().map(), ALLOWED_HEADERS);
    82         this.systemHeaders = new HttpHeadersImpl();
    82         this.systemHeadersBuilder = new HttpHeadersBuilder();
    83         this.uri = builder.uri();
    83         this.uri = builder.uri();
    84         assert uri != null;
    84         assert uri != null;
    85         this.proxy = null;
    85         this.proxy = null;
    86         this.expectContinue = builder.expectContinue();
    86         this.expectContinue = builder.expectContinue();
    87         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
    87         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
   104                     + "\"");
   104                     + "\"");
   105         URI requestURI = Objects.requireNonNull(request.uri(),
   105         URI requestURI = Objects.requireNonNull(request.uri(),
   106                 "uri must be non null");
   106                 "uri must be non null");
   107         Duration timeout = request.timeout().orElse(null);
   107         Duration timeout = request.timeout().orElse(null);
   108         this.method = method == null ? "GET" : method;
   108         this.method = method == null ? "GET" : method;
   109         this.userHeaders = ImmutableHeaders.validate(request.headers());
   109         this.userHeaders = HttpHeaders.of(request.headers().map(), Utils.VALIDATE_USER_HEADER);
   110         if (request instanceof HttpRequestImpl) {
   110         if (request instanceof HttpRequestImpl) {
   111             // all cases exception WebSocket should have a new system headers
   111             // all cases exception WebSocket should have a new system headers
   112             this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
   112             this.isWebSocket = ((HttpRequestImpl) request).isWebSocket;
   113             if (isWebSocket) {
   113             if (isWebSocket) {
   114                 this.systemHeaders = ((HttpRequestImpl) request).systemHeaders;
   114                 this.systemHeadersBuilder = ((HttpRequestImpl)request).systemHeadersBuilder;
   115             } else {
   115             } else {
   116                 this.systemHeaders = new HttpHeadersImpl();
   116                 this.systemHeadersBuilder = new HttpHeadersBuilder();
   117             }
   117             }
   118         } else {
   118         } else {
   119             HttpRequestBuilderImpl.checkURI(requestURI);
   119             HttpRequestBuilderImpl.checkURI(requestURI);
   120             checkTimeout(timeout);
   120             checkTimeout(timeout);
   121             this.systemHeaders = new HttpHeadersImpl();
   121             this.systemHeadersBuilder = new HttpHeadersBuilder();
   122         }
   122         }
   123         this.systemHeaders.setHeader("User-Agent", USER_AGENT);
   123         if (!userHeaders.firstValue("User-Agent").isPresent()) {
       
   124             this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
       
   125         }
   124         this.uri = requestURI;
   126         this.uri = requestURI;
   125         if (isWebSocket) {
   127         if (isWebSocket) {
   126             // WebSocket determines and sets the proxy itself
   128             // WebSocket determines and sets the proxy itself
   127             this.proxy = ((HttpRequestImpl) request).proxy;
   129             this.proxy = ((HttpRequestImpl) request).proxy;
   128         } else {
   130         } else {
   167                             HttpRequestImpl other) {
   169                             HttpRequestImpl other) {
   168         assert method == null || Utils.isValidName(method);
   170         assert method == null || Utils.isValidName(method);
   169         this.method = method == null? "GET" : method;
   171         this.method = method == null? "GET" : method;
   170         this.userHeaders = other.userHeaders;
   172         this.userHeaders = other.userHeaders;
   171         this.isWebSocket = other.isWebSocket;
   173         this.isWebSocket = other.isWebSocket;
   172         this.systemHeaders = new HttpHeadersImpl();
   174         this.systemHeadersBuilder = new HttpHeadersBuilder();
   173         this.systemHeaders.setHeader("User-Agent", USER_AGENT);
   175         if (!userHeaders.firstValue("User-Agent").isPresent()) {
       
   176             this.systemHeadersBuilder.setHeader("User-Agent", USER_AGENT);
       
   177         }
   174         this.uri = uri;
   178         this.uri = uri;
   175         this.proxy = other.proxy;
   179         this.proxy = other.proxy;
   176         this.expectContinue = other.expectContinue;
   180         this.expectContinue = other.expectContinue;
   177         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
   181         this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
   178         this.requestPublisher = other.requestPublisher;  // may be null
   182         this.requestPublisher = other.requestPublisher;  // may be null
   187         // TODO: isWebSocket flag is not specified, but the assumption is that
   191         // TODO: isWebSocket flag is not specified, but the assumption is that
   188         // such a request will never be made on a connection that will be returned
   192         // such a request will never be made on a connection that will be returned
   189         // to the connection pool (we might need to revisit this constructor later)
   193         // to the connection pool (we might need to revisit this constructor later)
   190         assert "CONNECT".equalsIgnoreCase(method);
   194         assert "CONNECT".equalsIgnoreCase(method);
   191         this.method = method;
   195         this.method = method;
   192         this.systemHeaders = new HttpHeadersImpl();
   196         this.systemHeadersBuilder = new HttpHeadersBuilder();
   193         this.userHeaders = ImmutableHeaders.of(headers);
   197         this.userHeaders = headers;
   194         this.uri = URI.create("socket://" + authority.getHostString() + ":"
   198         this.uri = URI.create("socket://" + authority.getHostString() + ":"
   195                               + Integer.toString(authority.getPort()) + "/");
   199                               + Integer.toString(authority.getPort()) + "/");
   196         this.proxy = null;
   200         this.proxy = null;
   197         this.requestPublisher = null;
   201         this.requestPublisher = null;
   198         this.authority = authority;
   202         this.authority = authority;
   216      * Creates a HttpRequestImpl from the given set of Headers and the associated
   220      * Creates a HttpRequestImpl from the given set of Headers and the associated
   217      * "parent" request. Fields not taken from the headers are taken from the
   221      * "parent" request. Fields not taken from the headers are taken from the
   218      * parent.
   222      * parent.
   219      */
   223      */
   220     static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
   224     static HttpRequestImpl createPushRequest(HttpRequestImpl parent,
   221                                              HttpHeadersImpl headers)
   225                                              HttpHeaders headers)
   222         throws IOException
   226         throws IOException
   223     {
   227     {
   224         return new HttpRequestImpl(parent, headers);
   228         return new HttpRequestImpl(parent, headers);
   225     }
   229     }
   226 
   230 
   227     // only used for push requests
   231     // only used for push requests
   228     private HttpRequestImpl(HttpRequestImpl parent, HttpHeadersImpl headers)
   232     private HttpRequestImpl(HttpRequestImpl parent, HttpHeaders headers)
   229         throws IOException
   233         throws IOException
   230     {
   234     {
   231         this.method = headers.firstValue(":method")
   235         this.method = headers.firstValue(":method")
   232                 .orElseThrow(() -> new IOException("No method in Push Promise"));
   236                 .orElseThrow(() -> new IOException("No method in Push Promise"));
   233         String path = headers.firstValue(":path")
   237         String path = headers.firstValue(":path")
   238                 .orElseThrow(() -> new IOException("No authority in Push Promise"));
   242                 .orElseThrow(() -> new IOException("No authority in Push Promise"));
   239         StringBuilder sb = new StringBuilder();
   243         StringBuilder sb = new StringBuilder();
   240         sb.append(scheme).append("://").append(authority).append(path);
   244         sb.append(scheme).append("://").append(authority).append(path);
   241         this.uri = URI.create(sb.toString());
   245         this.uri = URI.create(sb.toString());
   242         this.proxy = null;
   246         this.proxy = null;
   243         this.userHeaders = ImmutableHeaders.of(headers.map(), ALLOWED_HEADERS);
   247         this.userHeaders = HttpHeaders.of(headers.map(), ALLOWED_HEADERS);
   244         this.systemHeaders = parent.systemHeaders;
   248         this.systemHeadersBuilder = parent.systemHeadersBuilder;
   245         this.expectContinue = parent.expectContinue;
   249         this.expectContinue = parent.expectContinue;
   246         this.secure = parent.secure;
   250         this.secure = parent.secure;
   247         this.requestPublisher = parent.requestPublisher;
   251         this.requestPublisher = parent.requestPublisher;
   248         this.acc = parent.acc;
   252         this.acc = parent.acc;
   249         this.timeout = parent.timeout;
   253         this.timeout = parent.timeout;
   262     }
   266     }
   263 
   267 
   264     InetSocketAddress authority() { return authority; }
   268     InetSocketAddress authority() { return authority; }
   265 
   269 
   266     void setH2Upgrade(Http2ClientImpl h2client) {
   270     void setH2Upgrade(Http2ClientImpl h2client) {
   267         systemHeaders.setHeader("Connection", "Upgrade, HTTP2-Settings");
   271         systemHeadersBuilder.setHeader("Connection", "Upgrade, HTTP2-Settings");
   268         systemHeaders.setHeader("Upgrade", "h2c");
   272         systemHeadersBuilder.setHeader("Upgrade", "h2c");
   269         systemHeaders.setHeader("HTTP2-Settings", h2client.getSettingsString());
   273         systemHeadersBuilder.setHeader("HTTP2-Settings", h2client.getSettingsString());
   270     }
   274     }
   271 
   275 
   272     @Override
   276     @Override
   273     public boolean expectContinue() { return expectContinue; }
   277     public boolean expectContinue() { return expectContinue; }
   274 
   278 
   330         return timeout == null ? Optional.empty() : Optional.of(timeout);
   334         return timeout == null ? Optional.empty() : Optional.of(timeout);
   331     }
   335     }
   332 
   336 
   333     HttpHeaders getUserHeaders() { return userHeaders; }
   337     HttpHeaders getUserHeaders() { return userHeaders; }
   334 
   338 
   335     HttpHeadersImpl getSystemHeaders() { return systemHeaders; }
   339     HttpHeadersBuilder getSystemHeadersBuilder() { return systemHeadersBuilder; }
   336 
   340 
   337     @Override
   341     @Override
   338     public Optional<HttpClient.Version> version() { return version; }
   342     public Optional<HttpClient.Version> version() { return version; }
   339 
   343 
   340     void addSystemHeader(String name, String value) {
   344     void addSystemHeader(String name, String value) {
   341         systemHeaders.addHeader(name, value);
   345         systemHeadersBuilder.addHeader(name, value);
   342     }
   346     }
   343 
   347 
   344     @Override
   348     @Override
   345     public void setSystemHeader(String name, String value) {
   349     public void setSystemHeader(String name, String value) {
   346         systemHeaders.setHeader(name, value);
   350         systemHeadersBuilder.setHeader(name, value);
   347     }
   351     }
   348 
   352 
   349     InetSocketAddress getAddress() {
   353     InetSocketAddress getAddress() {
   350         URI uri = uri();
   354         URI uri = uri();
   351         if (uri == null) {
   355         if (uri == null) {