• 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

82.3
/src/main/java/com/meterware/httpunit/WebClient.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 com.meterware.httpunit.cookies.Cookie;
23
import com.meterware.httpunit.cookies.CookieJar;
24

25
import java.io.IOException;
26
import java.io.OutputStream;
27
import java.net.HttpURLConnection;
28
import java.net.PasswordAuthentication;
29
import java.net.URL;
30
import java.nio.charset.StandardCharsets;
31
import java.util.ArrayList;
32
import java.util.Base64;
33
import java.util.Dictionary;
34
import java.util.Enumeration;
35
import java.util.Hashtable;
36
import java.util.Iterator;
37
import java.util.LinkedList;
38
import java.util.List;
39

40
import org.xml.sax.SAXException;
41

42
/**
43
 * The context for a series of web requests. This class manages cookies used to maintain session context, computes
44
 * relative URLs, and generally emulates the browser behavior needed to build an automated test of a web site.
45
 **/
46
public abstract class WebClient {
47

48
    private ArrayList _openWindows = new ArrayList<>();
1✔
49

50
    /** The current main window. **/
51
    private WebWindow _mainWindow = new WebWindow(this);
1✔
52

53
    /** An authorization string to be sent with every request, whether challenged or not. May be null. **/
54
    private String _fixedAuthorizationString;
55

56
    /** An authorization string to be sent with the next request only. May be null. **/
57
    private String _authorizationString;
58

59
    private String _proxyAuthorizationString;
60
    private Hashtable _credentials = new Hashtable<>();
1✔
61

62
    public WebWindow getMainWindow() {
63
        return _mainWindow;
1✔
64
    }
65

66
    public void setMainWindow(WebWindow mainWindow) {
67
        if (!_openWindows.contains(mainWindow)) {
×
68
            throw new IllegalArgumentException("May only select an open window owned by this client");
×
69
        }
70
        _mainWindow = mainWindow;
×
71
    }
×
72

73
    public WebWindow[] getOpenWindows() {
74
        return (WebWindow[]) _openWindows.toArray(new WebWindow[_openWindows.size()]);
1✔
75
    }
76

77
    public WebWindow getOpenWindow(String name) {
78
        if (name == null || name.isEmpty()) {
1!
79
            return null;
×
80
        }
81
        for (Iterator i = _openWindows.iterator(); i.hasNext();) {
1!
82
            WebWindow window = (WebWindow) i.next();
1✔
83
            if (name.equals(window.getName())) {
1✔
84
                return window;
1✔
85
            }
86
        }
1✔
87
        return null;
×
88
    }
89

90
    /**
91
     * Submits a GET method request and returns a response.
92
     *
93
     * @exception SAXException
94
     *                thrown if there is an error parsing the retrieved page
95
     **/
96
    public WebResponse getResponse(String urlString) throws IOException, SAXException {
97
        return _mainWindow.getResponse(urlString);
1✔
98
    }
99

100
    /**
101
     * Submits a web request and returns a response. This is an alternate name for the getResponse method.
102
     */
103
    public WebResponse sendRequest(WebRequest request) throws IOException, SAXException {
104
        return _mainWindow.sendRequest(request);
1✔
105
    }
106

107
    /**
108
     * Returns the response representing the current top page in the main window.
109
     */
110
    public WebResponse getCurrentPage() {
111
        return _mainWindow.getCurrentPage();
1✔
112
    }
113

114
    /**
115
     * Submits a web request and returns a response, using all state developed so far as stored in cookies as requested
116
     * by the server.
117
     *
118
     * @exception SAXException
119
     *                thrown if there is an error parsing the retrieved page
120
     **/
121
    public WebResponse getResponse(WebRequest request) throws IOException, SAXException {
122
        return _mainWindow.getResponse(request);
1✔
123
    }
124

125
    /**
126
     * Returns the name of the currently active frames in the main window.
127
     **/
128
    public String[] getFrameNames() {
129
        return _mainWindow.getFrameNames();
1✔
130
    }
131

132
    /**
133
     * Returns the response associated with the specified frame name in the main window. Throws a runtime exception if
134
     * no matching frame is defined.
135
     **/
136
    public WebResponse getFrameContents(String frameName) {
137
        return _mainWindow.getFrameContents(frameName);
1✔
138
    }
139

140
    /**
141
     * Returns the response associated with the specified frame name in the main window. Throws a runtime exception if
142
     * no matching frame is defined.
143
     **/
144
    public WebResponse getFrameContents(FrameSelector targetFrame) {
145
        return _mainWindow.getFrameContents(targetFrame);
1✔
146
    }
147

148
    /**
149
     * Returns the resource specified by the request. Does not update the client or load included framesets or scripts.
150
     * May return null if the resource is a JavaScript URL which would normally leave the client unchanged.
151
     */
152
    public WebResponse getResource(WebRequest request) throws IOException {
153
        return _mainWindow.getResource(request);
×
154
    }
155

156
    /**
157
     * Resets the state of this client, removing all cookies, frames, and per-client headers. This does not affect any
158
     * listeners or preferences which may have been set.
159
     **/
160
    public void clearContents() {
161
        _mainWindow = new WebWindow(this);
×
162
        _cookieJar.clear();
×
163
        _headers = new HeaderDictionary();
×
164
    }
×
165

166
    /**
167
     * Defines a cookie to be sent to the server on every request.
168
     *
169
     * @deprecated as of 1.6, use #putCookie instead.
170
     **/
171
    @Deprecated
172
    public void addCookie(String name, String value) {
173
        _cookieJar.addCookie(name, value);
×
174
    }
×
175

176
    /**
177
     * Defines a cookie to be sent to the server on every request. This overrides any previous setting for this cookie
178
     * name.
179
     **/
180
    public void putCookie(String name, String value) {
181
        _cookieJar.putCookie(name, value);
1✔
182
    }
1✔
183

184
    /**
185
     * Returns the name of all the active cookies which will be sent to the server.
186
     **/
187
    public String[] getCookieNames() {
188
        return _cookieJar.getCookieNames();
1✔
189
    }
190

191
    /**
192
     * Returns an object containing the details of the named cookie
193
     */
194
    public Cookie getCookieDetails(String name) {
195
        return _cookieJar.getCookie(name);
1✔
196
    }
197

198
    /**
199
     * Returns the value of the specified cookie.
200
     **/
201
    public String getCookieValue(String name) {
202
        return _cookieJar.getCookieValue(name);
1✔
203
    }
204

205
    /**
206
     * Returns the properties associated with this client.
207
     */
208
    public ClientProperties getClientProperties() {
209
        if (_clientProperties == null) {
1✔
210
            _clientProperties = ClientProperties.getDefaultProperties().cloneProperties();
1✔
211
        }
212
        return _clientProperties;
1✔
213
    }
214

215
    /**
216
     * Specifies the user agent identification. Used to trigger browser-specific server behavior.
217
     *
218
     * @deprecated as of 1.4.6. Use ClientProperties#setUserAgent instead.
219
     **/
220
    @Deprecated
221
    public void setUserAgent(String userAgent) {
222
        getClientProperties().setUserAgent(userAgent);
×
223
    }
×
224

225
    /**
226
     * Returns the current user agent setting.
227
     *
228
     * @deprecated as of 1.4.6. Use ClientProperties#getUserAgent instead.
229
     **/
230
    @Deprecated
231
    public String getUserAgent() {
232
        return getClientProperties().getUserAgent();
×
233
    }
234

235
    /**
236
     * Sets a username and password for a basic authentication scheme. Use #setAuthentication for more accurate
237
     * emulation of browser behavior.
238
     **/
239
    public void setAuthorization(String userName, String password) {
240
        _fixedAuthorizationString = "Basic "
1✔
241
                + Base64.getEncoder().encodeToString((userName + ':' + password).getBytes(StandardCharsets.UTF_8));
1✔
242
    }
1✔
243

244
    /**
245
     * Specifies a username and password for on-demand authentication. Will only send the authorization header when
246
     * challenged for the specified realm.
247
     *
248
     * @param realm
249
     *            the realm for which the credentials apply.
250
     * @param username
251
     *            the user to authenticate
252
     * @param password
253
     *            the credentials for the user
254
     */
255
    public void setAuthentication(String realm, String username, String password) {
256
        _credentials.put(realm, new PasswordAuthentication(username, password.toCharArray()));
1✔
257
    }
1✔
258

259
    /**
260
     * get the credentials for the given realm
261
     *
262
     * @param realm
263
     *
264
     * @return
265
     */
266
    PasswordAuthentication getCredentialsForRealm(String realm) {
267
        if (_credentials == null) {
1!
268
            throw new Error("null _credentials while calling getCredentialsForRealm");
×
269
        }
270
        if (realm == null) {
1!
271
            throw new Error("null realm while calling getCredentialsForRealm");
×
272
        }
273
        return (PasswordAuthentication) _credentials.get(realm);
1✔
274
    }
275

276
    /**
277
     * Specifies a proxy server to use for requests from this client.
278
     */
279
    public abstract void setProxyServer(String proxyHost, int proxyPort);
280

281
    /**
282
     * Specifies a proxy server to use, along with a user and password for authentication.
283
     */
284
    public void setProxyServer(String proxyHost, int proxyPort, String userName, String password) {
285
        setProxyServer(proxyHost, proxyPort);
×
286
        _proxyAuthorizationString = "Basic "
×
287
                + Base64.getEncoder().encodeToString((userName + ':' + password).getBytes(StandardCharsets.UTF_8));
×
288
    }
×
289

290
    /**
291
     * Clears the proxy server settings.
292
     */
293
    public void clearProxyServer() {
294
    }
×
295

296
    /**
297
     * Returns the name of the active proxy server.
298
     */
299
    public String getProxyHost() {
300
        return System.getProperty("proxyHost");
×
301
    }
302

303
    /**
304
     * Returns the number of the active proxy port, or 0 is none is specified.
305
     */
306
    public int getProxyPort() {
307
        try {
308
            return Integer.getInteger("proxyPort");
×
309
        } catch (NumberFormatException e) {
×
310
            return 0;
×
311
        }
312
    }
313

314
    /**
315
     * Sets the value for a header field to be sent with all requests. If the value set is null, removes the header from
316
     * those to be sent.
317
     **/
318
    public void setHeaderField(String fieldName, String fieldValue) {
319
        _headers.put(fieldName, fieldValue);
1✔
320
    }
1✔
321

322
    /**
323
     * Returns the value for the header field with the specified name. This method will ignore the case of the field
324
     * name.
325
     */
326
    public String getHeaderField(String fieldName) {
327
        return (String) _headers.get(fieldName);
×
328
    }
329

330
    /**
331
     * Specifies whether an exception will be thrown when an error status (4xx or 5xx) is detected on a response.
332
     * Defaults to the value returned by HttpUnitOptions.getExceptionsThrownOnErrorStatus.
333
     **/
334
    public void setExceptionsThrownOnErrorStatus(boolean throwExceptions) {
335
        _exceptionsThrownOnErrorStatus = throwExceptions;
1✔
336
    }
1✔
337

338
    /**
339
     * Returns true if an exception will be thrown when an error status (4xx or 5xx) is detected on a response.
340
     **/
341
    public boolean getExceptionsThrownOnErrorStatus() {
342
        return _exceptionsThrownOnErrorStatus;
1✔
343
    }
344

345
    /**
346
     * Adds a listener to watch for requests and responses.
347
     */
348
    public void addClientListener(WebClientListener listener) {
349
        synchronized (_clientListeners) {
1✔
350
            if (listener != null && !_clientListeners.contains(listener)) {
1!
351
                _clientListeners.add(listener);
1✔
352
            }
353
        }
1✔
354
    }
1✔
355

356
    /**
357
     * Removes a listener to watch for requests and responses.
358
     */
359
    public void removeClientListener(WebClientListener listener) {
360
        synchronized (_clientListeners) {
×
361
            _clientListeners.remove(listener);
×
362
        }
×
363
    }
×
364

365
    /**
366
     * Adds a listener to watch for window openings and closings.
367
     */
368
    public void addWindowListener(WebWindowListener listener) {
369
        synchronized (_windowListeners) {
1✔
370
            if (listener != null && !_windowListeners.contains(listener)) {
1!
371
                _windowListeners.add(listener);
1✔
372
            }
373
        }
1✔
374
    }
1✔
375

376
    /**
377
     * Removes a listener to watch for window openings and closings.
378
     */
379
    public void removeWindowListener(WebWindowListener listener) {
380
        synchronized (_windowListeners) {
×
381
            _windowListeners.remove(listener);
×
382
        }
×
383
    }
×
384

385
    /**
386
     * Returns the next javascript alert without removing it from the queue.
387
     */
388
    public String getNextAlert() {
389
        return _alerts.isEmpty() ? null : (String) _alerts.getFirst();
1✔
390
    }
391

392
    /**
393
     * Returns the next javascript alert and removes it from the queue. If the queue is empty, will return an empty
394
     * string.
395
     */
396
    public String popNextAlert() {
397
        if (_alerts.isEmpty()) {
1✔
398
            return "";
1✔
399
        }
400
        return (String) _alerts.removeFirst();
1✔
401
    }
402

403
    /**
404
     * Specifies the object which will respond to all dialogs.
405
     **/
406
    public void setDialogResponder(DialogResponder responder) {
407
        _dialogResponder = responder;
1✔
408
    }
1✔
409

410
    // ------------------------------------------ protected members -----------------------------------
411

412
    protected WebClient() {
1✔
413
        _openWindows.add(_mainWindow);
1✔
414
    }
1✔
415

416
    /**
417
     * Creates a web response object which represents the response to the specified web request.
418
     *
419
     * @param request
420
     *            the request to which the response should be generated
421
     * @param targetFrame
422
     *            the frame in which the response should be stored
423
     **/
424
    abstract protected WebResponse newResponse(WebRequest request, FrameSelector targetFrame) throws IOException;
425

426
    /**
427
     * Writes the message body for the request.
428
     **/
429
    protected final void writeMessageBody(WebRequest request, OutputStream stream) throws IOException {
430
        request.writeMessageBody(stream);
1✔
431
    }
1✔
432

433
    /**
434
     * Returns the value of all current header fields.
435
     **/
436
    protected Dictionary getHeaderFields(URL targetURL) {
437
        Hashtable result = (Hashtable) _headers.clone();
1✔
438
        result.put("User-Agent", getClientProperties().getUserAgent());
1✔
439
        if (getClientProperties().isAcceptGzip()) {
1✔
440
            result.put("Accept-Encoding", "gzip");
1✔
441
        }
442
        AddHeaderIfNotNull(result, "Cookie", _cookieJar.getCookieHeaderField(targetURL));
1✔
443
        if (_authorizationString == null) {
1✔
444
            _authorizationString = _fixedAuthorizationString;
1✔
445
        }
446
        AddHeaderIfNotNull(result, "Authorization", _authorizationString);
1✔
447
        AddHeaderIfNotNull(result, "Proxy-Authorization", _proxyAuthorizationString);
1✔
448
        _authorizationString = null;
1✔
449
        return result;
1✔
450
    }
451

452
    private void AddHeaderIfNotNull(Hashtable result, final String headerName, final String headerValue) {
453
        if (headerValue != null) {
1✔
454
            result.put(headerName, headerValue);
1✔
455
        }
456
    }
1✔
457

458
    /**
459
     * Updates this web client based on a received response. This includes updating cookies and frames. This method is
460
     * required by ServletUnit, which cannot call the updateWindow method directly.
461
     **/
462
    protected final void updateMainWindow(FrameSelector frame, WebResponse response) throws IOException, SAXException {
463
        getMainWindow().updateWindow(frame.getName(), response, new RequestContext());
1✔
464
    }
1✔
465

466
    // ------------------------------------------------- package members
467
    // ----------------------------------------------------
468

469
    void tellListeners(WebRequest request) {
470
        List listeners;
471

472
        synchronized (_clientListeners) {
1✔
473
            listeners = new ArrayList(_clientListeners);
1✔
474
        }
1✔
475

476
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
477
            ((WebClientListener) i.next()).requestSent(this, request);
1✔
478
        }
479
    }
