001package io.prometheus.metrics.exporter.servlet.jakarta;
002
003import io.prometheus.metrics.exporter.common.PrometheusHttpExchange;
004import io.prometheus.metrics.exporter.common.PrometheusHttpRequest;
005import io.prometheus.metrics.exporter.common.PrometheusHttpResponse;
006import jakarta.servlet.http.HttpServletRequest;
007import jakarta.servlet.http.HttpServletResponse;
008import java.io.IOException;
009import java.io.OutputStream;
010import java.util.Enumeration;
011
012public class HttpExchangeAdapter implements PrometheusHttpExchange {
013
014  private final Request request;
015  private final Response response;
016
017  public HttpExchangeAdapter(HttpServletRequest request, HttpServletResponse response) {
018    this.request = new Request(request);
019    this.response = new Response(response);
020  }
021
022  @Override
023  public PrometheusHttpRequest getRequest() {
024    return request;
025  }
026
027  @Override
028  public PrometheusHttpResponse getResponse() {
029    return response;
030  }
031
032  @Override
033  public void handleException(IOException e) throws IOException {
034    throw e; // leave exception handling to the servlet container
035  }
036
037  @Override
038  public void handleException(RuntimeException e) {
039    throw e; // leave exception handling to the servlet container
040  }
041
042  @Override
043  public void close() {
044    // nothing to do for Servlets.
045  }
046
047  public static class Request implements PrometheusHttpRequest {
048
049    private final HttpServletRequest request;
050
051    public Request(HttpServletRequest request) {
052      this.request = request;
053    }
054
055    @Override
056    public String getQueryString() {
057      return request.getQueryString();
058    }
059
060    @Override
061    public Enumeration<String> getHeaders(String name) {
062      return request.getHeaders(name);
063    }
064
065    @Override
066    public String getMethod() {
067      return request.getMethod();
068    }
069
070    @Override
071    public String getRequestPath() {
072      StringBuilder uri = new StringBuilder();
073      String contextPath = request.getContextPath();
074      if (contextPath.startsWith("/")) {
075        uri.append(contextPath);
076      }
077      String servletPath = request.getServletPath();
078      if (servletPath.startsWith("/")) {
079        uri.append(servletPath);
080      }
081      String pathInfo = request.getPathInfo();
082      if (pathInfo != null) {
083        uri.append(pathInfo);
084      }
085      return uri.toString();
086    }
087  }
088
089  public static class Response implements PrometheusHttpResponse {
090
091    private final HttpServletResponse response;
092
093    public Response(HttpServletResponse response) {
094      this.response = response;
095    }
096
097    @Override
098    public void setHeader(String name, String value) {
099      response.setHeader(name, value);
100    }
101
102    @Override
103    public OutputStream sendHeadersAndGetBody(int statusCode, int contentLength)
104        throws IOException {
105      if (response.getHeader("Content-Length") == null && contentLength > 0) {
106        response.setContentLength(contentLength);
107      }
108      response.setStatus(statusCode);
109      return response.getOutputStream();
110    }
111  }
112}