Search in sources :

Example 1 with ChunkedOutputFilter

use of com.koushikdutta.async.http.filter.ChunkedOutputFilter in project AndroidAsync by koush.

the class AsyncHttpServerResponseImpl method end.

@Override
public void end() {
    if (ended)
        return;
    ended = true;
    if (headWritten && mSink == null) {
        // end will be called again after finished.
        return;
    }
    if (!headWritten) {
        // end was called, and no head or body was yet written,
        // so strip the transfer encoding as that is superfluous.
        mRawHeaders.remove("Transfer-Encoding");
    }
    if (mSink instanceof ChunkedOutputFilter) {
        ((ChunkedOutputFilter) mSink).setMaxBuffer(Integer.MAX_VALUE);
        mSink.write(new ByteBufferList());
        onEnd();
    } else if (!headWritten) {
        if (!mRequest.getMethod().equalsIgnoreCase(AsyncHttpHead.METHOD))
            send("text/html", "");
        else {
            writeHead();
            onEnd();
        }
    } else {
        onEnd();
    }
}
Also used : ByteBufferList(com.koushikdutta.async.ByteBufferList) ChunkedOutputFilter(com.koushikdutta.async.http.filter.ChunkedOutputFilter)

Example 2 with ChunkedOutputFilter

use of com.koushikdutta.async.http.filter.ChunkedOutputFilter in project AndroidAsync by koush.

the class AsyncHttpServerResponseImpl method initFirstWrite.

void initFirstWrite() {
    if (headWritten)
        return;
    headWritten = true;
    final boolean isChunked;
    String currentEncoding = mRawHeaders.get("Transfer-Encoding");
    if ("".equals(currentEncoding))
        mRawHeaders.removeAll("Transfer-Encoding");
    boolean canUseChunked = ("Chunked".equalsIgnoreCase(currentEncoding) || currentEncoding == null) && !"close".equalsIgnoreCase(mRawHeaders.get("Connection"));
    if (mContentLength < 0) {
        String contentLength = mRawHeaders.get("Content-Length");
        if (!TextUtils.isEmpty(contentLength))
            mContentLength = Long.valueOf(contentLength);
    }
    if (mContentLength < 0 && canUseChunked) {
        mRawHeaders.set("Transfer-Encoding", "Chunked");
        isChunked = true;
    } else {
        isChunked = false;
    }
    String statusLine = String.format(Locale.ENGLISH, "%s %s %s", httpVersion, code, AsyncHttpServer.getResponseCodeDescription(code));
    String rh = mRawHeaders.toPrefixString(statusLine);
    Util.writeAll(mSocket, rh.getBytes(), ex -> {
        if (ex != null) {
            report(ex);
            return;
        }
        if (isChunked) {
            ChunkedOutputFilter chunked = new ChunkedOutputFilter(mSocket);
            chunked.setMaxBuffer(0);
            mSink = chunked;
        } else {
            mSink = mSocket;
        }
        mSink.setClosedCallback(closedCallback);
        closedCallback = null;
        mSink.setWriteableCallback(writable);
        writable = null;
        if (ended) {
            // the response ended while headers were written
            end();
            return;
        }
        getServer().post(() -> {
            WritableCallback wb = getWriteableCallback();
            if (wb != null)
                wb.onWriteable();
        });
    });
}
Also used : WritableCallback(com.koushikdutta.async.callback.WritableCallback) ChunkedOutputFilter(com.koushikdutta.async.http.filter.ChunkedOutputFilter)

Example 3 with ChunkedOutputFilter

use of com.koushikdutta.async.http.filter.ChunkedOutputFilter in project AndroidAsync by koush.

the class HttpTransportMiddleware method exchangeHeaders.