1✔
480

481
    void tellListeners(WebResponse response) {
482
        List listeners;
483

484
        synchronized (_clientListeners) {
1✔
485
            listeners = new ArrayList(_clientListeners);
1✔
486
        }
1✔
487

488
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
489
            ((WebClientListener) i.next()).responseReceived(this, response);
1✔
490
        }
491
    }
1✔
492

493
    void updateClient(WebResponse response) throws IOException {
494
        if (getClientProperties().isAcceptCookies()) {
1✔
495
            _cookieJar.updateCookies(response.getCookieJar());
1✔
496
        }
497
        validateHeaders(response);
1✔
498
    }
1✔
499

500
    /**
501
     * Support Request [ 1288796 ] getCookieJar() in WebClient
502
     *
503
     * @deprecated - use with care - was not public in the past
504
     *
505
     * @return the cookie jar
506
     */
507
    @Deprecated
508
    public CookieJar getCookieJar() {
509
        return _cookieJar;
1✔
510
    }
511

512
    void updateFrameContents(WebWindow requestWindow, String requestTarget, WebResponse response,
513
            RequestContext requestContext) throws IOException, SAXException {
514
        if (response.getFrame() == FrameSelector.NEW_FRAME) {
1✔
515
            WebWindow window = new WebWindow(this, requestWindow.getCurrentPage());
1✔
516
            if (!WebRequest.NEW_WINDOW.equalsIgnoreCase(requestTarget)) {
1✔
517
                window.setName(requestTarget);
1✔
518
            }
519
            response.setFrame(window.getTopFrame());
1✔
520
            window.updateFrameContents(response, requestContext);
1✔
521
            _openWindows.add(window);
1✔
522
            reportWindowOpened(window);
1✔
523
        } else if (response.getFrame().getWindow() != null && response.getFrame().getWindow() != requestWindow) {
1✔
524
            response.getFrame().getWindow().updateFrameContents(response, requestContext);
1✔
525
        } else {
526
            if (response.getFrame() == FrameSelector.TOP_FRAME) {
1✔
527
                response.setFrame(requestWindow.getTopFrame());
1✔
528
            }
529
            requestWindow.updateFrameContents(response, requestContext);
1✔
530
        }
531
    }
