
io.jsync.http.impl.DefaultHttpClientResponse Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jsync.io Show documentation
Show all versions of jsync.io Show documentation
jsync.io is a non-blocking, event-driven networking framework for Java
/*
* Copyright (c) 2011-2013 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.jsync.http.impl;
import io.jsync.Async;
import io.jsync.Handler;
import io.jsync.MultiMap;
import io.jsync.VoidHandler;
import io.jsync.buffer.Buffer;
import io.jsync.http.HttpClientResponse;
import io.jsync.net.NetSocket;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.LastHttpContent;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
/**
* @author Tim Fox
*/
public class DefaultHttpClientResponse implements HttpClientResponse {
private final int statusCode;
private final String statusMessage;
private final DefaultHttpClientRequest request;
private final Async async;
private final ClientConnection conn;
private final HttpResponse response;
private Handler dataHandler;
private Handler endHandler;
private Handler exceptionHandler;
private LastHttpContent trailer;
private boolean paused;
private Queue pausedChunks;
private boolean hasPausedEnd;
private LastHttpContent pausedTrailer;
private NetSocket netSocket;
// Cache these for performance
private MultiMap headers;
private MultiMap trailers;
private List cookies;
DefaultHttpClientResponse(Async async, DefaultHttpClientRequest request, ClientConnection conn, HttpResponse response) {
this.async = async;
this.statusCode = response.getStatus().code();
this.statusMessage = response.getStatus().reasonPhrase();
this.request = request;
this.conn = conn;
this.response = response;
}
@Override
public int statusCode() {
return statusCode;
}
@Override
public String statusMessage() {
return statusMessage;
}
@Override
public MultiMap headers() {
if (headers == null) {
headers = new HttpHeadersAdapter(response.headers());
}
return headers;
}
@Override
public MultiMap trailers() {
if (trailers == null) {
trailers = new HttpHeadersAdapter(new DefaultHttpHeaders());
}
return trailers;
}
@Override
public List cookies() {
if (cookies == null) {
cookies = new ArrayList<>();
cookies.addAll(response.headers().getAll(io.jsync.http.HttpHeaders.SET_COOKIE));
if (trailer != null) {
cookies.addAll(trailer.trailingHeaders().getAll(io.jsync.http.HttpHeaders.SET_COOKIE));
}
}
return cookies;
}
@Override
public HttpClientResponse dataHandler(Handler dataHandler) {
this.dataHandler = dataHandler;
return this;
}
@Override
public HttpClientResponse endHandler(Handler endHandler) {
this.endHandler = endHandler;
return this;
}
@Override
public HttpClientResponse exceptionHandler(Handler exceptionHandler) {
this.exceptionHandler = exceptionHandler;
return this;
}
@Override
public HttpClientResponse pause() {
paused = true;
conn.doPause();
return this;
}
@Override
public HttpClientResponse resume() {
paused = false;
doResume();
conn.doResume();
return this;
}
@Override
public HttpClientResponse bodyHandler(final Handler bodyHandler) {
final BodyHandler handler = new BodyHandler();
dataHandler(handler);
endHandler(new VoidHandler() {
public void handle() {
handler.notifyHandler(bodyHandler);
}
});
return this;
}
private void doResume() {
if (pausedChunks != null) {
Buffer chunk;
while ((chunk = pausedChunks.poll()) != null) {
final Buffer theChunk = chunk;
async.runOnContext(new VoidHandler() {
@Override
protected void handle() {
handleChunk(theChunk);
}
});
}
}
if (hasPausedEnd) {
final LastHttpContent theTrailer = pausedTrailer;
async.runOnContext(new VoidHandler() {
@Override
protected void handle() {
handleEnd(theTrailer);
}
});
hasPausedEnd = false;
pausedTrailer = null;
}
}
void handleChunk(Buffer data) {
if (paused) {
if (pausedChunks == null) {
pausedChunks = new ArrayDeque<>();
}
pausedChunks.add(data);
} else {
request.dataReceived();
if (dataHandler != null) {
dataHandler.handle(data);
}
}
}
void handleEnd(LastHttpContent trailer) {
if (paused) {
hasPausedEnd = true;
pausedTrailer = trailer;
} else {
this.trailer = trailer;
trailers = new HttpHeadersAdapter(trailer.trailingHeaders());
if (endHandler != null) {
endHandler.handle(null);
}
}
}
void handleException(Throwable e) {
if (exceptionHandler != null) {
exceptionHandler.handle(e);
}
}
@Override
public NetSocket netSocket() {
if (netSocket == null) {
netSocket = conn.createNetSocket();
}
return netSocket;
}
private final class BodyHandler implements Handler {
private Buffer body;
@Override
public void handle(Buffer event) {
body().appendBuffer(event);
}
private Buffer body() {
if (body == null) {
body = new Buffer();
}
return body;
}
void notifyHandler(Handler bodyHandler) {
bodyHandler.handle(body());
// reset body so it can get GC'ed
body = null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy