From 08ba60775077e6f1e12d492304bbee6edc22fc56 Mon Sep 17 00:00:00 2001 From: Jason Keller Date: Thu, 5 Sep 2024 10:33:13 -0700 Subject: [PATCH] Protect against Http2Headers methods throwing exceptions --- .../netty4116/Http2RequestHeaderWrapper.java | 122 ++++++++++++------ .../netty4116/Http2ResponseHeaderWrapper.java | 57 +++++--- 2 files changed, 123 insertions(+), 56 deletions(-) diff --git a/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2RequestHeaderWrapper.java b/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2RequestHeaderWrapper.java index 904da2cd1b..8bcbefcd35 100644 --- a/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2RequestHeaderWrapper.java +++ b/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2RequestHeaderWrapper.java @@ -38,40 +38,79 @@ public class Http2RequestHeaderWrapper extends ExtendedRequest { public Http2RequestHeaderWrapper(Http2Headers http2Headers) { super(); this.http2Headers = http2Headers; - this.method = http2Headers.method(); - this.path = http2Headers.path(); - this.authority = http2Headers.authority(); - - Set rawCookies = null; - if (http2Headers.contains(HttpHeaderNames.COOKIE)) { - CharSequence cookie = http2Headers.get(HttpHeaderNames.COOKIE); - try { - if (cookie != null) { - rawCookies = ServerCookieDecoder.STRICT.decode(cookie.toString()); - } - } catch (Exception e) { - AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to decode cookie: {0}", cookie); - rawCookies = Collections.emptySet(); - } - } - this.cookies = rawCookies; + this.method = getMethodHeader(); + this.path = getPathHeader(); + this.authority = getAuthorityHeader(); + this.cookies = getCookies(); + this.parameters = getParameters(); + } + private Map> getParameters() { Map> params = null; - CharSequence path = http2Headers.path(); try { String uri; if (path != null) { uri = path.toString(); - uri = URL_REPLACEMENT_PATTERN.matcher(uri).replaceAll("%25"); // Escape any percent signs in the URI + // Escape any percent signs in the URI + uri = URL_REPLACEMENT_PATTERN.matcher(uri).replaceAll("%25"); QueryStringDecoder decoderQuery = new QueryStringDecoder(uri); params = decoderQuery.parameters(); - } } catch (Exception e) { AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to decode URI: {0}", path); params = new LinkedHashMap<>(); } - this.parameters = params; + return params; + } + + private Set getCookies() { + Set rawCookies = null; + try { + if (http2Headers.contains(HttpHeaderNames.COOKIE)) { + CharSequence cookie = http2Headers.get(HttpHeaderNames.COOKIE); + try { + if (cookie != null) { + rawCookies = ServerCookieDecoder.STRICT.decode(cookie.toString()); + } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to decode cookie: {0}", cookie); + rawCookies = Collections.emptySet(); + } + } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers cookies: {0}", e.getMessage()); + } + return rawCookies; + } + + private CharSequence getMethodHeader() { + CharSequence method = null; + try { + method = http2Headers.method(); + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers method: {0}", e.getMessage()); + } + return method; + } + + private CharSequence getPathHeader() { + CharSequence path = null; + try { + path = http2Headers.path(); + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers path: {0}", e.getMessage()); + } + return path; + } + + private CharSequence getAuthorityHeader() { + CharSequence authority = null; + try { + authority = http2Headers.authority(); + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers authority: {0}", e.getMessage()); + } + return authority; } @Override @@ -84,14 +123,18 @@ public String getRequestURI() { @Override public String getHeader(String name) { - // HTTP/2 only supports lowercase headers - String lowerCaseHeaderName = name.toLowerCase(); - if (lowerCaseHeaderName.equals(HttpHeaderNames.HOST.toString())) { - return getHost(); - } + try { + // HTTP/2 only supports lowercase headers + String lowerCaseHeaderName = name.toLowerCase(); + if (lowerCaseHeaderName.equals(HttpHeaderNames.HOST.toString())) { + return getHost(); + } - if (http2Headers.contains(lowerCaseHeaderName)) { - return http2Headers.get(lowerCaseHeaderName).toString(); + if (http2Headers.contains(lowerCaseHeaderName)) { + return http2Headers.get(lowerCaseHeaderName).toString(); + } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers header: {0}", e.getMessage()); } return null; } @@ -145,10 +188,13 @@ public String getMethod() { } public String getHost() { - if (http2Headers.contains(HttpHeaderNames.HOST)) { - return http2Headers.get(HttpHeaderNames.HOST).toString(); + try { + if (http2Headers.contains(HttpHeaderNames.HOST)) { + return http2Headers.get(HttpHeaderNames.HOST).toString(); + } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, "host header is not present in Http2Headers"); } - if (authority == null) { return null; } @@ -157,12 +203,16 @@ public String getHost() { @Override public List getHeaders(String name) { - // HTTP/2 only supports lowercase headers - String lowerCaseHeaderName = name.toLowerCase(); List headers = new ArrayList<>(); - List allHeaders = http2Headers.getAll(lowerCaseHeaderName); - for (CharSequence header : allHeaders) { - headers.add(header.toString()); + try { + // HTTP/2 only supports lowercase headers + String lowerCaseHeaderName = name.toLowerCase(); + List allHeaders = http2Headers.getAll(lowerCaseHeaderName); + for (CharSequence header : allHeaders) { + headers.add(header.toString()); + } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers headers: {0}", e.getMessage()); } return headers; } diff --git a/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2ResponseHeaderWrapper.java b/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2ResponseHeaderWrapper.java index 0cf70395fc..8bff7ee03b 100644 --- a/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2ResponseHeaderWrapper.java +++ b/instrumentation/netty-4.1.16/src/main/java/com/agent/instrumentation/netty4116/Http2ResponseHeaderWrapper.java @@ -7,11 +7,14 @@ package com.agent.instrumentation.netty4116; +import com.newrelic.agent.bridge.AgentBridge; import com.newrelic.api.agent.ExtendedResponse; import com.newrelic.api.agent.HeaderType; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http2.Http2Headers; +import java.util.logging.Level; + public class Http2ResponseHeaderWrapper extends ExtendedResponse { private final Http2Headers http2Headers; @@ -26,23 +29,29 @@ public HeaderType getHeaderType() { @Override public void setHeader(String name, String value) { - // HTTP/2 only supports lowercase headers - String lowerCaseHeaderName = name.toLowerCase(); try { + // HTTP/2 only supports lowercase headers + String lowerCaseHeaderName = name.toLowerCase(); http2Headers.set(lowerCaseHeaderName, value); - } catch (Exception ignored) { + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to set Http2Headers header: {0}", e.getMessage()); } } @Override public int getStatus() { - CharSequence status = http2Headers.status(); - if (status == null) { - return -1; - } try { - return Integer.parseInt(status.toString()); - } catch (NumberFormatException e) { + CharSequence status = http2Headers.status(); + if (status == null) { + return -1; + } + try { + return Integer.parseInt(status.toString()); + } catch (NumberFormatException e) { + return -1; + } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers status: {0}", e.getMessage()); return -1; } } @@ -55,26 +64,34 @@ public String getStatusMessage() { @Override public String getContentType() { - if (http2Headers.contains(HttpHeaderNames.CONTENT_TYPE)) { - CharSequence contentType = http2Headers.get(HttpHeaderNames.CONTENT_TYPE); - if (contentType != null) { - return contentType.toString(); + try { + if (http2Headers.contains(HttpHeaderNames.CONTENT_TYPE)) { + CharSequence contentType = http2Headers.get(HttpHeaderNames.CONTENT_TYPE); + if (contentType != null) { + return contentType.toString(); + } } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers content-type: {0}", e.getMessage()); } return null; } @Override public long getContentLength() { - if (http2Headers.contains(HttpHeaderNames.CONTENT_LENGTH)) { - CharSequence contentLength = http2Headers.get(HttpHeaderNames.CONTENT_LENGTH); - if (contentLength != null) { - try { - return Long.parseLong(contentLength.toString()); - } catch (NumberFormatException e) { - return -1; + try { + if (http2Headers.contains(HttpHeaderNames.CONTENT_LENGTH)) { + CharSequence contentLength = http2Headers.get(HttpHeaderNames.CONTENT_LENGTH); + if (contentLength != null) { + try { + return Long.parseLong(contentLength.toString()); + } catch (NumberFormatException e) { + return -1; + } } } + } catch (Exception e) { + AgentBridge.getAgent().getLogger().log(Level.FINER, e, "Unable to get Http2Headers content-length: {0}", e.getMessage()); } return -1; }