1✔
532

533
    void close(WebWindow window) {
534
        if (!_openWindows.contains(window)) {
1!
535
            throw new IllegalStateException("Window is already closed");
×
536
        }
537
        _openWindows.remove(window);
1✔
538
        if (_openWindows.isEmpty()) {
1✔
539
            _openWindows.add(new WebWindow(this));
1✔
540
        }
541
        if (window.equals(_mainWindow)) {
1✔
542
            _mainWindow = (WebWindow) _openWindows.get(0);
1✔
543
        }
544
        reportWindowClosed(window);
1✔
545
    }
1✔
546

547
    private void reportWindowOpened(WebWindow window) {
548
        List listeners;
549

550
        synchronized (_windowListeners) {
1✔
551
            listeners = new ArrayList(_windowListeners);
1✔
552
        }
1✔
553

554
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
555
            ((WebWindowListener) i.next()).windowOpened(this, window);
1✔
556
        }
557
    }
1✔
558

559
    private void reportWindowClosed(WebWindow window) {
560
        List listeners;
561

562
        synchronized (_windowListeners) {
1✔
563
            listeners = new ArrayList(_windowListeners);
1✔
564
        }
1✔
565

566
        for (Iterator i = listeners.iterator(); i.hasNext();) {
1✔
567
            ((WebWindowListener) i.next()).windowClosed(this, window);
1✔
568
        }
569
    }
