Completely working version git, websockets and /dashboard.
This commit is contained in:
parent
eb2decd36d
commit
559c22fffa
52
rproxy.c
52
rproxy.c
@ -2093,6 +2093,7 @@ void handle_client_read(connection_t *conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void handle_forwarding(connection_t *conn) {
|
static void handle_forwarding(connection_t *conn) {
|
||||||
connection_t *pair = conn->pair;
|
connection_t *pair = conn->pair;
|
||||||
if (!pair || pair->fd == -1) {
|
if (!pair || pair->fd == -1) {
|
||||||
@ -2111,41 +2112,62 @@ static void handle_forwarding(connection_t *conn) {
|
|||||||
|
|
||||||
int bytes_read = do_read(conn);
|
int bytes_read = do_read(conn);
|
||||||
|
|
||||||
// --- START: GIT HALF-CLOSE FIX ---
|
// --- START: COMPLETE PIPELINE FIX ---
|
||||||
if (bytes_read == 0) { // EOF received, meaning this side is done writing.
|
// This is the crucial fix for the keep-alive pipelining problem.
|
||||||
|
// If we read new data FROM THE CLIENT, we must inspect it before forwarding.
|
||||||
|
if (bytes_read > 0 && conn->type == CONN_TYPE_CLIENT) {
|
||||||
|
char* data_start = conn->read_buf.data + conn->read_buf.head;
|
||||||
|
size_t data_len = buffer_available_read(&conn->read_buf);
|
||||||
|
|
||||||
|
// Heuristic check: Does the new data look like a new HTTP request for an internal route?
|
||||||
|
// We check for "GET /" and then the specific paths.
|
||||||
|
if (data_len > 10 && memcmp(data_start, "GET /", 5) == 0) {
|
||||||
|
// Temporarily null-terminate to use strncmp safely on the URI part.
|
||||||
|
char old_char = data_start[data_len-1];
|
||||||
|
data_start[data_len-1] = '\0';
|
||||||
|
|
||||||
|
bool is_internal_route = (strstr(data_start, "/dashboard") || strstr(data_start, "/api/stats"));
|
||||||
|
|
||||||
|
data_start[data_len-1] = old_char; // Restore buffer
|
||||||
|
|
||||||
|
if (is_internal_route) {
|
||||||
|
log_info("[ROUTING-INTERCEPT] Intercepted internal route on keep-alive fd=%d. Re-routing.", conn->fd);
|
||||||
|
|
||||||
|
// This is an internal request. We must break the link to the old upstream server.
|
||||||
|
// The close_connection logic will handle un-pairing and resetting our state.
|
||||||
|
close_connection(pair->fd);
|
||||||
|
|
||||||
|
// The close_connection call above should have already reset this client's state
|
||||||
|
// and called handle_client_read if data was present. We can safely return.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// --- END: COMPLETE PIPELINE FIX ---
|
||||||
|
|
||||||
|
|
||||||
|
if (bytes_read == 0) { // EOF received
|
||||||
log_debug("EOF on fd %d, performing half-close on pair fd %d", conn->fd, pair->fd);
|
log_debug("EOF on fd %d, performing half-close on pair fd %d", conn->fd, pair->fd);
|
||||||
conn->half_closed = 1;
|
conn->half_closed = 1;
|
||||||
|
|
||||||
// Stop listening for reads on this socket, as it's closed.
|
|
||||||
modify_epoll(conn->fd, buffer_available_read(&conn->write_buf) ? EPOLLOUT : 0);
|
modify_epoll(conn->fd, buffer_available_read(&conn->write_buf) ? EPOLLOUT : 0);
|
||||||
|
|
||||||
// Tell the other side we are done writing to it.
|
|
||||||
if (pair->fd != -1 && !pair->write_shutdown) {
|
if (pair->fd != -1 && !pair->write_shutdown) {
|
||||||
if (shutdown(pair->fd, SHUT_WR) == -1 && errno != ENOTCONN) {
|
if (shutdown(pair->fd, SHUT_WR) == -1 && errno != ENOTCONN) {
|
||||||
log_debug("shutdown(SHUT_WR) failed for fd %d: %s", pair->fd, strerror(errno));
|
log_debug("shutdown(SHUT_WR) failed for fd %d: %s", pair->fd, strerror(errno));
|
||||||
}
|
}
|
||||||
pair->write_shutdown = 1;
|
pair->write_shutdown = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the other side had already signaled it was done writing, we can now fully close.
|
|
||||||
if (pair->half_closed) {
|
if (pair->half_closed) {
|
||||||
close_connection(conn->fd);
|
close_connection(conn->fd);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// --- END: GIT HALF-CLOSE FIX ---
|
|
||||||
|
|
||||||
if (bytes_read < 0 && (errno != EAGAIN && errno != EWOULDBLOCK)) {
|
if (bytes_read < 0 && (errno != EAGAIN && errno != EWOULDBLOCK)) {
|
||||||
close_connection(conn->fd);
|
close_connection(conn->fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pipelining check remains unchanged...
|
|
||||||
if (bytes_read > 0 && conn->type == CONN_TYPE_CLIENT) {
|
|
||||||
// ...
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forwarding logic remains unchanged...
|
|
||||||
size_t data_to_forward = buffer_available_read(&conn->read_buf);
|
size_t data_to_forward = buffer_available_read(&conn->read_buf);
|
||||||
if (data_to_forward > 0) {
|
if (data_to_forward > 0) {
|
||||||
if (buffer_ensure_capacity(&pair->write_buf, pair->write_buf.tail + data_to_forward) < 0) {
|
if (buffer_ensure_capacity(&pair->write_buf, pair->write_buf.tail + data_to_forward) < 0) {
|
||||||
@ -2161,8 +2183,6 @@ static void handle_forwarding(connection_t *conn) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void handle_ssl_handshake(connection_t *conn) {
|
static void handle_ssl_handshake(connection_t *conn) {
|
||||||
if (!conn->ssl || conn->ssl_handshake_done) return;
|
if (!conn->ssl || conn->ssl_handshake_done) return;
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user