• 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

82.64
/src/main/java/com/meterware/servletunit/ServletUnitHttpRequest.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.servletunit;
9

10
import com.meterware.httpunit.HttpUnitUtils;
11
import com.meterware.httpunit.WebClient;
12
import com.meterware.httpunit.WebRequest;
13

14
import jakarta.servlet.AsyncContext;
15
import jakarta.servlet.DispatcherType;
16
import jakarta.servlet.RequestDispatcher;
17
import jakarta.servlet.ServletConnection;
18
import jakarta.servlet.ServletContext;
19
import jakarta.servlet.ServletException;
20
import jakarta.servlet.ServletInputStream;
21
import jakarta.servlet.ServletRequest;
22
import jakarta.servlet.ServletResponse;
23
import jakarta.servlet.http.Cookie;
24
import jakarta.servlet.http.HttpServletRequest;
25
import jakarta.servlet.http.HttpServletResponse;
26
import jakarta.servlet.http.HttpSession;
27
import jakarta.servlet.http.HttpUpgradeHandler;
28
import jakarta.servlet.http.Part;
29

30
import java.io.BufferedReader;
31
import java.io.IOException;
32
import java.io.InputStreamReader;
33
import java.net.MalformedURLException;
34
import java.nio.charset.Charset;
35
import java.nio.charset.StandardCharsets;
36
import java.util.ArrayList;
37
import java.util.Base64;
38
import java.util.Collection;
39
import java.util.Collections;
40
import java.util.Date;
41
import java.util.Dictionary;
42
import java.util.Enumeration;
43
import java.util.Hashtable;
44
import java.util.Iterator;
45
import java.util.List;
46
import java.util.Locale;
47
import java.util.Map;
48
import java.util.StringTokenizer;
49

50
/**
51
 * The Class ServletUnitHttpRequest.
52
 */
53
class ServletUnitHttpRequest implements HttpServletRequest {
54

55
    /** The input stream. */
56
    private ServletInputStreamImpl _inputStream;
57

58
    /** The locales. */
59
    private List _locales;
60

61
    /** The protocol. */
62
    private String _protocol;
63

64
    /** The secure. */
65
    private boolean _secure;
66

67
    /** The request context. */
68
    private RequestContext _requestContext;
69

70
    /** The charset. */
71
    private String _charset;
72

73
    /** The got reader. */
74
    private boolean _gotReader;
75

76
    /** The got input stream. */
77
    private boolean _gotInputStream;
78

79
    /** The reader. */
80
    private BufferedReader _reader;
81

82
    /** The server port. */
83
    private int _serverPort;
84

85
    /** The server name. */
86
    private String _serverName;
87

88
    /**
89
     * Constructs a ServletUnitHttpRequest from a WebRequest object.
90
     *
91
     * @param servletRequest
92
     *            the servlet request
93
     * @param request
94
     *            the request
95
     * @param context
96
     *            the context
97
     * @param clientHeaders
98
     *            the client headers
99
     * @param messageBody
100
     *            the message body
101
     *
102
     * @throws MalformedURLException
103
     *             the malformed URL exception
104
     */
105
    ServletUnitHttpRequest(ServletMetaData servletRequest, WebRequest request, ServletUnitContext context,
106
            Dictionary clientHeaders, byte[] messageBody) throws MalformedURLException {
1✔
107
        if (context == null) {
1!
108
            throw new IllegalArgumentException("Context must not be null");
×
109
        }
110

111
        _servletRequest = servletRequest;
1✔
112
        _request = request;
1✔
113
        _context = context;
1✔
114
        _headers = new WebClient.HeaderDictionary();
1✔
115
        _headers.addEntries(clientHeaders);
1✔
116
        _headers.addEntries(request.getHeaders());
1✔
117
        setCookiesFromHeader(_headers);
1✔
118
        _messageBody = messageBody;
1✔
119
        _protocol = request.getURL().getProtocol().toLowerCase(Locale.ENGLISH);
1✔
120
        _secure = _protocol.endsWith("s");
1✔
121
        _serverName = request.getURL().getHost();
1✔
122
        _serverPort = request.getURL().getPort();
1✔
123
        if (_serverPort == -1) {
1✔
124
            _serverPort = request.getURL().getDefaultPort();
1✔
125
        }
126

127
        _requestContext = new RequestContext(request.getURL());
1✔
128
        String contentTypeHeader = (String) _headers.get("Content-Type");
1✔
129
        if (contentTypeHeader != null) {
1✔
130
            String[] res = HttpUnitUtils.parseContentTypeHeader(contentTypeHeader);
1✔
131
            _charset = res[1];
1✔
132
            _requestContext.setMessageEncoding(_charset);
1✔
133
        }
134
        if (_headers.get("Content-Length") == null) {
1!
135
            _headers.put("Content-Length", Integer.toString(messageBody.length));
1✔
136
        }
137

138
        boolean setBody =
1!
139
                // pre [ 1509117 ] getContentType()
140
                // _messageBody != null && (_contentType == null || _contentType.indexOf( "x-www-form-urlencoded" ) >= 0
141
                // );
142
                // patch version:
143
                _messageBody != null
144
                        && (contentTypeHeader == null || contentTypeHeader.indexOf("x-www-form-urlencoded") >= 0);
1✔
145
        if (setBody) {
1✔
146
            _requestContext.setMessageBody(_messageBody);
1✔
147
        }
148
    }
1✔
149

150
    // ----------------------------------------- HttpServletRequest methods --------------------------
151

152
    /**
153
     * Returns the name of the authentication scheme used to protect the servlet, for example, "BASIC" or "SSL," or null
154
     * if the servlet was not protected.
155
     **/
156
    @Override
157
    public String getAuthType() {
158
        return null;
1✔
159
    }
160

161
    /**
162
     * Returns the query string that is contained in the request URL after the path.
163
     **/
164
    @Override
165
    public String getQueryString() {
166
        return _request.getQueryString();
1✔
167
    }
168

169
    /**
170
     * Returns an array containing all of the Cookie objects the client sent with this request. This method returns null
171
     * if no cookies were sent.
172
     **/
173
    @Override
174
    public Cookie[] getCookies() {
175
        if (_cookies.size() == 0) {
1✔
176
            return null;
1✔
177
        }
178
        return _cookies.toArray(new Cookie[0]);
1✔
179
    }
180

181
    /**
182
     * Returns the value of the specified request header as an int. If the request does not have a header of the
183
     * specified name, this method returns -1. If the header cannot be converted to an integer, this method throws a
184
     * NumberFormatException.
185
     **/
186
    @Override
187
    public int getIntHeader(String name) {
188
        return Integer.parseInt(getHeader(name));
1✔
189
    }
190

191
    /**
192
     * Returns the value of the specified request header as a long value that represents a Date object. Use this method
193
     * with headers that contain dates, such as If-Modified-Since. <br>
194
     * The date is returned as the number of milliseconds since January 1, 1970 GMT. The header name is case
195
     * insensitive. If the request did not have a header of the specified name, this method returns -1. If the header
196
     * can't be converted to a date, the method throws an IllegalArgumentException.
197
     **/
198
    @Override
199
    public long getDateHeader(String name) {
200
        try {
201
            String dateString = getHeader(name);
1✔
202
            Date headerDate = new Date(dateString);
1✔
203
            return headerDate.getTime();
1✔
204
        } catch (Exception e) {
1✔
205
            return -1;
1✔
206
        }
207
    }
208

209
    /**
210
     * Returns the value of the specified request header as a String. If the request did not include a header of the
211
     * specified name, this method returns null. The header name is case insensitive. You can use this method with any
212
     * request header.
213
     **/
214
    @Override
215
    public String getHeader(String name) {
216
        return (String) _headers.get(name);
1✔
217
    }
218

219
    /**
220
     * Returns an enumeration of all the header names this request contains. If the request has no headers, this method
221
     * returns an empty enumeration. Some servlet containers do not allow do not allow servlets to access headers using
222
     * this method, in which case this method returns null.
223
     **/
224
    @Override
225
    public Enumeration getHeaderNames() {
226
        return _headers.keys();
1✔
227
    }
228

229
    /**
230
     * Returns the part of this request's URL that calls the servlet. This includes either the servlet name or a path to
231
     * the servlet, but does not include any extra path information or a query string.
232
     **/
233
    @Override
234
    public String getServletPath() {
235
        return _servletRequest.getServletPath();
1✔
236
    }
237

238
    /**
239
     * Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT.
240
     **/
241
    @Override
242
    public String getMethod() {
243
        return _request.getMethod();
1✔
244
    }
245

246
    /**
247
     * Returns any extra path information associated with the URL the client sent when it made this request. The extra
248
     * path information follows the servlet path but precedes the query string. This method returns null if there was no
249
     * extra path information.
250
     **/
251
    @Override
252
    public String getPathInfo() {
253
        return _servletRequest.getPathInfo();
1✔
254
    }
255

256
    /**
257
     * Returns any extra path information after the servlet name but before the query string, and translates it to a
258
     * real path. If the URL does not have any extra path information, this method returns null.
259
     **/
260
    @Override
261
    public String getPathTranslated() {
262
        return null;
×
263
    }
264

265
    /**
266
     * Checks whether the requested session ID came in as a cookie.
267
     **/
268
    @Override
269
    public boolean isRequestedSessionIdFromCookie() {
270
        return _sessionID != null;
×
271
    }
272

273
    /**
274
     * Returns the login of the user making this request, if the user has been authenticated, or null if the user has
275
     * not been authenticated. Whether the user name is sent with each subsequent request depends on the browser and
276
     * type of authentication.
277
     **/
278
    @Override
279
    public String getRemoteUser() {
280
        return _userName;
1✔
281
    }
282

283
    /**
284
     * Returns the session ID specified by the client. This may not be the same as the ID of the actual session in use.
285
     * For example, if the request specified an old (expired) session ID and the server has started a new session, this
286
     * method gets a new session with a new ID. If the request did not specify a session ID, this method returns null.
287
     **/
288
    @Override
289
    public String getRequestedSessionId() {
290
        return _sessionID;
1✔
291
    }
292

293
    /**
294
     * Returns the part of this request's URL from the protocol name up to the query string in the first line of the
295
     * HTTP request.
296
     **/
297
    @Override
298
    public String getRequestURI() {
299
        return _requestContext.getRequestURI();
1✔
300
    }
301

302
    /**
303
     * Returns the current HttpSession associated with this request or, if there is no current session and create is
304
     * true, returns a new session. <br>
305
     * If create is false and the request has no valid HttpSession, this method returns null.
306
     **/
307
    @Override
308
    public HttpSession getSession(boolean create) {
309
        _session = _context.getValidSession(getRequestedSessionId(), _session, create);
1✔
310
        return _session;
1✔
311
    }
312

313
    /**
314
     * Returns the current session associated with this request, or if the request does not have a session, creates one.
315
     **/
316
    @Override
317
    public HttpSession getSession() {
318
        return getSession(true);
1✔
319
    }
320

321
    /**
322
     * Checks whether the requested session ID is still valid.
323
     **/
324
    @Override
325
    public boolean isRequestedSessionIdValid() {
326
        return false;
×
327
    }
328

329
    /**
330
     * Checks whether the requested session ID came in as part of the request URL.
331
     **/
332
    @Override
333
    public boolean isRequestedSessionIdFromURL() {
334
        return false;
×
335
    }
336

337
    // --------------------------------- ServletRequest methods ----------------------------------------------------
338

339
    /**
340
     * Returns the length, in bytes, of the content contained in the request and sent by way of the input stream or -1
341
     * if the length is not known.
342
     **/
343
    @Override
344
    public int getContentLength() {
345
        return getIntHeader("Content-length");
1✔
346
    }
347

348
    /**
349
     * Returns the value of the named attribute as an <code>Object</code>. This method allows the servlet engine to give
350
     * the servlet custom information about a request. This method returns <code>null</code> if no attribute of the
351
     * given name exists.
352
     **/
353
    @Override
354
    public Object getAttribute(String name) {
355
        return _attributes.get(name);
1✔
356
    }
357

358
    /**
359
     * Returns an <code>Enumeration</code> containing the names of the attributes available to this request. This method
360
     * returns an empty <code>Enumeration</code> if the request has no attributes available to it.
361
     **/
362
    @Override
363
    public Enumeration getAttributeNames() {
364
        return _attributes.keys();
1✔
365
    }
366

367
    /**
368
     * Retrieves binary data from the body of the request as a {@link ServletInputStream}, which gives you the ability
369
     * to read one line at a time.
370
     *
371
     * @return a {@link ServletInputStream} object containing the body of the request
372
     *
373
     * @exception IllegalStateException
374
     *                if the {@link #getReader} method has already been called for this request
375
     * @exception IOException
376
     *                if an input or output exception occurred
377
     */
378
    @Override
379
    public ServletInputStream getInputStream() throws IOException {
380
        if (_gotReader) {
1✔
381
            throw new IllegalStateException("getReader() has already been called for this request");
1✔
382
        }
383
        initializeInputStream();
1✔
384
        _gotInputStream = true;
1✔
385
        return _inputStream;
1✔
386
    }
387

388
    /**
389
     * initialize the inputStream.
390
     */
391
    private void initializeInputStream() {
392
        if (_inputStream == null) {
1✔
393
            _inputStream = new ServletInputStreamImpl(_messageBody);
1✔
394
        }
395
    }
1✔
396

397
    /**
398
     * Returns the name of the character encoding style used in this request. This method returns <code>null</code> if
399
     * the request does not use character encoding.
400
     **/
401
    @Override
402
    public String getCharacterEncoding() {
403
        return _charset;
1✔
404
    }
405

406
    /**
407
     * Returns an <code>Enumeration</code> of <code>String</code> objects containing the names of the parameters
408
     * contained in this request. If the request has no parameters or if the input stream is empty, returns an empty
409
     * <code>Enumeration</code>. The input stream is empty when all the data returned by {@link #getInputStream} has
410
     * been read.
411
     **/
412
    @Override
413
    public Enumeration getParameterNames() {
414
        return _requestContext.getParameterNames();
×
415
    }
416

417
    /**
418
     * Returns the MIME type of the content of the request, or <code>null</code> if the type is not known. Same as the
419
     * value of the CGI variable CONTENT_TYPE.
420
     **/
421
    @Override
422
    public String getContentType() {
423
        return this.getHeader("Content-Type");
1✔
424
    }
425

426
    /**
427
     * Returns the value of a request parameter as a <code>String</code>, or <code>null</code> if the parameter does not
428
     * exist. Request parameters are extra information sent with the request.
429
     **/
430
    @Override
431
    public String getParameter(String name) {
432
        String[] parameters = getParameterValues(name);
1✔
433
        return parameters == null ? null : parameters[0];
1✔
434
    }
435

436
    /**
437
     * Returns an array of <code>String</code> objects containing all of the values the given request parameter has, or
438
     * <code>null</code> if the parameter does not exist. For example, in an HTTP servlet, this method returns an array
439
     * of <code>String</code> objects containing the values of a query string or posted form.
440
     **/
441
    @Override
442
    public String[] getParameterValues(String name) {
443
        return _requestContext.getParameterValues(name);
1✔
444
    }
445

446
    /**
447
     * Returns the name and version of the protocol the request uses in the form
448
     * <i>protocol/majorVersion.minorVersion</i>, for example, HTTP/1.1.
449
     **/
450
    @Override
451
    public String getProtocol() {
452
        return "HTTP/1.1";
×
453
    }
454

455
    /**
456
     * Returns the name of the scheme used to make this request, for example, <code>http</code>, <code>https</code>, or
457
     * <code>ftp</code>. Different schemes have different rules for constructing URLs, as noted in RFC 1738.
458
     **/
459
    @Override
460
    public String getScheme() {
461
        return _protocol;
1✔
462
    }
463

464
    /**
465
     * Returns the fully qualified name of the client that sent the request.
466
     **/
467
    @Override
468
    public String getRemoteHost() {
469
        return "localhost";
×
470
    }
471

472
    /**
473
     * Returns the host name of the server that received the request.
474
     **/
475
    @Override
476
    public String getServerName() {
477
        return _serverName;
1✔
478
    }
479

480
    /**
481
     * Returns the port number on which this request was received.
482
     **/
483
    @Override
484
    public int getServerPort() {
485
        return _serverPort;
1✔
486
    }
487

488
    /**
489
     * Returns the body of the request as a <code>BufferedReader</code> that translates character set encodings.
490
     *
491
     * @return the reader
492
     **/
493
    @Override
494
    public BufferedReader getReader() throws IOException {
495
        if (_gotInputStream) {
1✔
496
            throw new IllegalStateException("getInputStream() has already been called on this request");
1✔
497
        }
498
        if (_reader == null) {
1✔
499
            initializeInputStream();
1✔
500
            String encoding = getCharacterEncoding();
1✔
501
            if (encoding == null) {
1!
502
                encoding = StandardCharsets.ISO_8859_1.name();
1✔
503
            }
504
            _reader = new BufferedReader(new InputStreamReader(_inputStream, Charset.forName(encoding)));
1✔
505
            _gotReader = true;
1✔
506
        }
507
        return _reader;
1✔
508
    }
509

510
    /**
511
     * Returns the Internet Protocol (IP) address of the client that sent the request.
512
     **/
513
    @Override
514
    public String getRemoteAddr() {
515
        return LOOPBACK_ADDRESS;
×
516
    }
517

518
    /**
519
     * Stores an attribute in the context of this request. Attributes are reset between requests.
520
     **/
521
    @Override
522
    public void setAttribute(String key, Object o) {
523
        if (o == null) {
1✔
524
            _attributes.remove(key);
1✔
525
        } else {
526
            _attributes.put(key, o);
1✔
527
        }
528
    }
1✔
529

530
    // --------------------------------- methods added to ServletRequest in Servlet API 2.2
531
    // ------------------------------------------------
532

533
    /**
534
     * Returns a boolean indicating whether this request was made using a secure channel, such as HTTPS.
535
     **/
536
    @Override
537
    public boolean isSecure() {
538
        return _secure;
1✔
539
    }
540

541
    /**
542
     * Returns the preferred Locale that the client will accept content in, based on the Accept-Language header. If the
543
     * client request doesn't provide an Accept-Language header, this method returns the default locale for the server.
544
     **/
545
    @Override
546
    public Locale getLocale() {
547
        return (Locale) getPreferredLocales().get(0);
1✔
548
    }
549

550
    /**
551
     * Returns an Enumeration of Locale objects indicating, in decreasing order starting with the preferred locale, the
552
     * locales that are acceptable to the client based on the Accept-Language header. If the client request doesn't
553
     * provide an Accept-Language header, this method returns an Enumeration containing one Locale, the default locale
554
     * for the server.
555
     **/
556
    @Override
557
    public java.util.Enumeration getLocales() {
558
        return Collections.enumeration(getPreferredLocales());
1✔
559
    }
560

561
    /**
562
     * Parses the accept-language header to obtain a list of preferred locales.
563
     *
564
     * @return the preferred locales, sorted by qvalue
565
     */
566
    private List getPreferredLocales() {
567
        if (_locales == null) {
1✔
568
            _locales = new ArrayList<>();
1✔
569
            String languages = getHeader("accept-language");
1✔
570
            if (languages == null) {
1✔
571
                _locales.add(Locale.getDefault());
1✔
572
            } else {
573
                StringTokenizer st = new StringTokenizer(languages, ",");
1✔
574
                ArrayList al = new ArrayList<>();
1✔
575
                while (st.hasMoreTokens()) {
1✔
576
                    String token = st.nextToken();
1✔
577
                    al.add(new PrioritizedLocale(token));
1✔
578
                }
1✔
579
                Collections.sort(al);
1✔
580
                for (Iterator iterator = al.iterator(); iterator.hasNext();) {
1✔
581
                    _locales.add(((PrioritizedLocale) iterator.next()).getLocale());
1✔
582
                }
583
            }
584
        }
585
        return _locales;
1✔
586
    }
587

588
    /**
589
     * Removes an attribute from this request. This method is not generally needed as attributes only persist as long as
590
     * the request is being handled.
591
     **/
592
    @Override
593
    public void removeAttribute(String name) {
594
        _attributes.remove(name);
×
595
    }
×
596

597
    /**
598
     * Returns a RequestDispatcher object that acts as a wrapper for the resource located at the given path. A
599
     * RequestDispatcher object can be used to forward a request to the resource or to include the resource in a
600
     * response. The resource can be dynamic or static. The pathname specified may be relative, although it cannot
601
     * extend outside the current servlet context. If the path begins with a "/" it is interpreted as relative to the
602
     * current context root. This method returns null if the servlet container cannot return a RequestDispatcher. The
603
     * difference between this method and ServletContext.getRequestDispatcher(java.lang.String) is that this method can
604
     * take a relative path.
605
     **/
606
    @Override
607
    public RequestDispatcher getRequestDispatcher(String path) {
608
        try {
609
            if (!path.startsWith("/")) {
1✔
610
                path = combinedPath(getServletPath(), path);
1✔
611
            }
612
            return _servletRequest.getServlet().getServletConfig().getServletContext().getRequestDispatcher(path);
1✔
613
        } catch (ServletException e) {
×
614
            return null;
×
615
        }
616
    }
617

618
    /**
619
     * Combined path.
620
     *
621
     * @param basePath
622
     *            the base path
623
     * @param relativePath
624
     *            the relative path
625
     *
626
     * @return the string
627
     */
628
    private String combinedPath(String basePath, String relativePath) {
629
        if (basePath.indexOf('/') < 0) {
1!
630
            return relativePath;
×
631
        }
632
        return basePath.substring(0, basePath.lastIndexOf('/')) + '/' + relativePath;
1✔
633
    }
634

635
    // --------------------------------- methods added to HttpServletRequest in Servlet API 2.2
636
    // ------------------------------------------------
637

638
    /**
639
     * Returns a java.security.Principal object containing the name of the current authenticated user. If the user has
640
     * not been authenticated, the method returns null.
641
     **/
642
    @Override
643
    public java.security.Principal getUserPrincipal() {
644
        return null;
×
645
    }
646

647
    /**
648
     * Returns a boolean indicating whether the authenticated user is included in the specified logical "role". Roles
649
     * and role membership can be defined using deployment descriptors. If the user has not been authenticated, the
650
     * method returns false.
651
     **/
652
    @Override
653
    public boolean isUserInRole(String role) {
654
        if (_roles == null) {
1✔
655
            return false;
1✔
656
        }
657
        for (String _role : _roles) {
1✔
658
            if (role.equals(_role)) {
1✔
659
                return true;
1✔
660
            }
661
        }
662
        return false;
1✔
663
    }
664

665
    /**
666
     * Returns all the values of the specified request header as an Enumeration of String objects.
667
     **/
668
    @Override
669
    public java.util.Enumeration getHeaders(String name) {
670
        List list = new ArrayList<>();
1✔
671
        if (_headers.containsKey(name)) {
1!
672
            list.add(_headers.get(name));
1✔
673
        }
674
        return Collections.enumeration(list);
1✔
675
    }
676

677
    /**
678
     * Returns the portion of the request URI that indicates the context of the request. The context path always comes
679
     * first in a request URI. The path starts with a "/" character but does not end with a "/" character. For servlets
680
     * in the default (root) context, this method returns "".
681
     **/
682
    @Override
683
    public String getContextPath() {
684
        return _context.getContextPath();
1✔
685
    }
686

687
    // --------------------------------------- methods added to ServletRequest in Servlet API 2.3
688
    // ----------------------------
689

690
    /**
691
     * Returns a java.util.Map of the parameters of this request. Request parameters are extra information sent with the
692
     * request. For HTTP servlets, parameters are contained in the query string or posted form data.
693
     **/
694
    @Override
695
    public Map getParameterMap() {
696
        return _requestContext.getParameterMap();
1✔
697
    }
698

699
    /**
700
     * Overrides the name of the character encoding used in the body of this request. This method must be called prior
701
     * to reading request parameters or reading input using getReader().
702
     **/
703
    @Override
704
    public void setCharacterEncoding(String charset) {
705
        _charset = charset;
1✔
706
        _requestContext.setMessageEncoding(charset);
1✔
707
    }
1✔
708

709
    // --------------------------------------- methods added to HttpServletRequest in Servlet API 2.3
710
    // ----------------------------
711

712
    /**
713
     * Reconstructs the URL the client used to make the request. The returned URL contains a protocol, server name, port
714
     * number, and server path, but it does not include query string parameters. Because this method returns a
715
     * StringBuffer, not a string, you can modify the URL easily, for example, to append query parameters. This method
716
     * is useful for creating redirect messages and for reporting errors.
717
     */
718
    @Override
719
    public StringBuffer getRequestURL() {
720
        StringBuilder url = new StringBuilder();
1✔
721
        try {
722
            url.append(_request.getURL().getProtocol()).append("://");
1✔
723
            url.append(_request.getURL().getHost());
1✔
724
            String portPortion = _request.getURL().getPort() == -1 ? "" : ":" + _request.getURL().getPort();
1✔
725
            url.append(portPortion);
1✔
726
            url.append(_request.getURL().getPath());
1✔
727
        } catch (MalformedURLException e) {
×
728
            throw new RuntimeException("unable to read URL from request: " + _request);
×
729
        }
1✔
730
        return new StringBuffer(url);
1✔
731
    }
732

733
    // --------------------------------------- methods added to ServletRequest in Servlet API 2.4
734
    // ----------------------------
735

736
    @Override
737
    public int getRemotePort() {
738
        return 0; // To change body of implemented methods use File | Settings | File Templates.
×
739
    }
740

741
    @Override
742
    public String getLocalName() {
743
        return "localhost";
×
744
    }
745

746
    @Override
747
    public String getLocalAddr() {
748
        return "127.0.0.1";
×
749
    }
750

751
    @Override
752
    public int getLocalPort() {
753
        return 0; // To change body of implemented methods use File | Settings | File Templates.
×
754
    }
755

756
    // --------------------------------------------- package members ----------------------------------------------
757

758
    /**
759
     * Adds the cookie.
760
     *
761
     * @param cookie
762
     *            the cookie
763
     */
764
    private void addCookie(Cookie cookie) {
765
        _cookies.add(cookie);
1✔
766
        if (cookie.getName().equalsIgnoreCase(ServletUnitHttpSession.SESSION_COOKIE_NAME)) {
1✔
767
            _sessionID = cookie.getValue();
1✔
768
        }
769
    }
1✔
770

771
    /**
772
     * Gets the servlet session.
773
     *
774
     * @return the servlet session
775
     */
776
    private ServletUnitHttpSession getServletSession() {
777
        return (ServletUnitHttpSession) getSession();
1✔
778
    }
779

780
    /**
781
     * Read form authentication.
782
     */
783
    void readFormAuthentication() {
784
        if (getSession( /* create */ false) != null) {
1✔
785
            recordAuthenticationInfo(getServletSession().getUserName(), getServletSession().getRoles());
1✔
786
        }
787
    }
1✔
788

789
    /**
790
     * Read basic authentication.
791
     */
792
    void readBasicAuthentication() {
793
        String authorizationHeader = (String) _headers.get("Authorization");
1✔
794

795
        if (authorizationHeader != null) {
1✔
796
            String userAndPassword = new String(Base64.getDecoder().decode(authorizationHeader
1✔
797
                    .substring(authorizationHeader.indexOf(' ') + 1).getBytes(StandardCharsets.UTF_8)),
1✔
798
                    StandardCharsets.UTF_8);
799
            int colonPos = userAndPassword.indexOf(':');
1✔
800
            recordAuthenticationInfo(userAndPassword.substring(0, colonPos),
1✔
801
                    toArray(userAndPassword.substring(colonPos + 1)));
1✔
802
        }
803
    }
1✔
804

805
    /**
806
     * To array.
807
     *
808
     * @param roleList
809
     *            the role list
810
     *
811
     * @return the string[]
812
     */
813
    static String[] toArray(String roleList) {
814
        StringTokenizer st = new StringTokenizer(roleList, ",");
1✔
815
        String[] result = new String[st.countTokens()];
1✔
816
        for (int i = 0; i < result.length; i++) {
1✔
817
            result[i] = st.nextToken();
1✔
818
        }
819
        return result;
1✔
820
    }
821

822
    /**
823
     * Record authentication info.
824
     *
825
     * @param userName
826
     *            the user name
827
     * @param roles
828
     *            the roles
829
     */
830
    void recordAuthenticationInfo(String userName, String[] roles) {
831
        _userName = userName;
1✔
832
        _roles = roles;
1✔
833
    }
1✔
834

835
    // --------------------------------------------- private members ----------------------------------------------
836

837
    /** The Constant LOOPBACK_ADDRESS. */
838
    private static final String LOOPBACK_ADDRESS = "127.0.0.1";
839

840
    /** The request. */
841
    private WebRequest _request;
842

843
    /** The servlet request. */
844
    private ServletMetaData _servletRequest;
845

846
    /** The headers. */
847
    private WebClient.HeaderDictionary _headers;
848

849
    /** The context. */
850
    private ServletUnitContext _context;
851

852
    /** The session. */
853
    private ServletUnitHttpSession _session;
854

855
    /** The attributes. */
856
    private Hashtable _attributes = new Hashtable<>();
1✔
857

858
    /** The cookies. */
859
    private List<Cookie> _cookies = new ArrayList<>();
1✔
860

861
    /** The session ID. */
862
    private String _sessionID;
863

864
    /** The message body. */
865
    private byte[] _messageBody;
866

867
    /** The user name. */
868
    private String _userName;
869

870
    /** The roles. */
871
    private String[] _roles;
872

873
    /**
874
     * Throw not implemented yet.
875
     */
876
    private void throwNotImplementedYet() {
877
        throw new RuntimeException("Not implemented yet");
×
878
    }
879

880
    /**
881
     * Sets the cookies from header.
882
     *
883
     * @param clientHeaders
884
     *            the new cookies from header
885
     */
886
    private void setCookiesFromHeader(Dictionary clientHeaders) {
887
        String cookieHeader = (String) clientHeaders.get("Cookie");
1✔
888
        if (cookieHeader == null) {
1✔
889
            return;
1✔
890
        }
891

892
        StringTokenizer st = new StringTokenizer(cookieHeader, ",;=", true);
1✔
893
        String lastToken = st.nextToken();
1✔
894
        while (st.hasMoreTokens()) {
1✔
895
            String token = st.nextToken();
1✔
896
            if (token.equals("=") && st.hasMoreTokens()) {
1!
897
                addCookie(new Cookie(lastToken.trim(), st.nextToken().trim()));
1✔
898
            }
899
            lastToken = token;
1✔
900
        }
1✔
901
    }
1✔
902

903
    /**
904
     * The Class PrioritizedLocale.
905
     */
906
    static class PrioritizedLocale implements Comparable {
907

908
        /** The locale. */
909
        private Locale _locale;
910

911
        /** The priority. */
912
        private float _priority;
913

914
        /**
915
         * Instantiates a new prioritized locale.
916
         *
917
         * @param languageSpec
918
         *            the language spec
919
         */
920
        PrioritizedLocale(String languageSpec) {
1✔
921
            int semiIndex = languageSpec.indexOf(';');
1✔
922
            if (semiIndex < 0) {
1✔
923
                _priority = 1;
1✔
924
                _locale = parseLocale(languageSpec);
1✔
925
            } else {
926
                _priority = Float.parseFloat(languageSpec.substring(languageSpec.indexOf('=', semiIndex) + 1));
1✔
927
                _locale = parseLocale(languageSpec.substring(0, semiIndex));
1✔
928
            }
929
        }
1✔
930

931
        /**
932
         * Parses the locale.
933
         *
934
         * @param range
935
         *            the range
936
         *
937
         * @return the locale
938
         */
939
        private Locale parseLocale(String range) {
940
            range = range.trim();
1✔
941
            int dashIndex = range.indexOf('-');
1✔
942
            if (dashIndex < 0) {
1✔
943
                return new Locale(range, "");
1✔
944
            }
945
            return new Locale(range.substring(0, dashIndex), range.substring(dashIndex + 1));
1✔
946
        }
947

948
        /**
949
         * Gets the locale.
950
         *
951
         * @return the locale
952
         */
953
        public Locale getLocale() {
954
            return _locale;
1✔
955
        }
956

957
        @Override
958
        public int compareTo(Object o) {
959
            if (!(o instanceof PrioritizedLocale)) {
1!
960
                throw new IllegalArgumentException("may only combine with other prioritized locales");
×
961
            }
962
            PrioritizedLocale other = (PrioritizedLocale) o;
1✔
963
            return _priority == other._priority ? _locale.getLanguage().compareTo(other._locale.getLanguage())
1!
964
                    : _priority < other._priority ? +1 : -1;
1✔
965
        }
966

967
    }
968

969
    @Override
970
    public ServletContext getServletContext() {
971
        try {
972
            return _servletRequest.getServlet().getServletConfig().getServletContext();
×
973
        } catch (ServletException e) {
×
974
            return null;
×
975
        }
976
    }
977

978
    @Override
979
    public AsyncContext startAsync() throws IllegalStateException {
980
        // TODO Auto-generated method stub
981
        return null;
×
982
    }
983

984
    @Override
985
    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse)