@Override
public boolean exchangeHeaders(final OnExchangeHeaderData data) {
    Protocol p = Protocol.get(data.protocol);
    if (p != null && p != Protocol.HTTP_1_0 && p != Protocol.HTTP_1_1)
        return super.exchangeHeaders(data);
    AsyncHttpRequest request = data.request;
    AsyncHttpRequestBody requestBody = data.request.getBody();
    if (requestBody != null) {
        if (requestBody.length() >= 0) {
            request.getHeaders().set("Content-Length", String.valueOf(requestBody.length()));
            data.response.sink(data.socket);
        } else if ("close".equals(request.getHeaders().get("Connection"))) {
            data.response.sink(data.socket);
        } else {
            request.getHeaders().set("Transfer-Encoding", "Chunked");
            data.response.sink(new ChunkedOutputFilter(data.socket));
        }
    }
    String rl = request.getRequestLine().toString();
    String rs = request.getHeaders().toPrefixString(rl);
    byte[] rsBytes = rs.getBytes();
    // try to get the request body in the same packet as the request headers... if it will fit
    // in the max MTU (1540 or whatever).
    final boolean waitForBody = requestBody != null && requestBody.length() >= 0 && requestBody.length() + rsBytes.length < 1024;
    final BufferedDataSink bsink;
    final DataSink headerSink;
    if (waitForBody) {
        // force buffering of headers
        bsink = new BufferedDataSink(data.response.sink());
        bsink.forceBuffering(true);
        data.response.sink(bsink);
        headerSink = bsink;
    } else {
        bsink = null;
        headerSink = data.socket;
    }
    request.logv("\n" + rs);
    final CompletedCallback sentCallback = data.sendHeadersCallback;
    Util.writeAll(headerSink, rsBytes, new CompletedCallback() {

        @Override
        public void onCompleted(Exception ex) {
            Util.end(sentCallback, ex);
            // flush headers and any request body that was written by the callback
            if (bsink != null) {
                bsink.forceBuffering(false);
                bsink.setMaxBuffer(0);
            }
        }
    });
    LineEmitter.StringCallback headerCallback = new LineEmitter.StringCallback() {

        Headers mRawHeaders = new Headers();

        String statusLine;

        @Override
        public void onStringAvailable(String s) {
            try {
                s = s.trim();
                if (statusLine == null) {
                    statusLine = s;
                } else if (!TextUtils.isEmpty(s)) {
                    mRawHeaders.addLine(s);
                } else {
                    String[] parts = statusLine.split(" ", 3);
                    if (parts.length < 2)
                        throw new Exception(new IOException("Not HTTP"));
                    data.response.headers(mRawHeaders);
                    String protocol = parts[0];
                    data.response.protocol(protocol);
                    data.response.code(Integer.parseInt(parts[1]));
                    data.response.message(parts.length == 3 ? parts[2] : "");
                    data.receiveHeadersCallback.onCompleted(null);
                    // socket may get detached after headers (websocket)
                    AsyncSocket socket = data.response.socket();
                    if (socket == null)
                        return;
                    DataEmitter emitter;
                    // return content length, etc, which will confuse the body decoder
                    if (!data.request.hasBody()) {
                        emitter = HttpUtil.EndEmitter.create(socket.getServer(), null);
                    } else if (responseIsEmpty(data.response.code())) {
                        emitter = HttpUtil.EndEmitter.create(socket.getServer(), null);
                    } else {
                        emitter = HttpUtil.getBodyDecoder(socket, Protocol.get(protocol), mRawHeaders, false);
                    }
                    data.response.emitter(emitter);
                }
            } catch (Exception ex) {
                data.receiveHeadersCallback.onCompleted(ex);
            }
        }
    };
    LineEmitter liner = new LineEmitter();
    data.socket.setDataCallback(liner);
    liner.setLineCallback(headerCallback);
    return true;
}
Also used : BufferedDataSink(com.koushikdutta.async.BufferedDataSink) DataSink(com.koushikdutta.async.DataSink) CompletedCallback(com.koushikdutta.async.callback.CompletedCallback) BufferedDataSink(com.koushikdutta.async.BufferedDataSink) IOException(java.io.IOException) ChunkedOutputFilter(com.koushikdutta.async.http.filter.ChunkedOutputFilter) IOException(java.io.IOException) AsyncSocket(com.koushikdutta.async.AsyncSocket) LineEmitter(com.koushikdutta.async.LineEmitter) DataEmitter(com.koushikdutta.async.DataEmitter) AsyncHttpRequestBody(com.koushikdutta.async.http.body.AsyncHttpRequestBody)

Aggregations

ChunkedOutputFilter (com.koushikdutta.async.http.filter.ChunkedOutputFilter)3 AsyncSocket (com.koushikdutta.async.AsyncSocket)1 BufferedDataSink (com.koushikdutta.async.BufferedDataSink)1 ByteBufferList (com.koushikdutta.async.ByteBufferList)1 DataEmitter (com.koushikdutta.async.DataEmitter)1 DataSink (com.koushikdutta.async.DataSink)1 LineEmitter (com.koushikdutta.async.LineEmitter)1 CompletedCallback (com.koushikdutta.async.callback.CompletedCallback)1 WritableCallback (com.koushikdutta.async.callback.WritableCallback)1 AsyncHttpRequestBody (com.koushikdutta.async.http.body.AsyncHttpRequestBody)1 IOException (java.io.IOException)1