1✔
570

571
    // ------------------------------------------ package members ------------------------------------
572

573
    boolean getConfirmationResponse(String message) {
574
        return _dialogResponder.getConfirmation(message);
1✔
575
    }
576

577
    String getUserResponse(String message, String defaultResponse) {
578
        return _dialogResponder.getUserResponse(message, defaultResponse);
1✔
579
    }
580

581
    /**
582
     * simulate an alert by remembering the alert message on a Stack
583
     *
584
     * @param message
585
     *            - the alert message to post
586
     */
587
    void postAlert(String message) {
588
        _alerts.addLast(message);
1✔
589
    }
1✔
590

591
    // ------------------------------------------ private members -------------------------------------
592

593
    /** The list of alerts generated by JavaScript. **/
594
    private LinkedList _alerts = new LinkedList();
1✔
595

596
    /** The currently defined cookies. **/
597
    private CookieJar _cookieJar = new CookieJar();
1✔
598

599
    /** A map of header names to values. **/
600
    private HeaderDictionary _headers = new HeaderDictionary();
1✔
601

602
    private boolean _exceptionsThrownOnErrorStatus = HttpUnitOptions.getExceptionsThrownOnErrorStatus();
1✔
603

604
    private final List _clientListeners = new ArrayList<>();
1✔
605

606
    private final List _windowListeners = new ArrayList<>();
1✔
607

608
    private DialogResponder _dialogResponder = new DialogAdapter();
1✔
609

610
    private ClientProperties _clientProperties;
611

612
    /**
613
     * Examines the headers in the response and throws an exception if appropriate.
614
     *
615
     * @parm response - the response to validate
616
     **/
617
    private void validateHeaders(WebResponse response) throws HttpException {
618
        HttpException exception = null;
1✔
619
        if (response.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
1!
620
            exception = new HttpInternalErrorException(response.getURL());
×
621
        } else if (response.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
1✔
622
            exception = new HttpNotFoundException(response.getResponseMessage(), response.getURL());
1✔
623
        } else if (response.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) {
1✔
624
            exception = new HttpException(response.getResponseCode(), response.getResponseMessage(), response.getURL());
1✔
625
        }
626
        // is there an exception?
627
        if (exception != null) {
1✔
628
            // see feature request [ 914314 ] Add HttpException.getResponse for better reporting
629
            exception.setResponse(response);
1✔
630
            // shall we ignore errors?
631
            if (!getExceptionsThrownOnErrorStatus()) {
1✔
632
                return;
1✔
633
            }
634
            throw exception;
1✔
635
        }
636
    }
1✔
637

638
    FrameSelector findFrame(String target) {
639
        for (Object _openWindow : _openWindows) {
1✔
640
            WebWindow webWindow = (WebWindow) _openWindow;
1✔
641
            FrameSelector frame = webWindow.getFrame(target);
1✔
642
            if (frame != null) {
1✔
643
                return frame;
1✔
644
            }
645
        }
1✔
646
        return null;
1✔
647
    }
