Hello,
My plugin needs to return a 401 HTTP response code at times.
So what I do today is using the channel and send a response:
https://github.com/sscarduzio/elasticsearch-readonlyrest-plugin/blob/master/src/main/java/org/elasticsearch/plugin/readonlyrest/IndexLevelActionFilter.java#L156
So this is what makes the netty thread hang:
Client sends a HTTP request with Connection:Keep-Alive
I respond 401 (controller is closed, netty channel is not)
Client continues in the same connection with a new request
My plugin never get called again (because rest controller was closed, I guess)
See the snoop from Wireshark:
Digging on ES code, I noticed there's no keep alive check here when we close the controller,
https://github.com/elastic/elasticsearch/blob/master/core/src/main/java/org/elasticsearch/rest/RestController.java#L401
But you do correctly check if the header is set when you go about sending the response at the channel level
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.http.netty4;
import io.netty.channel.Channel;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.concurrent.CompletableContext;
import org.elasticsearch.http.HttpChannel;
import org.elasticsearch.http.HttpResponse;
import org.elasticsearch.transport.netty4.Netty4TcpChannel;
import java.net.InetSocketAddress;
public class Netty4HttpChannel implements HttpChannel {
private final Channel channel;
private final CompletableContext<Void> closeContext = new CompletableContext<>();
Netty4HttpChannel(Channel channel) {
this.channel = channel;
Netty4TcpChannel.addListener(this.channel.closeFuture(), closeContext);
}
@Override
public void sendResponse(HttpResponse response, ActionListener<Void> listener) {
channel.writeAndFlush(response, Netty4TcpChannel.addPromise(listener, channel));
}
@Override
public InetSocketAddress getLocalAddress() {
return (InetSocketAddress) channel.localAddress();
}
@Override
public InetSocketAddress getRemoteAddress() {
return (InetSocketAddress) channel.remoteAddress();
}
@Override
public void addCloseListener(ActionListener<Void> listener) {
closeContext.addListener(ActionListener.toBiConsumer(listener));
}
@Override
public boolean isOpen() {
return channel.isOpen();
}
@Override
public void close() {
channel.close();
}
public Channel getNettyChannel() {
return channel;
}
@Override
public String toString() {
return "Netty4HttpChannel{" +
"localAddress=" + getLocalAddress() +
", remoteAddress=" + getRemoteAddress() +
'}';
}
}
Is this a bug on your side or should I send a 401 response differently from my plugin?
jasontedor
(Jason Tedor)
April 29, 2017, 12:48pm
2
No, that's not closing the controller (it's not closable) nor the connection, that's only closing the resource channel so the circuit breaker accounting is correct. The bug is on your side, keep alive works fine.
system
(system)
Closed
May 27, 2017, 12:56pm
3
This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.