Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -319,4 +319,52 @@
* @return the {@code HttpPrincipal}, or {@code null} if no authenticator is set
*/
public abstract HttpPrincipal getPrincipal();

/**
* Upgrades the HTTP connection to use a different protocol.
*

Check failure on line 325 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* <p>This method enables support for HTTP protocol upgrade, such as
* upgrading to WebSocket. When called, the server will:
* <ol>
* <li>Send an HTTP 101 (Switching Protocols) response with the upgrade
* response headers that have been set via {@link #getResponseHeaders()}
* <li>Transfer control of the underlying socket to the provided
* {@link HttpUpgradeHandler}
* <li>Invoke the handler with direct access to the socket streams
* </ol>
*

Check failure on line 335 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* <p>This method must be called before {@link #sendResponseHeaders(int, long)}.
* Appropriate upgrade response headers (such as {@code Upgrade} and
* {@code Connection: upgrade}) must be set before calling this method.
*

Check failure on line 339 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* <p>After this method is called, the exchange is considered complete and
* no further HTTP operations should be performed on it. The upgrade handler
* takes full control of the connection.
*

Check failure on line 343 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* <p>Example usage for WebSocket upgrade:
* <pre>{@code
* public void handle(HttpExchange exchange) throws IOException {
* Headers requestHeaders = exchange.getRequestHeaders();
* if ("websocket".equalsIgnoreCase(requestHeaders.getFirst("Upgrade"))) {
* Headers responseHeaders = exchange.getResponseHeaders();
* responseHeaders.set("Upgrade", "websocket");
* responseHeaders.set("Connection", "Upgrade");
* // Set other required headers like Sec-WebSocket-Accept
*

Check failure on line 353 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace Column 7: trailing whitespace Column 8: trailing whitespace Column 9: trailing whitespace Column 10: trailing whitespace Column 11: trailing whitespace Column 12: trailing whitespace Column 13: trailing whitespace Column 14: trailing whitespace
* exchange.upgrade((input, output) -> {
* // Handle WebSocket protocol
* // Read and write WebSocket frames
* });
* }
* }
* }</pre>
*

Check failure on line 361 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* @param handler the handler for the upgraded protocol
* @throws IOException if an I/O error occurs
* @throws IllegalStateException if response headers have already been sent
* or if the connection cannot be upgraded
* @throws NullPointerException if handler is {@code null}
* @since 26
*/
public abstract void upgrade(HttpUpgradeHandler handler) throws IOException;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package com.sun.net.httpserver;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/**
* A handler which is invoked to process HTTP protocol upgrade requests.
*

Check failure on line 34 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpUpgradeHandler.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 2: trailing whitespace
* <p>When an HTTP upgrade is initiated via {@link HttpExchange#upgrade(int, HttpUpgradeHandler)},
* the server will invoke the {@link #handle(InputStream, OutputStream)} method
* of this handler, providing direct access to the underlying socket streams.
*

Check failure on line 38 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpUpgradeHandler.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 2: trailing whitespace
* <p>The handler is responsible for:
* <ul>
* <li>Implementing the upgraded protocol (e.g., WebSocket)
* <li>Managing the lifecycle of the upgraded connection
* <li>Closing the streams when done
* </ul>
*

Check failure on line 45 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpUpgradeHandler.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 2: trailing whitespace
* <p>Once the upgrade is complete, the HTTP server will no longer manage
* the connection, and the handler has full control over the socket.
*

Check failure on line 48 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpUpgradeHandler.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 2: trailing whitespace
* @since 26
*/
@FunctionalInterface
public interface HttpUpgradeHandler {

/**
* Handles the upgraded protocol on the given streams.
*

Check failure on line 56 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpUpgradeHandler.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* <p>This method is called after a successful HTTP upgrade response has
* been sent to the client. The provided streams give direct access to
* the underlying socket, allowing the implementation to communicate
* using the upgraded protocol.
*

Check failure on line 61 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpUpgradeHandler.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* <p>The implementation is responsible for closing both streams when
* the upgraded protocol session is complete. The streams may be the
* same object if using a socket channel.
*

Check failure on line 65 in src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpUpgradeHandler.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 6: trailing whitespace
* @param input the input stream from the client
* @param output the output stream to the client
* @throws IOException if an I/O error occurs during protocol handling
*/
void handle(InputStream input, OutputStream output) throws IOException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,8 @@ public void setStreams(InputStream i, OutputStream o) {
public HttpPrincipal getPrincipal() {
return exchange.getPrincipal();
}

public void upgrade(com.sun.net.httpserver.HttpUpgradeHandler handler) throws IOException {
exchange.upgrade(handler);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@
int rcode = -1;
HttpPrincipal principal;
ServerImpl server;

Check failure on line 89 in src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace
/* upgrade state */
boolean upgraded = false;
HttpUpgradeHandler upgradeHandler = null;

ExchangeImpl(
String m, URI u, Request req, long len, HttpConnection connection
Expand Down Expand Up @@ -411,6 +415,39 @@
this.principal = principal;
}

void upgrade(HttpUpgradeHandler handler) throws IOException {
if (handler == null) {
throw new NullPointerException("handler cannot be null");
}
if (sentHeaders) {
throw new IllegalStateException("headers already sent");
}
this.upgraded = true;
this.upgradeHandler = handler;
this.rcode = 101;

Check failure on line 428 in src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace
// Send upgrade response with 101 Switching Protocols
String statusLine = "HTTP/1.1 101" + Code.msg(101) + "\r\n";
ByteArrayOutputStream tmpout = new ByteArrayOutputStream();
tmpout.write(bytes(statusLine, 0), 0, statusLine.length());
rspHdrs.set("Date", FORMATTER.format(Instant.now()));

Check failure on line 434 in src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace
write(rspHdrs, tmpout);
tmpout.writeTo(ros);
ros.flush();
sentHeaders = true;

Check failure on line 439 in src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java

View check run for this annotation

openjdk / jcheck-openjdk/jdk-28961

Whitespace error

Column 0: trailing whitespace Column 1: trailing whitespace Column 2: trailing whitespace Column 3: trailing whitespace Column 4: trailing whitespace Column 5: trailing whitespace Column 6: trailing whitespace Column 7: trailing whitespace
server.logReply(101, req.requestLine(), null);
}

boolean isUpgraded() {
return upgraded;
}

HttpUpgradeHandler getUpgradeHandler() {
return upgradeHandler;
}

static ExchangeImpl get(HttpExchange t) {
if (t instanceof HttpExchangeImpl) {
return ((HttpExchangeImpl)t).getExchangeImpl();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ public HttpPrincipal getPrincipal() {
return impl.getPrincipal();
}

public void upgrade(HttpUpgradeHandler handler) throws IOException {
impl.upgrade(handler);
}

ExchangeImpl getExchangeImpl() {
return impl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ public HttpPrincipal getPrincipal() {
return impl.getPrincipal();
}

public void upgrade(HttpUpgradeHandler handler) throws IOException {
impl.upgrade(handler);
}

ExchangeImpl getExchangeImpl() {
return impl;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpUpgradeHandler;
import com.sun.net.httpserver.HttpsConfigurator;
import sun.net.httpserver.HttpConnection.State;

Expand Down Expand Up @@ -901,6 +902,22 @@ public void run() {
uc.doFilter(new HttpExchangeImpl(tx));
}

// Handle protocol upgrade if requested
if (tx.isUpgraded()) {
HttpUpgradeHandler upgradeHandler = tx.getUpgradeHandler();
if (upgradeHandler != null) {
try {
// Transfer control to the upgrade handler with raw streams
upgradeHandler.handle(rawin, rawout);
} catch (IOException e) {
logger.log(Level.DEBUG, "Upgrade handler exception", e);
} finally {
// After upgrade handler completes, close the connection
closeConnection(connection);
}
}
}

} catch (Exception e) {
logger.log(Level.TRACE, "ServerImpl.Exchange", e);
if (tx == null || !tx.writefinished) {
Expand Down
Loading