648

649
    /**
650
     * Sends a request and returns a response after dealing with any authentication challenge. If challenged and able to
651
     * respond, resends the request after setting the authentication header (which will apply only for the that
652
     * request).
653
     *
654
     * @param request
655
     *            the original request
656
     * @param targetFrame
657
     *            the frame into which the result will be stored
658
     *
659
     * @return a response from the server
660
     *
661
     * @throws IOException
662
     *             if an exception (including authorization failure) occurs
663
     */
664
    WebResponse createResponse(WebRequest request, FrameSelector targetFrame) throws IOException {
665
        WebResponse response = newResponse(request, targetFrame);
1✔
666
        AuthenticationChallenge challenge = new AuthenticationChallenge(this, request,
1✔
667
                response.getHeaderField("WWW-Authenticate"));
1✔
668
        if (!challenge.needToAuthenticate()) {
1✔
669
            return response;
1✔
670
        }
671
        setOnetimeAuthenticationHeader(challenge.createAuthenticationHeader());
1✔
672
        WebResponse response2 = newResponse(request, targetFrame);
1✔
673
        if (response2.getHeaderField("WWW-Authenticate") != null && getExceptionsThrownOnErrorStatus()) {
1!
674
            throw AuthenticationChallenge.createException(response2.getHeaderField("WWW-Authenticate"));
×
675
        }
676
        return response2;
1✔
677
    }
