• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

hazendaz / httpunit / 389

12 Aug 2025 11:17PM UTC coverage: 80.48% (-0.02%) from 80.503%
389

push

github

hazendaz
Merge branch 'master' into javax

3216 of 4105 branches covered (78.34%)

Branch coverage included in aggregate %.

238 of 258 new or added lines in 68 files covered. (92.25%)

2 existing lines in 2 files now uncovered.

8254 of 10147 relevant lines covered (81.34%)

0.81 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.46
/src/main/java/com/meterware/httpunit/HttpWebResponse.java
1
/*
2
 * MIT License
3
 *
4
 * Copyright 2011-2025 Russell Gold
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
7
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
9
 * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
10
 *
11
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions
12
 * of the Software.
13
 *
14
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
15
 * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
17
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
18
 * DEALINGS IN THE SOFTWARE.
19
 */
20
package com.meterware.httpunit;
21

22
import java.io.BufferedInputStream;
23
import java.io.ByteArrayInputStream;
24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.net.HttpURLConnection;
27
import java.net.URL;
28
import java.net.URLConnection;
29
import java.net.UnknownHostException;
30
import java.nio.charset.Charset;
31
import java.util.Enumeration;
32
import java.util.Hashtable;
33
import java.util.StringTokenizer;
34
import java.util.Vector;
35

36
/**
37
 * A response from a web server to an Http request.
38
 *
39
 * @author <a href="mailto:russgold@httpunit.org">Russell Gold</a>
40
 **/
41
class HttpWebResponse extends WebResponse {
42

43
    private String _referer;
44

45
    /**
46
     * Constructs a response object from an input stream.
47
     *
48
     * @param frame
49
     *            the target window or frame to which the request should be directed
50
     * @param url
51
     *            the url from which the response was received
52
     * @param connection
53
     *            the URL connection from which the response can be read
54
     **/
55
    HttpWebResponse(WebConversation client, FrameSelector frame, URL url, URLConnection connection,
56
            boolean throwExceptionOnError) throws IOException {
57
        super(client, frame, url);
1✔
58
        if (HttpUnitOptions.isLoggingHttpHeaders()) {
1!
59
            System.out.println("\nReceived from " + url);
×
60
        }
61
        readHeaders(connection);
1✔
62

63
        /** make sure that any IO exception for HTML received page happens here, not later. **/
64
        if (_responseCode < HttpURLConnection.HTTP_BAD_REQUEST || !throwExceptionOnError) {
1✔
65
            InputStream inputStream = getInputStream(connection);
1✔
66
            defineRawInputStream(new BufferedInputStream(inputStream));
1✔
67
            String contentType = getContentType();
1✔
68
            if (contentType.startsWith("text")) {
1✔
69
                loadResponseText();
1✔
70
            }
71
        }
72
    }
1✔
73

74
    HttpWebResponse(WebConversation client, FrameSelector frame, WebRequest request, URLConnection connection,
75
            boolean throwExceptionOnError) throws IOException {
76
        this(client, frame, request.getURL(), connection, throwExceptionOnError);
1✔
77
        super.setWithParse(!request.getMethod().equals("HEAD"));
1✔
78
        _referer = request.getReferer();
1✔
79
    }
1✔
80

81
    /**
82
     * get the input stream for the given connection
83
     *
84
     * @param connection
85
     *
86
     * @return
87
     *
88
     * @throws IOException
89
     */
90
    private InputStream getInputStream(URLConnection connection) throws IOException {
91
        InputStream result = null;
1✔
92
        // check whether there is an error stream
93
        if (isResponseOnErrorStream(connection)) {
1✔
94
            result = ((HttpURLConnection) connection).getErrorStream();
1✔
95
        } else {
96
            // if there is no error stream it depends on the response code
97
            try {
98
                result = connection.getInputStream();
1✔
99
            } catch (java.io.FileNotFoundException fnfe) {
1✔
100
                // as of JDK 1.5 a null inputstream might have been returned here
101
                // see bug report [ 1283878 ] FileNotFoundException using Sun JDK 1.5 on empty error pages
102
                // by Roger Lindsj?
103
                if (!isErrorResponse(connection)) {
1✔
104
                    throw fnfe;
1✔
105
                }
106
                // fake an empty error stream
107
                result = new ByteArrayInputStream(new byte[0]);
1✔
108
            }
1✔
109
        }
110
        return result;
1✔
111
    }
112

113
    /**
114
     * check whether a response code >=400 was received
115
     *
116
     * @param connection
117
     *
118
     * @return
119
     */
120
    private boolean isErrorResponse(URLConnection connection) {
121
        return _responseCode >= HttpURLConnection.HTTP_BAD_REQUEST;
1✔
122
    }
123

124
    /**
125
     * check whether the response is on the error stream
126
     *
127
     * @param connection
128
     *
129
     * @return
130
     */
131
    private boolean isResponseOnErrorStream(URLConnection connection) {
132
        return isErrorResponse(connection) && ((HttpURLConnection) connection).getErrorStream() != null;
1✔
133
    }
134

135
    /**
136
     * Returns the response code associated with this response.
137
     **/
138
    @Override
139
    public int getResponseCode() {
140
        return _responseCode;
1✔
141
    }
142

143
    /**
144
     * Returns the response message associated with this response.
145
     **/
146
    @Override
147
    public String getResponseMessage() {
148
        return _responseMessage;
1✔
149
    }
150

151
    @Override
152
    public String[] getHeaderFieldNames() {
NEW
153
        Vector names = new Vector<>();
×
154
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
155
            names.addElement(e.nextElement());
×
156
        }
157
        String[] result = new String[names.size()];
×
158
        names.copyInto(result);
×
159
        return result;
×
160
    }
