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

hazendaz / httpunit / 552

30 Oct 2025 07:58PM UTC coverage: 80.509% (-0.04%) from 80.553%
552

push

github

hazendaz
[gha] Update actions

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8249 of 10132 relevant lines covered (81.42%)

0.81 hits per line

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

84.03
/src/main/java/com/meterware/pseudoserver/WebResource.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.pseudoserver;
21

22
import com.meterware.httpunit.HttpUnitUtils;
23

24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.io.OutputStream;
27
import java.net.HttpURLConnection;
28
import java.nio.charset.Charset;
29
import java.nio.charset.StandardCharsets;
30
import java.util.Vector;
31

32
/**
33
 * A resource to be returned from the simulated server.
34
 **/
35
public class WebResource {
36

37
    static final String DEFAULT_CONTENT_TYPE = "text/html";
38

39
    private boolean _closesConnection;
40

41
    private byte[] _contents;
42
    private String _string;
43
    private InputStream _stream;
44

45
    private int _responseCode;
46
    private boolean _sendCharacterSet;
47
    private String _contentType = DEFAULT_CONTENT_TYPE;
1✔
48
    private String _characterSet = StandardCharsets.ISO_8859_1.name();
1✔
49
    private boolean _hasExplicitContentTypeHeader;
50
    private boolean _hasExplicitContentLengthHeader;
51
    private Vector _headers = new Vector<>();
1✔
52
    private boolean _isChunked;
53

54
    public WebResource(String contents) {
55
        this(contents, DEFAULT_CONTENT_TYPE);
1✔
56
    }
1✔
57

58
    public WebResource(String contents, String contentType) {
59
        this(contents, contentType, HttpURLConnection.HTTP_OK);
1✔
60
    }
1✔
61

62
    public WebResource(byte[] contents, String contentType) {
63
        this(contents, contentType, HttpURLConnection.HTTP_OK);
1✔
64
    }
1✔
65

66
    public void addHeader(String header) {
67
        _headers.addElement(header);
1✔
68
        if (header.toLowerCase().startsWith("content-type")) {
1✔
69
            _hasExplicitContentTypeHeader = true;
1✔
70
        }
71
        if (header.toLowerCase().startsWith("content-length")) {
1✔
72
            _hasExplicitContentLengthHeader = true;
1✔
73
        }
74
        if (header.trim().toLowerCase().startsWith("connection") && header.trim().toLowerCase().endsWith("close")) {
1!
75
            _closesConnection = true;
1✔
76
        }
77
        if (header.trim().toLowerCase().startsWith("transfer-encoding")
1✔
78
                && header.trim().toLowerCase().endsWith("chunked")) {
1!
79
            _isChunked = true;
1✔
80
        }
81
    }
1✔
82

83
    public void setCharacterSet(String characterSet) {
84
        _characterSet = characterSet;
1✔
85
    }
1✔
86

87
    public void setSendCharacterSet(boolean enabled) {
88
        _sendCharacterSet = enabled;
1✔
89
    }
1✔
90

91
    public void suppressAutomaticLengthHeader() {
92
        _hasExplicitContentLengthHeader = true;
×
93
    }
×
94

95
    public void suppressAutomaticContentTypeHeader() {
96
        _hasExplicitContentTypeHeader = true;
1✔
97
    }
1✔
98

99
    public WebResource(String contents, int responseCode) {
100
        this(contents, DEFAULT_CONTENT_TYPE, responseCode);
1✔
101
    }
1✔
102

103
    public WebResource(String contents, String contentType, int responseCode) {
1✔
104
        _string = contents;
1✔
105
        _contentType = contentType;
1✔
106
        _responseCode = responseCode;
1✔
107
    }
1✔
108

109
    public WebResource(byte[] contents, String contentType, int responseCode) {
1✔
110
        _contents = contents;
1✔
111
        _contentType = contentType;
1✔
112
        _responseCode = responseCode;
1✔
113
    }
1✔
114

115
    public WebResource(InputStream stream, String contentType, int responseCode) {
1✔
116
        _stream = stream;
1✔
117
        _contentType = contentType;
1✔
118
        _responseCode = responseCode;
1✔
119
        addHeader("Connection: close");
1✔
120
    }
1✔
121

122
    String[] getHeaders() {
123
        final Vector effectiveHeaders = (Vector) _headers.clone();
1✔
124
        if (!_hasExplicitContentTypeHeader) {
1✔
125
            effectiveHeaders.add(getContentTypeHeader());
1✔
126
        }
127
        if (_stream == null && !_hasExplicitContentLengthHeader && !isChunked()) {
1✔
128
            effectiveHeaders.add(getContentLengthHeader());
1✔
129
        }
130
        String[] headers = new String[effectiveHeaders.size()];
1✔
131
        effectiveHeaders.copyInto(headers);
1✔
132
        return headers;
1✔
133
    }
134

135
    private boolean isChunked() {
136
        return _isChunked;
1✔
137
    }
138

139
    boolean closesConnection() {
140
        return _closesConnection;
1✔
141
    }
142

143
    void writeTo(OutputStream outputStream) throws IOException {
144
        if (_stream == null) {
1✔
145
            outputStream.write(getContentsAsBytes());
1✔
146
        } else {
147
            byte[] buffer = new byte[8 * 1024];
1✔
148
            int count = 0;
1✔
149
            do {
150
                outputStream.write(buffer, 0, count);
1✔
151
                count = _stream.read(buffer, 0, buffer.length);
1✔
152
            } while (count != -1);
1✔
153
        }
154
    }
1✔
155

156
    static String toString(byte[] contentsAsBytes) {
157
        StringBuilder sb = new StringBuilder();
×
158
        for (byte contentsAsByte : contentsAsBytes) {
×
159
            sb.append(Integer.toHexString(contentsAsByte)).append(' ');
×
160
        }
161
        return sb.toString();
×
162
    }
163

164
    private byte[] getContentsAsBytes() {
165
        if (_contents != null) {
1✔
166
            return _contents;
1✔
167
        }
168
        if (_string != null) {
1!
169
            return _string.getBytes(getCharacterSet());
1✔
170
        }
171
        throw new IllegalStateException("Cannot get bytes from stream");
×
172
    }
173

174
    private String getContentTypeHeader() {
175
        return "Content-Type: " + _contentType + getCharacterSetParameter();
1✔
176
    }
177

178
    private String getContentLengthHeader() {
179
        return "Content-Length: " + getContentsAsBytes().length;
1✔
180
    }
181

182
    Charset getCharacterSet() {
183
        return Charset.forName(HttpUnitUtils.stripQuotes(_characterSet));
1✔
184
    }
185

186
    String getCharacterSetParameter() {
187
        if (!_sendCharacterSet) {
1✔
188
            return "";
1✔
189
        }
190
        return "; charset=" + _characterSet;
1✔
191
    }
192

193
    int getResponseCode() {
194
        return _responseCode;
1✔
195
    }
196

197
    @Override
198
    public String toString() {
199
        return "WebResource [code=" + _responseCode + "; type = " + _contentType + "; charset = " + _characterSet
×
200
                + "]\n" + getContentsAsString();
×
201
    }
202

203
    private String getContentsAsString() {
204
        if (_string != null) {
×
205
            return _string;
×
206
        }
207
        return "<< hex bytes >>";
×
208
    }
209

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