986
            throws IllegalStateException {
987
        // TODO Auto-generated method stub
988
        return null;
×
989
    }
990

991
    @Override
992
    public boolean isAsyncStarted() {
993
        // TODO Auto-generated method stub
994
        return false;
×
995
    }
996

997
    @Override
998
    public boolean isAsyncSupported() {
999
        // TODO Auto-generated method stub
1000
        return false;
×
1001
    }
1002

1003
    @Override
1004
    public AsyncContext getAsyncContext() {
1005
        // TODO Auto-generated method stub
1006
        return null;
×
1007
    }
1008

1009
    @Override
1010
    public DispatcherType getDispatcherType() {
1011
        // TODO Auto-generated method stub
1012
        return null;
×
1013
    }
1014

1015
    @Override
1016
    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
1017
        // TODO Auto-generated method stub
1018
        return false;
×
1019
    }
1020

1021
    @Override
1022
    public void login(String username, String password) throws ServletException {
1023
        // TODO Auto-generated method stub
1024

1025
    }
×
1026

1027
    @Override
1028
    public void logout() throws ServletException {
1029
        // TODO Auto-generated method stub
1030

1031
    }
×
1032

1033
    @Override
1034
    public Collection<Part> getParts() throws IOException, ServletException {
1035
        // TODO Auto-generated method stub
1036
        return null;
×
1037
    }
1038

1039
    @Override
1040
    public Part getPart(String name) throws IOException, ServletException {
1041
        // TODO Auto-generated method stub
1042
        return null;
×
1043
    }
1044

1045
    @Override
1046
    public long getContentLengthLong() {
1047
        // TODO Auto-generated method stub
1048
        return 0;
×
1049
    }
1050

1051
    @Override
1052
    public String changeSessionId() {
1053
        // TODO Auto-generated method stub
1054
        return null;
×
1055
    }
1056

1057
    @Override
1058
    public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
1059
        // TODO Auto-generated method stub
1060
        return null;
×
1061
    }
1062

1063
    @Override
1064
    public String getRequestId() {
1065
        // TODO Auto-generated method stub
1066
        return null;
×
1067
    }
1068

1069
    @Override
1070
    public String getProtocolRequestId() {
1071
        // TODO Auto-generated method stub
1072
        return null;
×
1073
    }
1074

1075
    @Override
1076
    public ServletConnection getServletConnection() {
1077
        // TODO Auto-generated method stub
1078
        return null;
×
1079
    }
1080
}
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