161

162
    /**
163
     * Returns the value for the specified header field. If no such field is defined, will return null.
164
     **/
165
    @Override
166
    public String getHeaderField(String fieldName) {
167
        String[] fields = (String[]) _headers.get(fieldName.toUpperCase());
1✔
168
        return fields == null ? null : fields[0];
1✔
169
    }
170

171
    @Override
172
    public String[] getHeaderFields(String fieldName) {
173
        String[] fields = (String[]) _headers.get(fieldName.toUpperCase());
1✔
174
        return fields == null ? new String[0] : fields;
1✔
175
    }
176

177
    @Override
178
    public String toString() {
179
        StringBuilder sb = new StringBuilder("HttpWebResponse [url=");
×
180
        sb.append(getURL()).append("; headers=");
×
181
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
182
            Object key = e.nextElement();
×
183
            String[] values = (String[]) _headers.get(key);
×
184
            for (String value : values) {
×
185
                sb.append("\n   ").append(key).append(": ").append(value);
×
186
            }
187
        }
×
188
        sb.append(" ]");
×
189
        return sb.toString();
×
190
    }
191

192
    @Override
193
    String getReferer() {
194
        return _referer;
1✔
195
    }
196

197
    // ------------------------------------- private members -------------------------------------
198

199
    private static final String FILE_ENCODING = Charset.defaultCharset().displayName();
1✔
200

201
    private int _responseCode = HttpURLConnection.HTTP_OK;
1✔
202
    private String _responseMessage = "OK";
1✔
203

204
    /**
205
     * set the responseCode to the given code and message
206
     *
207
     * @param code
208
     * @param message
209
     */
210
    private void setResponseCode(int code, String message) {
211
        _responseCode = code;
1✔
212
        _responseMessage = message;
1✔
213
    }
1✔
214

215
    private Hashtable _headers = new Hashtable<>();
1✔
216

217
    /**
218
     * read the response Header for the given connection and set the response code and message accordingly
219
     *
220
     * @param connection
221
     *
222
     * @throws IOException
223
     */
224
    private void readResponseHeader(HttpURLConnection connection) throws IOException {
225
        if (!needStatusWorkaround()) {
1!
226
            setResponseCode(connection.getResponseCode(), connection.getResponseMessage());
1✔
227
        } else {
228
            if (connection.getHeaderField(0) == null) {
×
229
                throw new UnknownHostException(connection.getURL().toExternalForm());
×
230
            }
231

232
            StringTokenizer st = new StringTokenizer(connection.getHeaderField(0));
×
233
            st.nextToken();
×
234
            if (!st.hasMoreTokens()) {
×
235
                setResponseCode(HttpURLConnection.HTTP_OK, "OK");
×
236
            } else {
237
                try {
238
                    setResponseCode(Integer.parseInt(st.nextToken()), getRemainingTokens(st));
×
239
                } catch (NumberFormatException e) {
×
240
                    setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR, "Cannot parse response header");
×
241
                }
×
242
            }
243
        }
244
    }
1✔
245

246
    private boolean needStatusWorkaround() {
247
        final String jdkVersion = System.getProperty("java.version");
1✔
248
        return jdkVersion.startsWith("1.2") || jdkVersion.startsWith("1.3");
1!
249
    }
250

251
    private String getRemainingTokens(StringTokenizer st) {
252
        StringBuilder messageBuffer = new StringBuilder(st.hasMoreTokens() ? st.nextToken() : "");
×
253
        while (st.hasMoreTokens()) {
×
254
            messageBuffer.append(' ').append(st.nextToken());
×
255
        }
256
        return messageBuffer.toString();
×
257
    }
258

259
    private void readHeaders(URLConnection connection) throws IOException {
260
        loadHeaders(connection);
1✔
261
        if (connection instanceof HttpURLConnection) {
1✔
262
            readResponseHeader((HttpURLConnection) connection);
1✔
263
        } else {
264
            setResponseCode(HttpURLConnection.HTTP_OK, "OK");
1✔
265
            if (connection.getContentType().startsWith("text")) {
1!
266
                setContentTypeHeader(connection.getContentType() + "; charset=" + FILE_ENCODING);
1✔
267
            }
268
        }
269
    }
1✔
270

271
    private void loadHeaders(URLConnection connection) {
272
        if (HttpUnitOptions.isLoggingHttpHeaders()) {
1!
273
            System.out.println("Header:: " + connection.getHeaderField(0));
×
274
        }
275
        for (int i = 1; true; i++) {
1✔
276
            String headerFieldKey = connection.getHeaderFieldKey(i);
1✔
277
            String headerField = connection.getHeaderField(i);
1✔
278
            if (headerFieldKey == null || headerField == null) {
1!
279
                break;
×
280
            }
281
            if (HttpUnitOptions.isLoggingHttpHeaders()) {
1!
282
                System.out.println("Header:: " + headerFieldKey + ": " + headerField);
×
283
            }
284
            addHeader(headerFieldKey.toUpperCase(), headerField);
1✔
285
        }
286

287
        if (connection.getContentType() != null) {
1!
288
            setContentTypeHeader(connection.getContentType());
1✔
289
        }
290
    }
1✔
291

292
    private void addHeader(String key, String field) {
293
        _headers.put(key, HttpUnitUtils.withNewValue((String[]) _headers.get(key), field));
1✔
294
    }
1✔
295

296
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc