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

hazendaz / httpunit / 755

14 Feb 2026 07:14PM UTC coverage: 80.526%. Remained the same
755

push

github

hazendaz
[ci] Fix badge

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10124 relevant lines covered (81.44%)

0.81 hits per line

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

64.29
/src/main/java/com/meterware/httpunit/HttpWebResponse.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2000-2026 Russell Gold
6
 * Copyright 2021-2000 hazendaz
7
 */
8
package com.meterware.httpunit;
9

10
import java.io.BufferedInputStream;
11
import java.io.ByteArrayInputStream;
12
import java.io.IOException;
13
import java.io.InputStream;
14
import java.net.HttpURLConnection;
15
import java.net.URL;
16
import java.net.URLConnection;
17
import java.net.UnknownHostException;
18
import java.nio.charset.Charset;
19
import java.util.ArrayList;
20
import java.util.Enumeration;
21
import java.util.Hashtable;
22
import java.util.List;
23
import java.util.StringTokenizer;
24

25
/**
26
 * A response from a web server to an Http request.
27
 **/
28
class HttpWebResponse extends WebResponse {
29

30
    /** The referer. */
31
    private String _referer;
32

33
    /**
34
     * Constructs a response object from an input stream.
35
     *
36
     * @param client
37
     *            the client
38
     * @param frame
39
     *            the target window or frame to which the request should be directed
40
     * @param url
41
     *            the url from which the response was received
42
     * @param connection
43
     *            the URL connection from which the response can be read
44
     * @param throwExceptionOnError
45
     *            the throw exception on error
46
     *
47
     * @throws IOException
48
     *             Signals that an I/O exception has occurred.
49
     */
50
    HttpWebResponse(WebConversation client, FrameSelector frame, URL url, URLConnection connection,
51
            boolean throwExceptionOnError) throws IOException {
52
        super(client, frame, url);
1✔
53
        if (HttpUnitOptions.isLoggingHttpHeaders()) {
1!
54
            System.out.println("\nReceived from " + url);
×
55
        }
56
        readHeaders(connection);
1✔
57

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

69
    /**
70
     * Instantiates a new http web response.
71
     *
72
     * @param client
73
     *            the client
74
     * @param frame
75
     *            the frame
76
     * @param request
77
     *            the request
78
     * @param connection
79
     *            the connection
80
     * @param throwExceptionOnError
81
     *            the throw exception on error
82
     *
83
     * @throws IOException
84
     *             Signals that an I/O exception has occurred.
85
     */
86
    HttpWebResponse(WebConversation client, FrameSelector frame, WebRequest request, URLConnection connection,
87
            boolean throwExceptionOnError) throws IOException {
88
        this(client, frame, request.getURL(), connection, throwExceptionOnError);
1✔
89
        super.setWithParse(!request.getMethod().equals("HEAD"));
1✔
90
        _referer = request.getReferer();
1✔
91
    }
1✔
92

93
    /**
94
     * get the input stream for the given connection.
95
     *
96
     * @param connection
97
     *            the connection
98
     *
99
     * @return the input stream
100
     *
101
     * @throws IOException
102
     *             Signals that an I/O exception has occurred.
103
     */
104
    private InputStream getInputStream(URLConnection connection) throws IOException {
105
        InputStream result = null;
1✔
106
        // check whether there is an error stream
107
        if (isResponseOnErrorStream(connection)) {
1✔
108
            result = ((HttpURLConnection) connection).getErrorStream();
1✔
109
        } else {
110
            // if there is no error stream it depends on the response code
111
            try {
112
                result = connection.getInputStream();
1✔
113
            } catch (java.io.FileNotFoundException fnfe) {
1✔
114
                // as of JDK 1.5 a null inputstream might have been returned here
115
                // see bug report [ 1283878 ] FileNotFoundException using Sun JDK 1.5 on empty error pages
116
                // by Roger Lindsj?
117
                if (!isErrorResponse(connection)) {
1✔
118
                    throw fnfe;
1✔
119
                }
120
                // fake an empty error stream
121
                result = new ByteArrayInputStream(new byte[0]);
1✔
122
            }
1✔
123
        }
124
        return result;
1✔
125
    }
126

127
    /**
128
     * check whether a response code >=400 was received.
129
     *
130
     * @param connection
131
     *            the connection
132
     *
133
     * @return true, if is error response
134
     */
135
    private boolean isErrorResponse(URLConnection connection) {
136
        return _responseCode >= HttpURLConnection.HTTP_BAD_REQUEST;
1✔
137
    }
138

139
    /**
140
     * check whether the response is on the error stream.
141
     *
142
     * @param connection
143
     *            the connection
144
     *
145
     * @return true, if is response on error stream
146
     */
147
    private boolean isResponseOnErrorStream(URLConnection connection) {
148
        return isErrorResponse(connection) && ((HttpURLConnection) connection).getErrorStream() != null;
1✔
149
    }
150

151
    /**
152
     * Returns the response code associated with this response.
153
     **/
154
    @Override
155
    public int getResponseCode() {
156
        return _responseCode;
1✔
157
    }
158

159
    /**
160
     * Returns the response message associated with this response.
161
     **/
162
    @Override
163
    public String getResponseMessage() {
164
        return _responseMessage;
1✔
165
    }
166

167
    @Override
168
    public String[] getHeaderFieldNames() {
169
        List<String> names = new ArrayList<>();
×
170
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
171
            names.add((String) e.nextElement());
×
172
        }
173
        return names.toArray(new String[0]);
×
174
    }
175

176
    /**
177
     * Returns the value for the specified header field. If no such field is defined, will return null.
178
     **/
179
    @Override
180
    public String getHeaderField(String fieldName) {
181
        String[] fields = (String[]) _headers.get(fieldName.toUpperCase());
1✔
182
        return fields == null ? null : fields[0];
1✔
183
    }
184

185
    @Override
186
    public String[] getHeaderFields(String fieldName) {
187
        String[] fields = (String[]) _headers.get(fieldName.toUpperCase());
1✔
188
        return fields == null ? new String[0] : fields;
1✔
189
    }
190

191
    @Override
192
    public String toString() {
193
        StringBuilder sb = new StringBuilder("HttpWebResponse [url=");
×
194
        sb.append(getURL()).append("; headers=");
×
195
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
196
            Object key = e.nextElement();
×
197
            String[] values = (String[]) _headers.get(key);
×
198
            for (String value : values) {
×
199
                sb.append("\n   ").append(key).append(": ").append(value);
×
200
            }
201
        }
×
202
        sb.append(" ]");
×
203
        return sb.toString();
×
204
    }
205

206
    @Override
207
    String getReferer() {
208
        return _referer;
1✔
209
    }
210

211
    // ------------------------------------- private members -------------------------------------
212

213
    /** The Constant FILE_ENCODING. */
214
    private static final String FILE_ENCODING = Charset.defaultCharset().displayName();
1✔
215

216
    /** The response code. */
217
    private int _responseCode = HttpURLConnection.HTTP_OK;
1✔
218

219
    /** The response message. */
220
    private String _responseMessage = "OK";
1✔
221

222
    /**
223
     * set the responseCode to the given code and message.
224
     *
225
     * @param code
226
     *            the code
227
     * @param message
228
     *            the message
229
     */
230
    private void setResponseCode(int code, String message) {
231
        _responseCode = code;
1✔
232
        _responseMessage = message;
1✔
233
    }
1✔
234

235
    /** The headers. */
236
    private Hashtable _headers = new Hashtable<>();
1✔
237

238
    /**
239
     * read the response Header for the given connection and set the response code and message accordingly.
240
     *
241
     * @param connection
242
     *            the connection
243
     *
244
     * @throws IOException
245
     *             Signals that an I/O exception has occurred.
246
     */
247
    private void readResponseHeader(HttpURLConnection connection) throws IOException {
248
        if (!needStatusWorkaround()) {
1!
249
            setResponseCode(connection.getResponseCode(), connection.getResponseMessage());
1✔
250
        } else {
251
            if (connection.getHeaderField(0) == null) {
×
252
                throw new UnknownHostException(connection.getURL().toExternalForm());
×
253
            }
254

255
            StringTokenizer st = new StringTokenizer(connection.getHeaderField(0));
×
256
            st.nextToken();
×
257
            if (!st.hasMoreTokens()) {
×
258
                setResponseCode(HttpURLConnection.HTTP_OK, "OK");
×
259
            } else {
260
                try {
261
                    setResponseCode(Integer.parseInt(st.nextToken()), getRemainingTokens(st));
×
262
                } catch (NumberFormatException e) {
×
263
                    setResponseCode(HttpURLConnection.HTTP_INTERNAL_ERROR, "Cannot parse response header");
×
264
                }
×
265
            }
266
        }
267
    }
1✔
268

269
    /**
270
     * Need status workaround.
271
     *
272
     * @return true, if successful
273
     */
274
    private boolean needStatusWorkaround() {
275
        final String jdkVersion = System.getProperty("java.version");
1✔
276
        return jdkVersion.startsWith("1.2") || jdkVersion.startsWith("1.3");
1!
277
    }
278

279
    /**
280
     * Gets the remaining tokens.
281
     *
282
     * @param st
283
     *            the st
284
     *
285
     * @return the remaining tokens
286
     */
287
    private String getRemainingTokens(StringTokenizer st) {
288
        StringBuilder messageBuffer = new StringBuilder(st.hasMoreTokens() ? st.nextToken() : "");
×
289
        while (st.hasMoreTokens()) {
×
290
            messageBuffer.append(' ').append(st.nextToken());
×
291
        }
292
        return messageBuffer.toString();
×
293
    }
294

295
    /**
296
     * Read headers.
297
     *
298
     * @param connection
299
     *            the connection
300
     *
301
     * @throws IOException
302
     *             Signals that an I/O exception has occurred.
303
     */
304
    private void readHeaders(URLConnection connection) throws IOException {
305
        loadHeaders(connection);
1✔
306
        if (connection instanceof HttpURLConnection) {
1✔
307
            readResponseHeader((HttpURLConnection) connection);
1✔
308
        } else {
309
            setResponseCode(HttpURLConnection.HTTP_OK, "OK");
1✔
310
            if (connection.getContentType().startsWith("text")) {
1!
311
                setContentTypeHeader(connection.getContentType() + "; charset=" + FILE_ENCODING);
1✔
312
            }
313
        }
314
    }
1✔
315

316
    /**
317
     * Load headers.
318
     *
319
     * @param connection
320
     *            the connection
321
     */
322
    private void loadHeaders(URLConnection connection) {
323
        if (HttpUnitOptions.isLoggingHttpHeaders()) {
1!
324
            System.out.println("Header:: " + connection.getHeaderField(0));
×
325
        }
326
        for (int i = 1; true; i++) {
1✔
327
            String headerFieldKey = connection.getHeaderFieldKey(i);
1✔
328
            String headerField = connection.getHeaderField(i);
1✔
329
            if (headerFieldKey == null || headerField == null) {
1!
330
                break;
×
331
            }
332
            if (HttpUnitOptions.isLoggingHttpHeaders()) {
1!
333
                System.out.println("Header:: " + headerFieldKey + ": " + headerField);
×
334
            }
335
            addHeader(headerFieldKey.toUpperCase(), headerField);
1✔
336
        }
337

338
        if (connection.getContentType() != null) {
1!
339
            setContentTypeHeader(connection.getContentType());
1✔
340
        }
341
    }
1✔
342

343
    /**
344
     * Adds the header.
345
     *
346
     * @param key
347
     *            the key
348
     * @param field
349
     *            the field
350
     */
351
    private void addHeader(String key, String field) {
352
        _headers.put(key, HttpUnitUtils.withNewValue((String[]) _headers.get(key), field));
1✔
353
    }
1✔
354

355
}
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