154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson/*
254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * Copyright (C) 2011 Google Inc.
354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson *
454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
554ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * you may not use this file except in compliance with the License.
654ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * You may obtain a copy of the License at
754ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson *
854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
954ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson *
1054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * Unless required by applicable law or agreed to in writing, software
1154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
1254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * See the License for the specific language governing permissions and
1454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * limitations under the License.
1554ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson */
1654ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
1754ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilsonpackage com.google.mockwebserver;
1854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
197a68ed6a49c3060b235810391a82412a95f9c979jwilsonimport java.io.UnsupportedEncodingException;
2024198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilsonimport java.net.Socket;
21ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fullerimport java.security.Principal;
22ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fullerimport java.security.cert.Certificate;
237a68ed6a49c3060b235810391a82412a95f9c979jwilsonimport java.util.ArrayList;
2454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilsonimport java.util.List;
25ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller
26ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fullerimport javax.net.ssl.SSLPeerUnverifiedException;
27ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fullerimport javax.net.ssl.SSLSession;
2824198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilsonimport javax.net.ssl.SSLSocket;
2954ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
3054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson/**
3154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson * An HTTP request that came into the mock web server.
3254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson */
3354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilsonpublic final class RecordedRequest {
3454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    private final String requestLine;
353b406d4de9b5f0f1caa990f079075eb0bfc5220aJeff Sharkey    private final String method;
363b406d4de9b5f0f1caa990f079075eb0bfc5220aJeff Sharkey    private final String path;
3754ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    private final List<String> headers;
3854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    private final List<Integer> chunkSizes;
3954ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    private final int bodySize;
4054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    private final byte[] body;
4154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    private final int sequenceNumber;
4224198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson    private final String sslProtocol;
43ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    private final String sslCipherSuite;
44ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    private final Principal sslLocalPrincipal;
45ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    private final Principal sslPeerPrincipal;
46ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    private final Certificate[] sslLocalCertificates;
47ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    private final Certificate[] sslPeerCertificates;
4854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
497a68ed6a49c3060b235810391a82412a95f9c979jwilson    public RecordedRequest(String requestLine, List<String> headers, List<Integer> chunkSizes,
5024198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson            int bodySize, byte[] body, int sequenceNumber, Socket socket) {
5154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        this.requestLine = requestLine;
5254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        this.headers = headers;
5354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        this.chunkSizes = chunkSizes;
5454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        this.bodySize = bodySize;
5554ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        this.body = body;
5654ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        this.sequenceNumber = sequenceNumber;
5724198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson
5824198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson        if (socket instanceof SSLSocket) {
5924198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson            SSLSocket sslSocket = (SSLSocket) socket;
60ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            SSLSession session = sslSocket.getSession();
61ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslProtocol = session.getProtocol();
62ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslCipherSuite = session.getCipherSuite();
63ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslLocalPrincipal = session.getLocalPrincipal();
64ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslLocalCertificates = session.getLocalCertificates();
65ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            Principal peerPrincipal = null;
66ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            Certificate[] peerCertificates = null;
67ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            try {
68ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller                peerPrincipal = session.getPeerPrincipal();
69ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller                peerCertificates = session.getPeerCertificates();
70ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            } catch (SSLPeerUnverifiedException e) {
71ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller                // No-op: use nulls instead
72ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            }
73ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslPeerPrincipal = peerPrincipal;
74ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslPeerCertificates = peerCertificates;
7524198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson        } else {
7624198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson            sslProtocol = null;
77ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslCipherSuite = null;
78ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslLocalPrincipal = null;
79ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslLocalCertificates = null;
80ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslPeerPrincipal = null;
81ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller            sslPeerCertificates = null;
8224198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson        }
833b406d4de9b5f0f1caa990f079075eb0bfc5220aJeff Sharkey
8483aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu        if (requestLine != null) {
8583aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu            int methodEnd = requestLine.indexOf(' ');
8683aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu            int pathEnd = requestLine.indexOf(' ', methodEnd + 1);
8783aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu            this.method = requestLine.substring(0, methodEnd);
8883aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu            this.path = requestLine.substring(methodEnd + 1, pathEnd);
8983aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu        } else {
9083aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu            this.method = null;
9183aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu            this.path = null;
9283aa2d278c5a3f9b93cd809f6fdffba9d1fa3868Brian Muramatsu        }
9354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
9454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
9554ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    public String getRequestLine() {
9654ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        return requestLine;
9754ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
9854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
997a68ed6a49c3060b235810391a82412a95f9c979jwilson    public String getMethod() {
1007a68ed6a49c3060b235810391a82412a95f9c979jwilson        return method;
1017a68ed6a49c3060b235810391a82412a95f9c979jwilson    }
1027a68ed6a49c3060b235810391a82412a95f9c979jwilson
1037a68ed6a49c3060b235810391a82412a95f9c979jwilson    public String getPath() {
1047a68ed6a49c3060b235810391a82412a95f9c979jwilson        return path;
1057a68ed6a49c3060b235810391a82412a95f9c979jwilson    }
1067a68ed6a49c3060b235810391a82412a95f9c979jwilson
1077a68ed6a49c3060b235810391a82412a95f9c979jwilson    /**
1087a68ed6a49c3060b235810391a82412a95f9c979jwilson     * Returns all headers.
1097a68ed6a49c3060b235810391a82412a95f9c979jwilson     */
11054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    public List<String> getHeaders() {
11154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        return headers;
11254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
11354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
11454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    /**
1157a68ed6a49c3060b235810391a82412a95f9c979jwilson     * Returns the first header named {@code name}, or null if no such header
1167a68ed6a49c3060b235810391a82412a95f9c979jwilson     * exists.
1177a68ed6a49c3060b235810391a82412a95f9c979jwilson     */
1187a68ed6a49c3060b235810391a82412a95f9c979jwilson    public String getHeader(String name) {
1197a68ed6a49c3060b235810391a82412a95f9c979jwilson        name += ":";
1207a68ed6a49c3060b235810391a82412a95f9c979jwilson        for (String header : headers) {
1217a68ed6a49c3060b235810391a82412a95f9c979jwilson            if (name.regionMatches(true, 0, header, 0, name.length())) {
1227a68ed6a49c3060b235810391a82412a95f9c979jwilson                return header.substring(name.length()).trim();
1237a68ed6a49c3060b235810391a82412a95f9c979jwilson            }
1247a68ed6a49c3060b235810391a82412a95f9c979jwilson        }
1257a68ed6a49c3060b235810391a82412a95f9c979jwilson        return null;
1267a68ed6a49c3060b235810391a82412a95f9c979jwilson    }
1277a68ed6a49c3060b235810391a82412a95f9c979jwilson
1287a68ed6a49c3060b235810391a82412a95f9c979jwilson    /**
1297a68ed6a49c3060b235810391a82412a95f9c979jwilson     * Returns the headers named {@code name}.
1307a68ed6a49c3060b235810391a82412a95f9c979jwilson     */
1317a68ed6a49c3060b235810391a82412a95f9c979jwilson    public List<String> getHeaders(String name) {
1327a68ed6a49c3060b235810391a82412a95f9c979jwilson        List<String> result = new ArrayList<String>();
1337a68ed6a49c3060b235810391a82412a95f9c979jwilson        name += ":";
1347a68ed6a49c3060b235810391a82412a95f9c979jwilson        for (String header : headers) {
1357a68ed6a49c3060b235810391a82412a95f9c979jwilson            if (name.regionMatches(true, 0, header, 0, name.length())) {
1367a68ed6a49c3060b235810391a82412a95f9c979jwilson                result.add(header.substring(name.length()).trim());
1377a68ed6a49c3060b235810391a82412a95f9c979jwilson            }
1387a68ed6a49c3060b235810391a82412a95f9c979jwilson        }
1397a68ed6a49c3060b235810391a82412a95f9c979jwilson        return result;
1407a68ed6a49c3060b235810391a82412a95f9c979jwilson    }
1417a68ed6a49c3060b235810391a82412a95f9c979jwilson
1427a68ed6a49c3060b235810391a82412a95f9c979jwilson    /**
14354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * Returns the sizes of the chunks of this request's body, or an empty list
14454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * if the request's body was empty or unchunked.
14554ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     */
14654ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    public List<Integer> getChunkSizes() {
14754ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        return chunkSizes;
14854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
14954ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
15054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    /**
15154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * Returns the total size of the body of this POST request (before
15254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * truncation).
15354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     */
15454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    public int getBodySize() {
15554ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        return bodySize;
15654ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
15754ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
15854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    /**
15954ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * Returns the body of this POST request. This may be truncated.
16054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     */
16154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    public byte[] getBody() {
16254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        return body;
16354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
16454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
16554ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    /**
1667a68ed6a49c3060b235810391a82412a95f9c979jwilson     * Returns the body of this POST request decoded as a UTF-8 string.
1677a68ed6a49c3060b235810391a82412a95f9c979jwilson     */
1687a68ed6a49c3060b235810391a82412a95f9c979jwilson    public String getUtf8Body() {
1697a68ed6a49c3060b235810391a82412a95f9c979jwilson        try {
1707a68ed6a49c3060b235810391a82412a95f9c979jwilson            return new String(body, "UTF-8");
1717a68ed6a49c3060b235810391a82412a95f9c979jwilson        } catch (UnsupportedEncodingException e) {
1727a68ed6a49c3060b235810391a82412a95f9c979jwilson            throw new AssertionError();
1737a68ed6a49c3060b235810391a82412a95f9c979jwilson        }
1747a68ed6a49c3060b235810391a82412a95f9c979jwilson    }
1757a68ed6a49c3060b235810391a82412a95f9c979jwilson
1767a68ed6a49c3060b235810391a82412a95f9c979jwilson    /**
17754ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * Returns the index of this request on its HTTP connection. Since a single
17854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * HTTP connection may serve multiple requests, each request is assigned its
17954ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     * own sequence number.
18054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson     */
18154ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    public int getSequenceNumber() {
18254ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson        return sequenceNumber;
18354ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
18454ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson
18524198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson    /**
186ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * Returns the SSL connection's protocol like {@code TLSv1}, {@code SSLv3},
187ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * {@code NONE} or {@code null} if the connection doesn't use SSL.
18824198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson     */
18924198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson    public String getSslProtocol() {
19024198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson        return sslProtocol;
19124198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson    }
19224198dd39014c4490b963f039b04d52e01d79bc5Jesse Wilson
193ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    /**
194ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * Returns the SSL connection's cipher protocol retrieved using
195ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * {@code sslSocket.getSession().getCipherSuite()} or {@code null} if the connection doesn't
196ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * use SSL.
197ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     */
198ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    public String getSslCipherSuite() {
199ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller        return sslCipherSuite;
200ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    }
201ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller
202ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    /**
203ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * Returns the SSL connection's local principal retrieved using
204ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * {@code sslSocket.getSession().getLocalPrincipal()} or {@code null} if the connection doesn't
205ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * use SSL.
206ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     */
207ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    public Principal getSslLocalPrincipal() {
208ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller        return sslLocalPrincipal;
209ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    }
210ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller
211ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    /**
212ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * Returns the SSL connection's local certificates retrieved using
213ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * {@code sslSocket.getSession().getLocalCertificates()} or {@code null} if the connection
214ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * doesn't use SSL.
215ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     */
216ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    public Certificate[] getSslLocalCertificates() {
217ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller        return sslLocalCertificates;
218ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    }
219ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller
220ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    /**
221ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * Returns the SSL connection's peer principal retrieved using
222ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * {@code sslSocket.getSession().getPeerPrincipal()}, or {@code null} if the connection doesn't
223ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * use SSL or the peer has not been verified.
224ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     */
225ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    public Principal getSslPeerPrincipal() {
226ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller        return sslPeerPrincipal;
227ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    }
228ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller
229ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    /**
230ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * Returns the SSL connection's peer certificates retrieved using
231ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * {@code sslSocket.getSession().getPeerCertificates()}, or {@code null} if the connection
232ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     * doesn't use SSL or the peer has not been verified.
233ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller     */
234ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    public Certificate[] getSslPeerCertificates() {
235ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller        return sslPeerCertificates;
236ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller    }
237ba996dc6b146d35eb9b98b93bf8d3ffc543543baNeil Fuller
23854ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    @Override public String toString() {
239a4a53d9c9bf86165a5e2bd9ce4bcb834f09d4c37Narayan Kamath        return "RecordedRequest {" + requestLine + "}";
24054ce6cb5d13f732a3e71aa3555cd3709d5bf3cf5Jesse Wilson    }
241a4a53d9c9bf86165a5e2bd9ce4bcb834f09d4c37Narayan Kamath}
242