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