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

hazendaz / httpunit / 636

05 Dec 2025 03:27AM UTC coverage: 80.509%. Remained the same
636

push

github

hazendaz
Cleanup more old since tags

you guessed it, at this point going to jautodoc the rest so the warnings on builds go away ;)

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

78.57
/src/main/java/com/meterware/pseudoserver/ReceivedHttpMessage.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 java.io.ByteArrayInputStream;
23
import java.io.ByteArrayOutputStream;
24
import java.io.IOException;
25
import java.io.InputStream;
26
import java.io.InputStreamReader;
27
import java.io.Reader;
28
import java.util.Enumeration;
29
import java.util.Hashtable;
30

31
abstract class ReceivedHttpMessage {
32

33
    private static final int CR = 13;
34
    private static final int LF = 10;
35
    private Reader _reader;
36
    private Hashtable _headers = new Hashtable<>();
1✔
37
    private byte[] _requestBody;
38

39
    ReceivedHttpMessage(InputStream inputStream) throws IOException {
1✔
40
        interpretMessageHeader(readHeaderLine(inputStream));
1✔
41
        readHeaders(inputStream);
1✔
42
        readMessageBody(inputStream);
1✔
43
    }
1✔
44

45
    @Override
46
    public String toString() {
47
        StringBuilder sb = new StringBuilder(getClassName()).append("[ ");
1✔
48
        appendMessageHeader(sb);
1✔
49
        sb.append("\n");
1✔
50
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
1✔
51
            Object key = e.nextElement();
1✔
52
            sb.append("      ").append(key).append(": ").append(_headers.get(key)).append("\n");
1✔
53
        }
1✔
54
        sb.append("   body contains ").append(getBody().length).append(" byte(s)]");
1✔
55
        return sb.toString();
1✔
56
    }
57

58
    private String readHeaderLine(InputStream inputStream) throws IOException {
59
        return new String(readDelimitedChunk(inputStream));
1✔
60
    }
61

62
    private byte[] readDelimitedChunk(InputStream inputStream) throws IOException {
63
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
1✔
64
        int b = inputStream.read();
1✔
65
        while (b != CR) {
1✔
66
            baos.write(b);
1✔
67
            b = inputStream.read();
1✔
68
        }
69

70
        b = inputStream.read();
1✔
71
        if (b != LF) {
1!
72
            throw new IOException("Bad header line termination: " + b);
×
73
        }
74
        return baos.toByteArray();
1✔
75
    }
76

77
    void appendContents(StringBuilder sb) {
78
        for (Enumeration e = _headers.keys(); e.hasMoreElements();) {
×
79
            Object key = e.nextElement();
×
80
            sb.append("      ").append(key).append(": ").append(_headers.get(key)).append("\n");
×
81
        }
×
82
        sb.append("   body contains ").append(getBody().length).append(" byte(s)");
×
83
    }
×
84

85
    Reader getReader() {
86
        return _reader;
×
87
    }
88

89
    String getHeader(String name) {
90
        return (String) _headers.get(name.toUpperCase());
1✔
91
    }
92

93
    byte[] getBody() {
94
        return _requestBody;
1✔
95
    }
96

97
    private void readMessageBody(InputStream inputStream) throws IOException {
98
        if ("chunked".equalsIgnoreCase(getHeader("Transfer-Encoding"))) {
1✔
99
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
1✔
100
            while (getNextChunkLength(inputStream) > 0) {
1✔
101
                baos.write(readDelimitedChunk(inputStream));
1✔
102
            }
103
            flushChunkTrailer(inputStream);
1✔
104
            _requestBody = baos.toByteArray();
1✔
105
        } else {
1✔
106
            int totalExpected = getContentLength();
1✔
107
            ByteArrayOutputStream baos = new ByteArrayOutputStream(totalExpected);
1✔
108
            byte[] buffer = new byte[1024];
1✔
109
            int total = 0;
1✔
110
            int count = -1;
1✔
111
            while (total < totalExpected && (count = inputStream.read(buffer)) != -1) {
1!
112
                baos.write(buffer, 0, count);
1✔
113
                total += count;
1✔
114
            }
115
            baos.flush();
1✔
116
            _requestBody = baos.toByteArray();
1✔
117
        }
118
        _reader = new InputStreamReader(new ByteArrayInputStream(_requestBody));
1✔
119
    }
1✔
120

121
    private void flushChunkTrailer(InputStream inputStream) throws IOException {
122
        byte[] line;
123
        do {
124
            line = readDelimitedChunk(inputStream);
1✔
125
        } while (line.length > 0);
1!
126
    }
1✔
127

128
    private int getNextChunkLength(InputStream inputStream) throws IOException {
129
        try {
130
            return Integer.parseInt(readHeaderLine(inputStream), 16);
1✔
131
        } catch (NumberFormatException e) {
×
132
            throw new IOException("Unabled to read chunk length: " + e);
×
133
        }
134
    }
135

136
    private int getContentLength() {
137
        try {
138
            return Integer.parseInt(getHeader("Content-Length"));
1✔
139
        } catch (NumberFormatException e) {
1✔
140
            return 0;
1✔
141
        }
142
    }
143

144
    private void readHeaders(InputStream inputStream) throws IOException {
145
        String lastHeader = null;
1✔
146

147
        String header = readHeaderLine(inputStream);
1✔
148
        while (header.length() > 0) {
1✔
149
            if (header.charAt(0) <= ' ') {
1!
150
                if (lastHeader == null) {
×
151
                    continue;
×
152
                }
153
                _headers.put(lastHeader, _headers.get(lastHeader) + header.trim());
×
154
            } else {
155
                lastHeader = header.substring(0, header.indexOf(':')).toUpperCase();
1✔
156
                _headers.put(lastHeader, header.substring(header.indexOf(':') + 1).trim());
1✔
157
            }
158
            header = readHeaderLine(inputStream);
1✔
159
        }
160
    }
1✔
161

162
    private String getClassName() {
163
        return getClass().getName().substring(getClass().getName().lastIndexOf('.') + 1);
1✔
164
    }
165

166
    abstract void appendMessageHeader(StringBuilder sb);
167

168
    abstract void interpretMessageHeader(String messageHeader);
169

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