jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java
author sgehwolf
Mon, 21 Mar 2016 11:24:09 +0100
changeset 37322 696304418137
parent 36131 379db4b2f95d
child 37720 45cd7cc65382
permissions -rw-r--r--
4858370: JDWP: Memory Leak: GlobalRefs never deleted when processing invokeMethod command Summary: Delete global references in invoker_completeInvokeRequest() Reviewed-by: sspitsyn
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
36131
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     1
/*
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     2
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     4
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    10
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    15
 * accompanied this code).
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    16
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    20
 *
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    23
 */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    24
package java.net.http;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    25
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    26
import java.io.IOException;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    27
import java.net.URI;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    28
import java.nio.ByteBuffer;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    29
import java.util.List;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    30
import java.util.Map;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    31
import java.util.Set;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    32
import java.util.function.LongConsumer;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    33
import static java.net.http.HttpClient.Version.HTTP_1_1;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    34
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    35
/**
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    36
 * Handles a HTTP/1.1 response in two blocking calls. readHeaders() and
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    37
 * readBody(). There can be more than one of these per Http exchange.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    38
 */
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    39
class Http1Response {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    40
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    41
    private ResponseContent content;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    42
    private final HttpRequestImpl request;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    43
    HttpResponseImpl response;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    44
    private final HttpConnection connection;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    45
    private ResponseHeaders headers;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    46
    private int responseCode;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    47
    private ByteBuffer buffer; // same buffer used for reading status line and headers
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    48
    private final Http1Exchange exchange;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    49
    private final boolean redirecting; // redirecting
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    50
    private boolean return2Cache; // return connection to cache when finished
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    51
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    52
    Http1Response(HttpConnection conn, Http1Exchange exchange) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    53
        this.request = exchange.request();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    54
        this.exchange = exchange;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    55
        this.connection = conn;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    56
        this.redirecting = false;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    57
        buffer = connection.getRemaining();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    58
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    59
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    60
    // called when the initial read should come from a buffer left
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    61
    // over from a previous response.
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    62
    void setBuffer(ByteBuffer buffer) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    63
        this.buffer = buffer;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    64
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    65
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    66
    @SuppressWarnings("unchecked")
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    67
    public void readHeaders() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    68
        String statusline = readStatusLine();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    69
        if (statusline == null) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    70
            if (Log.errors()) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    71
                Log.logError("Connection closed. Retry");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    72
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    73
            connection.close();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    74
            // connection was closed
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    75
            throw new IOException("Connection closed");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    76
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    77
        if (!statusline.startsWith("HTTP/1.")) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    78
            throw new IOException("Invalid status line: " + statusline);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    79
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    80
        char c = statusline.charAt(7);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    81
        responseCode = Integer.parseInt(statusline.substring(9, 12));
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    82
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    83
        headers = new ResponseHeaders(connection, buffer);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    84
        headers.initHeaders();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    85
        if (Log.headers()) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    86
            logHeaders(headers);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    87
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    88
        response = new HttpResponseImpl(responseCode,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    89
                                        exchange.exchange,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    90
                                        headers,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    91
                                        null,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    92
                                        connection.sslParameters(),
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    93
                                        HTTP_1_1,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    94
                                        connection);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    95
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    96
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    97
    private boolean finished;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    98
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
    99
    synchronized void completed() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   100
        finished = true;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   101
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   102
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   103
    synchronized boolean finished() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   104
        return finished;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   105
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   106
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   107
    // Blocking flow controller implementation. Only works when a
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   108
    // thread is dedicated to reading response body
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   109
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   110
    static class FlowController implements LongConsumer {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   111
        long window ;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   112
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   113
        @Override
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   114
        public synchronized void accept(long value) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   115
            window += value;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   116
            notifyAll();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   117
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   118
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   119
        public synchronized void request(long value) throws InterruptedException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   120
            while (window < value) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   121
                wait();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   122
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   123
            window -= value;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   124
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   125
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   126
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   127
    FlowController flowController;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   128
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   129
    int fixupContentLen(int clen) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   130
        if (request.method().equalsIgnoreCase("HEAD")) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   131
            return 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   132
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   133
        if (clen == -1) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   134
            if (headers.firstValue("Transfer-encoding").orElse("")
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   135
                       .equalsIgnoreCase("chunked")) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   136
                return -1;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   137
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   138
            return 0;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   139
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   140
        return clen;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   141
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   142
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   143
    private void returnBuffer(ByteBuffer buf) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   144
        // not currently used, but will be when we change SSL to use fixed
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   145
        // sized buffers and a single buffer pool for HttpClientImpl
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   146
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   147
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   148
    @SuppressWarnings("unchecked")
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   149
    public <T> T readBody(java.net.http.HttpResponse.BodyProcessor<T> p,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   150
                          boolean return2Cache)
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   151
        throws IOException
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   152
    {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   153
        T body = null; // TODO: check null case below
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   154
        this.return2Cache = return2Cache;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   155
        final java.net.http.HttpResponse.BodyProcessor<T> pusher = p;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   156
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   157
        int clen0 = headers.getContentLength();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   158
        final int clen = fixupContentLen(clen0);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   159
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   160
        flowController = new FlowController();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   161
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   162
        body = pusher.onResponseBodyStart(clen, headers, flowController);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   163
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   164
        ExecutorWrapper executor;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   165
        if (body == null) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   166
            executor = ExecutorWrapper.callingThread();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   167
        } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   168
            executor = request.client().executorWrapper();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   169
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   170
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   171
        final ResponseHeaders h = headers;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   172
        if (body == null) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   173
            content = new ResponseContent(connection,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   174
                                          clen,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   175
                                          h,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   176
                                          pusher,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   177
                                          flowController);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   178
            content.pushBody(headers.getResidue());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   179
            body = pusher.onResponseComplete();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   180
            completed();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   181
            onFinished();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   182
            return body;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   183
        } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   184
            executor.execute(() -> {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   185
                    try {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   186
                        content = new ResponseContent(connection,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   187
                                                      clen,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   188
                                                      h,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   189
                                                      pusher,
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   190
                                                      flowController);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   191
                        content.pushBody(headers.getResidue());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   192
                        pusher.onResponseComplete();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   193
                        completed();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   194
                        onFinished();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   195
                    } catch (Throwable e) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   196
                        pusher.onResponseError(e);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   197
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   198
                },
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   199
                () -> response.getAccessControlContext());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   200
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   201
        return body;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   202
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   203
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   204
    private void onFinished() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   205
        connection.buffer = content.getResidue();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   206
        if (return2Cache) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   207
            connection.returnToCache(headers);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   208
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   209
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   210
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   211
    private void logHeaders(ResponseHeaders headers) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   212
        Map<String, List<String>> h = headers.mapInternal();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   213
        Set<String> keys = h.keySet();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   214
        Set<Map.Entry<String, List<String>>> entries = h.entrySet();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   215
        for (Map.Entry<String, List<String>> entry : entries) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   216
            String key = entry.getKey();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   217
            StringBuilder sb = new StringBuilder();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   218
            sb.append(key).append(": ");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   219
            List<String> values = entry.getValue();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   220
            if (values != null) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   221
                for (String value : values) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   222
                    sb.append(value).append(' ');
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   223
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   224
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   225
            Log.logHeaders(sb.toString());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   226
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   227
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   228
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   229
    HttpResponseImpl response() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   230
        return response;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   231
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   232
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   233
    boolean redirecting() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   234
        return redirecting;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   235
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   236
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   237
    HttpHeaders responseHeaders() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   238
        return headers;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   239
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   240
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   241
    int responseCode() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   242
        return responseCode;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   243
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   244
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   245
    static final char CR = '\r';
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   246
    static final char LF = '\n';
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   247
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   248
    private ByteBuffer getBuffer() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   249
        if (buffer == null || !buffer.hasRemaining()) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   250
            buffer = connection.read();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   251
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   252
        return buffer;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   253
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   254
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   255
    ByteBuffer buffer() {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   256
        return buffer;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   257
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   258
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   259
    String readStatusLine() throws IOException {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   260
        boolean cr = false;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   261
        StringBuilder statusLine = new StringBuilder(128);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   262
        ByteBuffer b;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   263
        while ((b = getBuffer()) != null) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   264
            byte[] buf = b.array();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   265
            int offset = b.position();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   266
            int len = b.limit() - offset;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   267
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   268
            for (int i = 0; i < len; i++) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   269
                char c = (char) buf[i+offset];
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   270
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   271
                if (cr) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   272
                    if (c == LF) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   273
                        b.position(i + 1 + offset);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   274
                        return statusLine.toString();
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   275
                    } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   276
                        throw new IOException("invalid status line");
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   277
                    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   278
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   279
                if (c == CR) {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   280
                    cr = true;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   281
                } else {
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   282
                    statusLine.append(c);
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   283
                }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   284
            }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   285
            // unlikely, but possible, that multiple reads required
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   286
            b.position(b.limit());
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   287
        }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   288
        return null;
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   289
    }
379db4b2f95d 8087112: HTTP API and HTTP/1.1 implementation
michaelm
parents:
diff changeset
   290
}