Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
3 changes: 2 additions & 1 deletion src/java.base/share/classes/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,8 @@
jdk.net;
exports sun.net to
java.net.http,
jdk.naming.dns;
jdk.naming.dns,
jdk.httpserver;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good if we could avoid giving the jdk.httpserver module access to the sun.net.* package.

@dfuch @Michael-Mc-Mahon Are you sure that net.properties is the right place for this?

Copy link
Member

@dfuch dfuch Oct 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlanBateman I hadn't realised that the HttpServer didn't already have access to sun.net.* - and I agree that it would be better if we did not add such an access. That said - the new property is a compatibility property - and documenting in module-info seemed a bit too much - so out of the way in net.properties seemed like an appealing place to add it.

Another possibility could be to document it only in the release notes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shall I revert the change and leave as a system property?

exports sun.net.ext to
jdk.net;
exports sun.net.dns to
Expand Down
7 changes: 7 additions & 0 deletions src/java.base/share/conf/net.properties
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,13 @@ jdk.http.auth.tunneling.disabledSchemes=Basic
#
jdk.http.ntlm.transparentAuth=disabled

# Prior to JDK 26, the HttpExchange attribute map was shared with the enclosing HttpContext.
# Since JDK 26, by default, exchange attributes are per-exchange and the context attributes must
# be accessed by calling getHttpContext().getAttributes(). Uncomment this property to
# restore the pre JDK 26 behavior.
#
# jdk.httpserver.attributes=context

#
# Maximum HTTP field section size that a client is prepared to accept
#
Expand Down
2 changes: 2 additions & 0 deletions src/jdk.httpserver/share/classes/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@
* socket option on all incoming connections.
* </li></ul>
*
* Additional system/networking properties may be defined in net.properties
*
* @apiNote The API and SPI in this module are designed and implemented to support a minimal
* HTTP server and simple HTTP semantics primarily.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import java.net.*;
import javax.net.ssl.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.text.*;
Expand All @@ -38,6 +39,8 @@
import java.util.stream.Stream;
import com.sun.net.httpserver.*;

import sun.net.NetProperties;

class ExchangeImpl {

Headers reqHdrs, rspHdrs;
Expand All @@ -59,6 +62,9 @@ class ExchangeImpl {

/* for formatting the Date: header */
private static final DateTimeFormatter FORMATTER;
private static final boolean perExchangeAttributes =
!Optional.ofNullable(NetProperties.get("jdk.httpserver.attributes")).orElse("")
.equals("context");
static {
String pattern = "EEE, dd MMM yyyy HH:mm:ss zzz";
FORMATTER = DateTimeFormatter.ofPattern(pattern, Locale.US)
Expand All @@ -76,7 +82,7 @@ class ExchangeImpl {
PlaceholderOutputStream uos_orig;

boolean sentHeaders; /* true after response headers sent */
Map<String,Object> attributes;
final Map<String,Object> attributes;
int rcode = -1;
HttpPrincipal principal;
ServerImpl server;
Expand All @@ -91,6 +97,9 @@ class ExchangeImpl {
this.uri = u;
this.connection = connection;
this.reqContentLen = len;
this.attributes = perExchangeAttributes
? new ConcurrentHashMap<>()
: getHttpContext().getAttributes();
/* ros only used for headers, body written directly to stream */
this.ros = req.outputStream();
this.ris = req.inputStream();
Expand Down Expand Up @@ -361,26 +370,15 @@ public SSLSession getSSLSession () {
}

public Object getAttribute (String name) {
if (name == null) {
throw new NullPointerException ("null name parameter");
}
if (attributes == null) {
attributes = getHttpContext().getAttributes();
}
return attributes.get (name);
return attributes.get(Objects.requireNonNull(name, "null name parameter"));
}

public void setAttribute (String name, Object value) {
if (name == null) {
throw new NullPointerException ("null name parameter");
}
if (attributes == null) {
attributes = getHttpContext().getAttributes();
}
var key = Objects.requireNonNull(name, "null name parameter");
if (value != null) {
attributes.put (name, value);
attributes.put(key, value);
} else {
attributes.remove (name);
attributes.remove(key);
}
}

Expand Down
3 changes: 2 additions & 1 deletion test/jdk/com/sun/net/httpserver/ExchangeAttributeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ public static void setup() {
public void testExchangeAttributes() throws Exception {
var handler = new AttribHandler();
var server = HttpServer.create(new InetSocketAddress(LOOPBACK_ADDR,0), 10);
server.createContext("/", handler);
server.createContext("/", handler).getAttributes().put("attr", "context-val");
server.start();
try {
var client = HttpClient.newBuilder().proxy(NO_PROXY).build();
Expand Down Expand Up @@ -101,6 +101,7 @@ static class AttribHandler implements HttpHandler {
@java.lang.Override
public void handle(HttpExchange exchange) throws IOException {
try {
assertNull(exchange.getAttribute("attr"));
exchange.setAttribute("attr", "val");
assertEquals("val", exchange.getAttribute("attr"));
exchange.setAttribute("attr", null);
Expand Down