001package io.prometheus.metrics.exporter.servlet.javax;
002
003import io.prometheus.metrics.exporter.common.PrometheusHttpExchange;
004import io.prometheus.metrics.exporter.common.PrometheusHttpRequest;
005import io.prometheus.metrics.exporter.common.PrometheusHttpResponse;
006import java.io.IOException;
007import java.io.OutputStream;
008import java.util.Enumeration;
009import javax.servlet.http.HttpServletRequest;
010import javax.servlet.http.HttpServletResponse;
011
012/**
013 * This class is an adapter for HTTP exchanges, implementing the PrometheusHttpExchange interface.
014 * It wraps HttpServletRequest and HttpServletResponse objects into Request and Response inner
015 * classes.
016 */
017public class HttpExchangeAdapter implements PrometheusHttpExchange {
018
019  private final Request request;
020  private final Response response;
021
022  /**
023   * Constructs a new HttpExchangeAdapter with the given HttpServletRequest and HttpServletResponse.
024   *
025   * @param request the HttpServletRequest to be adapted
026   * @param response the HttpServletResponse to be adapted
027   */
028  public HttpExchangeAdapter(HttpServletRequest request, HttpServletResponse response) {
029    this.request = new Request(request);
030    this.response = new Response(response);
031  }
032
033  /**
034   * Returns the adapted HttpServletRequest.
035   *
036   * @return the adapted HttpServletRequest
037   */
038  @Override
039  public PrometheusHttpRequest getRequest() {
040    return request;
041  }
042
043  /**
044   * Returns the adapted HttpServletResponse.
045   *
046   * @return the adapted HttpServletResponse
047   */
048  @Override
049  public PrometheusHttpResponse getResponse() {
050    return response;
051  }
052
053  @Override
054  public void handleException(IOException e) throws IOException {
055    throw e; // leave exception handling to the servlet container
056  }
057
058  @Override
059  public void handleException(RuntimeException e) {
060    throw e; // leave exception handling to the servlet container
061  }
062
063  @Override
064  public void close() {
065    // nothing to do for Servlets.
066  }
067
068  /** This inner class adapts a HttpServletRequest to a PrometheusHttpRequest. */
069  public static class Request implements PrometheusHttpRequest {
070
071    private final HttpServletRequest request;
072
073    /**
074     * Constructs a new Request with the given HttpServletRequest.
075     *
076     * @param request the HttpServletRequest to be adapted
077     */
078    public Request(HttpServletRequest request) {
079      this.request = request;
080    }
081
082    @Override
083    public String getQueryString() {
084      return request.getQueryString();
085    }
086
087    @Override
088    public Enumeration<String> getHeaders(String name) {
089      return request.getHeaders(name);
090    }
091
092    @Override
093    public String getMethod() {
094      return request.getMethod();
095    }
096
097    @Override
098    public String getRequestPath() {
099      StringBuilder uri = new StringBuilder();
100      String contextPath = request.getContextPath();
101      if (contextPath.startsWith("/")) {
102        uri.append(contextPath);
103      }
104      String servletPath = request.getServletPath();
105      if (servletPath.startsWith("/")) {
106        uri.append(servletPath);
107      }
108      String pathInfo = request.getPathInfo();
109      if (pathInfo != null) {
110        uri.append(pathInfo);
111      }
112      return uri.toString();
113    }
114  }
115
116  /** This inner class adapts a HttpServletResponse to a PrometheusHttpResponse. */
117  public static class Response implements PrometheusHttpResponse {
118
119    private final HttpServletResponse response;
120
121    /**
122     * Constructs a new Response with the given HttpServletResponse.
123     *
124     * @param response the HttpServletResponse to be adapted
125     */
126    public Response(HttpServletResponse response) {
127      this.response = response;
128    }
129
130    @Override
131    public void setHeader(String name, String value) {
132      response.setHeader(name, value);
133    }
134
135    @Override
136    public OutputStream sendHeadersAndGetBody(int statusCode, int contentLength)
137        throws IOException {
138      if (response.getHeader("Content-Length") == null && contentLength > 0) {
139        response.setContentLength(contentLength);
140      }
141      response.setStatus(statusCode);
142      return response.getOutputStream();
143    }
144  }
145}