678

679
    private void setOnetimeAuthenticationHeader(String authorizationHeader) {
680
        _authorizationString = authorizationHeader;
1✔
681
    }
1✔
682

683
    // ==================================================================================================
684

685
    static public class HeaderDictionary extends Hashtable {
1✔
686

687
        private static final long serialVersionUID = 1L;
688

689
        public void addEntries(Dictionary source) {
690
            for (Enumeration e = source.keys(); e.hasMoreElements();) {
1✔
691
                Object key = e.nextElement();
1✔
692
                put(key, source.get(key));
1✔
693
            }
1✔
694
        }
1✔
695

696
        @Override
697
        public boolean containsKey(Object key) {
698
            return super.containsKey(matchPreviousFieldName(key.toString()));
1✔
699
        }
700

701
        @Override
702
        public Object get(Object fieldName) {
703
            return super.get(matchPreviousFieldName(fieldName.toString()));
1✔
704
        }
705

706
        @Override
707
        public Object put(Object fieldName, Object fieldValue) {
708
            fieldName = matchPreviousFieldName(fieldName.toString());
1✔
709
            Object oldValue = super.get(fieldName);
1✔
710
            if (fieldValue == null) {
1!
711
                remove(fieldName);
×
712
            } else {
713
                super.put(fieldName, fieldValue);
1✔
714
            }
715
            return oldValue;
1✔
716
        }
717

718
        /**
719
         * If a matching field name with different case is already known, returns the older name. Otherwise, returns the
720
         * specified name.
721
         **/
722
        private String matchPreviousFieldName(String fieldName) {
723
            for (Enumeration e = keys(); e.hasMoreElements();) {
1✔
724
                String key = (String) e.nextElement();
1✔
725
                if (key.equalsIgnoreCase(fieldName)) {
1✔
726
                    return key;
1✔
727
                }
728
            }
1✔
729
            return fieldName;
1✔
730
        }
731

732
    }
733

734
}
735

736
// ==================================================================================================
737

738
class RedirectWebRequest extends WebRequest {
739

740
    RedirectWebRequest(WebResponse response) {
741
        super(response.getURL(), response.getHeaderField("Location"), response.getFrame(), response.getFrameName());
1✔
742
        if (response.getReferer() != null) {
1✔
743
            setHeaderField("Referer", response.getReferer());
1✔
744
        }
745
    }
1✔
746

747
    /**
748
     * Returns the HTTP method defined for this request.
749
     **/
750
    @Override
751
    public String getMethod() {
752
        return "GET";
1✔
753
    }
754
}
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