diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java index 79c59629ba7..15cd719d983 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java @@ -391,26 +391,29 @@ public class HttpClient extends ContainerLifeCycle .idleTimeout(oldRequest.getIdleTimeout(), TimeUnit.MILLISECONDS) .timeout(oldRequest.getTimeout(), TimeUnit.MILLISECONDS) .followRedirects(oldRequest.isFollowRedirects()); - for (HttpField header : oldRequest.getHeaders()) + for (HttpField field : oldRequest.getHeaders()) { - // We have a new URI, so skip the host header if present - if (HttpHeader.HOST == header.getHeader()) + HttpHeader header = field.getHeader(); + // We have a new URI, so skip the host header if present. + if (HttpHeader.HOST == header) continue; - // Remove expectation headers - if (HttpHeader.EXPECT == header.getHeader()) + // Remove expectation headers. + if (HttpHeader.EXPECT == header) continue; - // Remove cookies - if (HttpHeader.COOKIE == header.getHeader()) + // Remove cookies. + if (HttpHeader.COOKIE == header) continue; - // Remove authorization headers - if (HttpHeader.AUTHORIZATION == header.getHeader() || - HttpHeader.PROXY_AUTHORIZATION == header.getHeader()) + // Remove authorization headers. + if (HttpHeader.AUTHORIZATION == header || + HttpHeader.PROXY_AUTHORIZATION == header) continue; - newRequest.header(header.getName(), header.getValue()); + String value = field.getValue(); + if (!newRequest.getHeaders().contains(header, value)) + newRequest.header(field.getName(), value); } return newRequest; } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java index 0e39d1e05ce..d2e26bdafd2 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpSender.java @@ -62,7 +62,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener private final AtomicReference requestState = new AtomicReference<>(RequestState.QUEUED); private final AtomicReference senderState = new AtomicReference<>(SenderState.IDLE); private final Callback commitCallback = new CommitCallback(); - private final Callback contentCallback = new ContentCallback(); + private final IteratingCallback contentCallback = new ContentCallback(); private final Callback lastCallback = new LastContentCallback(); private final HttpChannel channel; private volatile HttpContent content; @@ -100,14 +100,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener if (updateSenderState(current, newSenderState)) { LOG.debug("Deferred content available, {} -> {}", current, newSenderState); - // TODO should just call contentCallback.iterate() here. - HttpContent content = this.content; - if (content.advance()) - sendContent(exchange, content, contentCallback); // TODO old style usage! - else if (content.isConsumed()) - sendContent(exchange, content, lastCallback); - else - throw new IllegalStateException(); + contentCallback.iterate(); return; } break; @@ -456,25 +449,11 @@ public abstract class HttpSender implements AsyncContentProvider.Listener case WAITING: { // We received the 100 Continue, now send the content if any. - HttpContent content = this.content; - // TODO should just call contentCallback.iterate() here. - if (content.advance()) - { - // There is content to send. - if (!updateSenderState(current, SenderState.SENDING)) - throw illegalSenderState(current); - LOG.debug("Proceeding while waiting"); - sendContent(exchange, content, contentCallback); // TODO old style usage! - return; - } - else - { - // No content to send yet - it's deferred. - if (!updateSenderState(current, SenderState.IDLE)) - throw illegalSenderState(current); - LOG.debug("Proceeding deferred"); - return; - } + if (!updateSenderState(current, SenderState.SENDING)) + throw illegalSenderState(current); + LOG.debug("Proceeding while waiting"); + contentCallback.iterate(); + return; } default: { @@ -665,30 +644,8 @@ public abstract class HttpSender implements AsyncContentProvider.Listener { case SENDING: { - // TODO should just call contentCallback.iterate() here. - // We have content to send ? - if (content.advance()) - { - sendContent(exchange, content, contentCallback); // TODO old style usage! - return; - } - else - { - if (content.isConsumed()) - { - sendContent(exchange, content, lastCallback); - return; - } - else - { - if (updateSenderState(current, SenderState.IDLE)) - { - LOG.debug("Waiting for deferred content for {}", request); - return; - } - break; - } - } + contentCallback.iterate(); + return; } case SENDING_WITH_CONTENT: { @@ -745,59 +702,43 @@ public abstract class HttpSender implements AsyncContentProvider.Listener if (exchange == null) return Action.IDLE; - Request request = exchange.getRequest(); HttpContent content = HttpSender.this.content; - - ByteBuffer contentBuffer = content.getContent(); - if (contentBuffer != null) - { - if (!someToContent(request, contentBuffer)) - return Action.IDLE; - } - while (true) { boolean advanced = content.advance(); boolean consumed = content.isConsumed(); + if (LOG.isDebugEnabled()) + LOG.debug("Content {} consumed {} for {}", advanced, consumed, exchange.getRequest()); - SenderState current = senderState.get(); + if (advanced) + { + sendContent(exchange, content, this); + return Action.SCHEDULED; + } + + if (consumed) + { + sendContent(exchange, content, lastCallback); + return Action.IDLE; + } + + SenderState current = HttpSender.this.senderState.get(); switch (current) { case SENDING: { - if (advanced) + if (updateSenderState(current, SenderState.IDLE)) { - // There is more content to send - sendContent(exchange, content, this); - return Action.SCHEDULED; - } - else if (consumed) - { - sendContent(exchange, content, lastCallback); + if (LOG.isDebugEnabled()) + LOG.debug("Content is deferred for {}", exchange.getRequest()); return Action.IDLE; } - else - { - if (updateSenderState(current, SenderState.IDLE)) - { - LOG.debug("Waiting for deferred content for {}", request); - return Action.IDLE; - } - break; - } + break; } case SENDING_WITH_CONTENT: { - if (updateSenderState(current, SenderState.SENDING)) - { - LOG.debug("Deferred content available for {}", request); - if (advanced) - { - sendContent(exchange, content, this); - return Action.SCHEDULED; - } - } - throw illegalSenderState(current); + updateSenderState(current, SenderState.SENDING); + break; } default: { @@ -810,6 +751,8 @@ public abstract class HttpSender implements AsyncContentProvider.Listener @Override public void succeeded() { + ByteBuffer buffer = content.getContent(); + someToContent(getHttpExchange().getRequest(), buffer); content.succeeded(); super.succeeded(); }