or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

async-processing.mdhttp-processing.mdindex.mdlisteners-events.mdsecurity-filtering.mdservlet-lifecycle.mdsession-cookies.md

http-processing.mddocs/

0

# HTTP Request and Response Processing

1

2

The Java Servlet API provides comprehensive support for HTTP request and response processing. This includes handling different HTTP methods, processing request parameters and headers, managing response output, and supporting advanced features like multipart requests and HTTP/2 server push.

3

4

## HttpServlet Base Class

5

6

```java { .api }

7

/**

8

* Abstract base class for HTTP servlets.

9

* Extends GenericServlet and provides HTTP-specific functionality.

10

*/

11

public abstract class HttpServlet extends GenericServlet {

12

13

/**

14

* Handle HTTP GET requests.

15

* Default implementation returns HTTP 405 (Method Not Allowed).

16

*/

17

protected void doGet(HttpServletRequest req, HttpServletResponse resp)

18

throws ServletException, IOException {

19

String protocol = req.getProtocol();

20

String msg = lStrings.getString("http.method_get_not_supported");

21

if (protocol.endsWith("1.1")) {

22

resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);

23

} else {

24

resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);

25

}

26

}

27

28

/**

29

* Handle HTTP POST requests.

30

* Default implementation returns HTTP 405 (Method Not Allowed).

31

*/

32

protected void doPost(HttpServletRequest req, HttpServletResponse resp)

33

throws ServletException, IOException {

34

String protocol = req.getProtocol();

35

String msg = lStrings.getString("http.method_post_not_supported");

36

if (protocol.endsWith("1.1")) {

37

resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);

38

} else {

39

resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);

40

}

41

}

42

43

/**

44

* Handle HTTP PUT requests.

45

* Default implementation returns HTTP 405 (Method Not Allowed).

46

*/

47

protected void doPut(HttpServletRequest req, HttpServletResponse resp)

48

throws ServletException, IOException {

49

String protocol = req.getProtocol();

50

String msg = lStrings.getString("http.method_put_not_supported");

51

if (protocol.endsWith("1.1")) {

52

resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);

53

} else {

54

resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);

55

}

56

}

57

58

/**

59

* Handle HTTP DELETE requests.

60

* Default implementation returns HTTP 405 (Method Not Allowed).

61

*/

62

protected void doDelete(HttpServletRequest req, HttpServletResponse resp)

63

throws ServletException, IOException {

64

String protocol = req.getProtocol();

65

String msg = lStrings.getString("http.method_delete_not_supported");

66

if (protocol.endsWith("1.1")) {

67

resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);

68

} else {

69

resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);

70

}

71

}

72

73

/**

74

* Handle HTTP HEAD requests.

75

* Default implementation calls doGet and discards response body.

76

*/

77

protected void doHead(HttpServletRequest req, HttpServletResponse resp)

78

throws ServletException, IOException {

79

NoBodyResponse response = new NoBodyResponse(resp);

80

doGet(req, response);

81

response.setContentLength();

82

}

83

84

/**

85

* Handle HTTP OPTIONS requests.

86

* Default implementation determines which methods are supported.

87

*/

88

protected void doOptions(HttpServletRequest req, HttpServletResponse resp)

89

throws ServletException, IOException {

90

91

Method[] methods = getAllDeclaredMethods(this.getClass());

92

boolean ALLOW_GET = false;

93

boolean ALLOW_HEAD = false;

94

boolean ALLOW_POST = false;

95

boolean ALLOW_PUT = false;

96

boolean ALLOW_DELETE = false;

97

boolean ALLOW_TRACE = true;

98

boolean ALLOW_OPTIONS = true;

99

100

// Check which doXXX methods are overridden

101

for (Method method : methods) {

102

if (method.getName().equals("doGet")) {

103

ALLOW_GET = true;

104

ALLOW_HEAD = true;

105

} else if (method.getName().equals("doPost")) {

106

ALLOW_POST = true;

107

} else if (method.getName().equals("doPut")) {

108

ALLOW_PUT = true;

109

} else if (method.getName().equals("doDelete")) {

110

ALLOW_DELETE = true;

111

}

112

}

113

114

StringBuilder allow = new StringBuilder();

115

if (ALLOW_GET) allow.append("GET");

116

if (ALLOW_HEAD) append(allow, "HEAD");

117

if (ALLOW_POST) append(allow, "POST");

118

if (ALLOW_PUT) append(allow, "PUT");

119

if (ALLOW_DELETE) append(allow, "DELETE");

120

if (ALLOW_TRACE) append(allow, "TRACE");

121

if (ALLOW_OPTIONS) append(allow, "OPTIONS");

122

123

resp.setHeader("Allow", allow.toString());

124

}

125

126

/**

127

* Handle HTTP TRACE requests.

128

* Default implementation reflects the request back as the response.

129

*/

130

protected void doTrace(HttpServletRequest req, HttpServletResponse resp)

131

throws ServletException, IOException {

132

133

String CRLF = "\r\n";

134

StringBuilder buffer = new StringBuilder("TRACE ")

135

.append(req.getRequestURI())

136

.append(" ")

137

.append(req.getProtocol())

138

.append(CRLF);

139

140

Enumeration<String> reqHeaderEnum = req.getHeaderNames();

141

while (reqHeaderEnum.hasMoreElements()) {

142

String headerName = reqHeaderEnum.nextElement();

143

buffer.append(headerName).append(": ")

144

.append(req.getHeader(headerName)).append(CRLF);

145

}

146

147

buffer.append(CRLF);

148

149

int responseLength = buffer.length();

150

resp.setContentType("message/http");

151

resp.setContentLength(responseLength);

152

ServletOutputStream out = resp.getOutputStream();

153

out.print(buffer.toString());

154

}

155

156

/**

157

* Get the last modified time for the resource.

158

* Default returns -1 (unknown).

159

*/

160

protected long getLastModified(HttpServletRequest req) {

161

return -1;

162

}

163

164

/**

165

* Dispatch HTTP requests to appropriate doXXX methods.

166

*/

167

@Override

168

public void service(ServletRequest req, ServletResponse res)

169

throws ServletException, IOException {

170

171

HttpServletRequest request;

172

HttpServletResponse response;

173

174

try {

175

request = (HttpServletRequest) req;

176

response = (HttpServletResponse) res;

177

} catch (ClassCastException e) {

178

throw new ServletException("Non-HTTP request or response");

179

}

180

181

service(request, response);

182

}

183

184

/**

185

* HTTP-specific service method that dispatches to doXXX methods.

186

*/

187

protected void service(HttpServletRequest req, HttpServletResponse resp)

188

throws ServletException, IOException {

189

190

String method = req.getMethod();

191

192

if (method.equals(METHOD_GET)) {

193

long lastModified = getLastModified(req);

194

if (lastModified == -1) {

195

doGet(req, resp);

196

} else {

197

long ifModifiedSince = req.getDateHeader("If-Modified-Since");

198

if (ifModifiedSince < (lastModified / 1000 * 1000)) {

199

maybeSetLastModified(resp, lastModified);

200

doGet(req, resp);

201

} else {

202

resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);

203

}

204

}

205

} else if (method.equals(METHOD_HEAD)) {

206

long lastModified = getLastModified(req);

207

maybeSetLastModified(resp, lastModified);

208

doHead(req, resp);

209

} else if (method.equals(METHOD_POST)) {

210

doPost(req, resp);

211

} else if (method.equals(METHOD_PUT)) {

212

doPut(req, resp);

213

} else if (method.equals(METHOD_DELETE)) {

214

doDelete(req, resp);

215

} else if (method.equals(METHOD_OPTIONS)) {

216

doOptions(req, resp);

217

} else if (method.equals(METHOD_TRACE)) {

218

doTrace(req, resp);

219

} else {

220

String errMsg = lStrings.getString("http.method_not_implemented");

221

Object[] errArgs = new Object[1];

222

errArgs[0] = method;

223

errMsg = MessageFormat.format(errMsg, errArgs);

224

resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);

225

}

226

}

227

}

228

```

229

230

## HttpServletRequest Interface

231

232

```java { .api }

233

/**

234

* HTTP-specific servlet request interface.

235

* Extends ServletRequest with HTTP-specific functionality.

236

*/

237

public interface HttpServletRequest extends ServletRequest {

238

239

// HTTP method constants

240

public static final String BASIC_AUTH = "BASIC";

241

public static final String FORM_AUTH = "FORM";

242

public static final String CLIENT_CERT_AUTH = "CLIENT_CERT";

243

public static final String DIGEST_AUTH = "DIGEST";

244

245

// Request attributes for authentication

246

public static final String AUTHORIZATION = "javax.servlet.http.authorization";

247

public static final String REMOTE_USER = "javax.servlet.http.remoteUser";

248

249

/**

250

* Get the authentication scheme (BASIC, FORM, etc.)

251

*/

252

String getAuthType();

253

254

/**

255

* Get all cookies sent with this request.

256

*/

257

Cookie[] getCookies();

258

259

/**

260

* Get the value of a date header.

261

*/

262

long getDateHeader(String name);

263

264

/**

265

* Get the value of a request header.

266

*/

267

String getHeader(String name);

268

269

/**

270

* Get all values for a header with multiple values.

271

*/

272

Enumeration<String> getHeaders(String name);

273

274

/**

275

* Get all header names in this request.

276

*/

277

Enumeration<String> getHeaderNames();

278

279

/**

280

* Get the value of an integer header.

281

*/

282

int getIntHeader(String name);

283

284

/**

285

* Get servlet mapping information for this request.

286

*/

287

HttpServletMapping getHttpServletMapping();

288

289

/**

290

* Get the HTTP method (GET, POST, etc.)

291

*/

292

String getMethod();

293

294

/**

295

* Get extra path information after servlet path.

296

*/

297

String getPathInfo();

298

299

/**

300

* Get real path corresponding to path info.

301

*/

302

String getPathTranslated();

303

304

/**

305

* Get the context path portion of the request URL.

306

*/

307

String getContextPath();

308

309

/**

310

* Get the query string from the request URL.

311

*/

312

String getQueryString();

313

314

/**

315

* Get the login name of the authenticated user.

316

*/

317

String getRemoteUser();

318

319

/**

320

* Check if the user is in the specified role.

321

*/

322

boolean isUserInRole(String role);

323

324

/**

325

* Get the Principal object for the authenticated user.

326

*/

327

java.security.Principal getUserPrincipal();

328

329

/**

330

* Get the session ID from the request.

331

*/

332

String getRequestedSessionId();

333

334

/**

335

* Get the full request URI.

336

*/

337

String getRequestURI();

338

339

/**

340

* Get the full request URL including query string.

341

*/

342

StringBuffer getRequestURL();

343

344

/**

345

* Get the servlet path portion of the request URL.

346

*/

347

String getServletPath();

348

349

/**

350

* Get the current session, creating one if necessary.

351

*/

352

HttpSession getSession(boolean create);

353

354

/**

355

* Get the current session (create = true).

356

*/

357

HttpSession getSession();

358

359

/**

360

* Change the session ID and return the new ID.

361

*/

362

String changeSessionId();

363

364

/**

365

* Check if the session ID came from a cookie.

366

*/

367

boolean isRequestedSessionIdValid();

368

369

/**

370

* Check if the session ID is still valid.

371

*/

372

boolean isRequestedSessionIdFromCookie();

373

374

/**

375

* Check if the session ID came from URL encoding.

376

*/

377

boolean isRequestedSessionIdFromURL();

378

379

/**

380

* Check if the session ID came from URL encoding (deprecated).

381

*/

382

@Deprecated

383

boolean isRequestedSessionIdFromUrl();

384

385

/**

386

* Programmatically authenticate the user.

387

*/

388

boolean authenticate(HttpServletResponse response)

389

throws IOException, ServletException;

390

391

/**

392

* Programmatically log in the user.

393

*/

394

void login(String username, String password) throws ServletException;

395

396

/**

397

* Programmatically log out the user.

398

*/

399

void logout() throws ServletException;

400

401

/**

402

* Get all parts from a multipart/form-data request.

403

*/

404

Collection<Part> getParts() throws IOException, ServletException;

405

406

/**

407

* Get a specific part by name from a multipart request.

408

*/

409

Part getPart(String name) throws IOException, ServletException;

410

411

/**

412

* Create an HttpUpgradeHandler for protocol upgrade.

413

*/

414

<T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass)

415

throws IOException, ServletException;

416

}

417

```

418

419

## HttpServletResponse Interface

420

421

```java { .api }

422

/**

423

* HTTP-specific servlet response interface.

424

* Extends ServletResponse with HTTP-specific functionality.

425

*/

426

public interface HttpServletResponse extends ServletResponse {

427

428

// Status code constants

429

public static final int SC_CONTINUE = 100;

430

public static final int SC_SWITCHING_PROTOCOLS = 101;

431

public static final int SC_OK = 200;

432

public static final int SC_CREATED = 201;

433

public static final int SC_ACCEPTED = 202;

434

public static final int SC_NON_AUTHORITATIVE_INFORMATION = 203;

435

public static final int SC_NO_CONTENT = 204;

436

public static final int SC_RESET_CONTENT = 205;

437

public static final int SC_PARTIAL_CONTENT = 206;

438

public static final int SC_MULTIPLE_CHOICES = 300;

439

public static final int SC_MOVED_PERMANENTLY = 301;

440

public static final int SC_MOVED_TEMPORARILY = 302;

441

public static final int SC_FOUND = 302;

442

public static final int SC_SEE_OTHER = 303;

443

public static final int SC_NOT_MODIFIED = 304;

444

public static final int SC_USE_PROXY = 305;

445

public static final int SC_TEMPORARY_REDIRECT = 307;

446

public static final int SC_BAD_REQUEST = 400;

447

public static final int SC_UNAUTHORIZED = 401;

448

public static final int SC_PAYMENT_REQUIRED = 402;

449

public static final int SC_FORBIDDEN = 403;

450

public static final int SC_NOT_FOUND = 404;

451

public static final int SC_METHOD_NOT_ALLOWED = 405;

452

public static final int SC_NOT_ACCEPTABLE = 406;

453

public static final int SC_PROXY_AUTHENTICATION_REQUIRED = 407;

454

public static final int SC_REQUEST_TIMEOUT = 408;

455

public static final int SC_CONFLICT = 409;

456

public static final int SC_GONE = 410;

457

public static final int SC_LENGTH_REQUIRED = 411;

458

public static final int SC_PRECONDITION_FAILED = 412;

459

public static final int SC_REQUEST_ENTITY_TOO_LARGE = 413;

460

public static final int SC_REQUEST_URI_TOO_LONG = 414;

461

public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;

462

public static final int SC_REQUESTED_RANGE_NOT_SATISFIABLE = 416;

463

public static final int SC_EXPECTATION_FAILED = 417;

464

public static final int SC_INTERNAL_SERVER_ERROR = 500;

465

public static final int SC_NOT_IMPLEMENTED = 501;

466

public static final int SC_BAD_GATEWAY = 502;

467

public static final int SC_SERVICE_UNAVAILABLE = 503;

468

public static final int SC_GATEWAY_TIMEOUT = 504;

469

public static final int SC_HTTP_VERSION_NOT_SUPPORTED = 505;

470

471

/**

472

* Add a cookie to the response.

473

*/

474

void addCookie(Cookie cookie);

475

476

/**

477

* Check if the response contains the specified header.

478

*/

479

boolean containsHeader(String name);

480

481

/**

482

* Encode a URL for session tracking via URL rewriting.

483

*/

484

String encodeURL(String url);

485

486

/**

487

* Encode a redirect URL for session tracking.

488

*/

489

String encodeRedirectURL(String url);

490

491

/**

492

* Encode a URL for session tracking (deprecated).

493

*/

494

@Deprecated

495

String encodeUrl(String url);

496

497

/**

498

* Encode a redirect URL for session tracking (deprecated).

499

*/

500

@Deprecated

501

String encodeRedirectUrl(String url);

502

503

/**

504

* Send an error response with the specified status code.

505

*/

506

void sendError(int sc, String msg) throws IOException;

507

508

/**

509

* Send an error response with the specified status code.

510

*/

511

void sendError(int sc) throws IOException;

512

513

/**

514

* Send a redirect response to the specified URL.

515

*/

516

void sendRedirect(String location) throws IOException;

517

518

/**

519

* Set a date header with the given value.

520

*/

521

void setDateHeader(String name, long date);

522

523

/**

524

* Add a date header with the given value.

525

*/

526

void addDateHeader(String name, long date);

527

528

/**

529

* Set a header with the given value.

530

*/

531

void setHeader(String name, String value);

532

533

/**

534

* Add a header with the given value.

535

*/

536

void addHeader(String name, String value);

537

538

/**

539

* Set an integer header with the given value.

540

*/

541

void setIntHeader(String name, int value);

542

543

/**

544

* Add an integer header with the given value.

545

*/

546

void addIntHeader(String name, int value);

547

548

/**

549

* Set the response status code.

550

*/

551

void setStatus(int sc);

552

553

/**

554

* Set the response status code with message (deprecated).

555

*/

556

@Deprecated

557

void setStatus(int sc, String sm);

558

559

/**

560

* Get the response status code.

561

*/

562

int getStatus();

563

564

/**

565

* Get the value of a response header.

566

*/

567

String getHeader(String name);

568

569

/**

570

* Get all values for a response header.

571

*/

572

Collection<String> getHeaders(String name);

573

574

/**

575

* Get all response header names.

576

*/

577

Collection<String> getHeaderNames();

578

579

/**

580

* Get trailer fields for chunked encoding.

581

*/

582

Supplier<Map<String, String>> getTrailerFields();

583

584

/**

585

* Set trailer fields for chunked encoding.

586

*/

587

void setTrailerFields(Supplier<Map<String, String>> supplier);

588

}

589

```

590

591

## Multipart Request Processing

592

593

### Part Interface

594

595

```java { .api }

596

/**

597

* Interface representing a part in a multipart/form-data request.

598

*/

599

public interface Part {

600

601

/**

602

* Get an InputStream for reading the part content.

603

*/

604

InputStream getInputStream() throws IOException;

605

606

/**

607

* Get the content type of this part.

608

*/

609

String getContentType();

610

611

/**

612

* Get the name of this part (from the name attribute).

613

*/

614

String getName();

615

616

/**

617

* Get the submitted filename (from filename attribute).

618

*/

619

String getSubmittedFileName();

620

621

/**

622

* Get the size of this part in bytes.

623

*/

624

long getSize();

625

626

/**

627

* Write this part to a file on disk.

628

*/

629

void write(String fileName) throws IOException;

630

631

/**

632

* Delete any temporary storage for this part.

633

*/

634

void delete() throws IOException;

635

636

/**

637

* Get the value of a header for this part.

638

*/

639

String getHeader(String name);

640

641

/**

642

* Get all values for a header.

643

*/

644

Collection<String> getHeaders(String name);

645

646

/**

647

* Get all header names for this part.

648

*/

649

Collection<String> getHeaderNames();

650

}

651

```

652

653

### Multipart Configuration Examples

654

655

```java { .api }

656

/**

657

* Servlet configured for multipart request handling

658

*/

659

@WebServlet("/upload")

660

@MultipartConfig(

661

location = "/tmp",

662

fileSizeThreshold = 1024 * 1024, // 1 MB

663

maxFileSize = 1024 * 1024 * 5, // 5 MB

664

maxRequestSize = 1024 * 1024 * 5 * 5 // 25 MB

665

)

666

public class FileUploadServlet extends HttpServlet {

667

668

@Override

669

protected void doPost(HttpServletRequest request, HttpServletResponse response)

670

throws ServletException, IOException {

671

672

// Process regular form parameters

673

String description = request.getParameter("description");

674

675

// Process uploaded files

676

for (Part part : request.getParts()) {

677

if (part.getName().equals("file") && part.getSize() > 0) {

678

String fileName = getSubmittedFileName(part);

679

680

// Validate file type

681

String contentType = part.getContentType();

682

if (!isValidContentType(contentType)) {

683

response.sendError(HttpServletResponse.SC_BAD_REQUEST,

684

"Invalid file type: " + contentType);

685

return;

686

}

687

688

// Save the file

689

String uploadPath = getServletContext().getRealPath("/uploads");

690

File uploadDir = new File(uploadPath);

691

if (!uploadDir.exists()) {

692

uploadDir.mkdirs();

693

}

694

695

String filePath = uploadPath + File.separator + fileName;

696

part.write(filePath);

697

698

// Log the upload

699

log("File uploaded: " + fileName + " (" + part.getSize() + " bytes)");

700

}

701

}

702

703

response.setContentType("application/json");

704

response.getWriter().write("{\"status\":\"success\",\"message\":\"Files uploaded\"}");

705

}

706

707

private String getSubmittedFileName(Part part) {

708

String contentDisposition = part.getHeader("Content-Disposition");

709

String[] elements = contentDisposition.split(";");

710

711

for (String element : elements) {

712

if (element.trim().startsWith("filename")) {

713

return element.substring(element.indexOf('=') + 1)

714

.trim().replace("\"", "");

715

}

716

}

717

return "unknown";

718

}

719

720

private boolean isValidContentType(String contentType) {

721

return contentType != null && (

722

contentType.startsWith("image/") ||

723

contentType.equals("application/pdf") ||

724

contentType.startsWith("text/")

725

);

726

}

727

}

728

```

729

730

## HTTP/2 Server Push Support

731

732

### PushBuilder Interface

733

734

```java { .api }

735

/**

736

* Interface for HTTP/2 server push functionality.

737

*/

738

public interface PushBuilder {

739

740

/**

741

* Set the HTTP method for the push request.

742

*/

743

PushBuilder method(String method);

744

745

/**

746

* Set the query string for the push request.

747

*/

748

PushBuilder queryString(String queryString);

749

750

/**

751

* Set the session ID for the push request.

752

*/

753

PushBuilder sessionId(String sessionId);

754

755

/**

756

* Set a header for the push request.

757

*/

758

PushBuilder setHeader(String name, String value);

759

760

/**

761

* Add a header to the push request.

762

*/

763

PushBuilder addHeader(String name, String value);

764

765

/**

766

* Remove a header from the push request.

767

*/

768

PushBuilder removeHeader(String name);

769

770

/**

771

* Set the path for the push request.

772

*/

773

PushBuilder path(String path);

774

775

/**

776

* Initiate the server push.

777

*/

778

void push();

779

780

/**

781

* Get the HTTP method for the push request.

782

*/

783

String getMethod();

784

785

/**

786

* Get the query string for the push request.

787

*/

788

String getQueryString();

789

790

/**

791

* Get the session ID for the push request.

792

*/

793

String getSessionId();

794

795

/**

796

* Get all header names for the push request.

797

*/

798

Set<String> getHeaderNames();

799

800

/**

801

* Get the value of a header for the push request.

802

*/

803

String getHeader(String name);

804

805

/**

806

* Get the path for the push request.

807

*/

808

String getPath();

809

}

810

```

811

812

### Server Push Example

813

814

```java { .api }

815

/**

816

* Servlet demonstrating HTTP/2 server push

817

*/

818

public class ServerPushServlet extends HttpServlet {

819

820

@Override

821

protected void doGet(HttpServletRequest request, HttpServletResponse response)

822

throws ServletException, IOException {

823

824

// Check if server push is supported

825

PushBuilder pushBuilder = request.newPushBuilder();

826

if (pushBuilder != null) {

827

// Push CSS resources

828

pushBuilder.path("/css/styles.css")

829

.setHeader("Content-Type", "text/css")

830

.push();

831

832

// Push JavaScript resources

833

pushBuilder.path("/js/app.js")

834

.setHeader("Content-Type", "application/javascript")

835

.push();

836

837

// Push image resources

838

pushBuilder.path("/images/logo.png")

839

.setHeader("Content-Type", "image/png")

840

.push();

841

}

842

843

// Generate the main HTML response

844

response.setContentType("text/html;charset=UTF-8");

845

PrintWriter out = response.getWriter();

846

847

out.println("<!DOCTYPE html>");

848

out.println("<html>");

849

out.println("<head>");

850

out.println(" <title>Server Push Example</title>");

851

out.println(" <link rel=\"stylesheet\" href=\"/css/styles.css\">");

852

out.println("</head>");

853

out.println("<body>");

854

out.println(" <img src=\"/images/logo.png\" alt=\"Logo\">");

855

out.println(" <h1>Welcome to Server Push Demo</h1>");

856

out.println(" <script src=\"/js/app.js\"></script>");

857

out.println("</body>");

858

out.println("</html>");

859

}

860

}

861

```

862

863

## Request and Response Wrapper Classes

864

865

```java { .api }

866

/**

867

* HTTP servlet request wrapper for request modification/decoration.

868

*/

869

public class HttpServletRequestWrapper extends ServletRequestWrapper

870

implements HttpServletRequest {

871

872

private HttpServletRequest request;

873

874

public HttpServletRequestWrapper(HttpServletRequest request) {

875

super(request);

876

if (request == null) {

877

throw new IllegalArgumentException("Request cannot be null");

878

}

879

this.request = request;

880

}

881

882

// Delegate all methods to wrapped request

883

public String getAuthType() {

884

return this.request.getAuthType();

885

}

886

887

public Cookie[] getCookies() {

888

return this.request.getCookies();

889

}

890

891

public long getDateHeader(String name) {

892

return this.request.getDateHeader(name);

893

}

894

895

public String getHeader(String name) {

896

return this.request.getHeader(name);

897

}

898

899

// ... all other HttpServletRequest methods

900

}

901

902

/**

903

* HTTP servlet response wrapper for response modification/decoration.

904

*/

905

public class HttpServletResponseWrapper extends ServletResponseWrapper

906

implements HttpServletResponse {

907

908

private HttpServletResponse response;

909

910

public HttpServletResponseWrapper(HttpServletResponse response) {

911

super(response);

912

if (response == null) {

913

throw new IllegalArgumentException("Response cannot be null");

914

}

915

this.response = response;

916

}

917

918

// Delegate all methods to wrapped response

919

public void addCookie(Cookie cookie) {

920

this.response.addCookie(cookie);

921

}

922

923

public boolean containsHeader(String name) {

924

return this.response.containsHeader(name);

925

}

926

927

public String encodeURL(String url) {

928

return this.response.encodeURL(url);

929

}

930

931

// ... all other HttpServletResponse methods

932

}

933

```

934

935

## Content Processing Examples

936

937

### JSON API Servlet

938

939

```java { .api }

940

/**

941

* REST API servlet for JSON processing

942

*/

943

@WebServlet("/api/users/*")

944

public class UserAPIServlet extends HttpServlet {

945

946

private final ObjectMapper mapper = new ObjectMapper();

947

948

@Override

949

protected void doGet(HttpServletRequest request, HttpServletResponse response)

950

throws ServletException, IOException {

951

952

String pathInfo = request.getPathInfo();

953

response.setContentType("application/json;charset=UTF-8");

954

955

try {

956

if (pathInfo == null || pathInfo.equals("/")) {

957

// Get all users

958

List<User> users = getUserService().getAllUsers();

959

writeJsonResponse(response, users);

960

} else {

961

// Get specific user

962

String userId = pathInfo.substring(1);

963

User user = getUserService().getUser(userId);

964

if (user != null) {

965

writeJsonResponse(response, user);

966

} else {

967

response.setStatus(HttpServletResponse.SC_NOT_FOUND);

968

writeJsonResponse(response, Map.of("error", "User not found"));

969

}

970

}

971

} catch (Exception e) {

972

response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

973

writeJsonResponse(response, Map.of("error", "Internal server error"));

974

}

975

}

976

977

@Override

978

protected void doPost(HttpServletRequest request, HttpServletResponse response)

979

throws ServletException, IOException {

980

981

response.setContentType("application/json;charset=UTF-8");

982

983

try {

984

// Read JSON request body

985

User user = mapper.readValue(request.getInputStream(), User.class);

986

987

// Validate user data

988

if (user.getName() == null || user.getEmail() == null) {

989

response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

990

writeJsonResponse(response, Map.of("error", "Name and email are required"));

991

return;

992

}

993

994

// Create user

995

User createdUser = getUserService().createUser(user);

996

response.setStatus(HttpServletResponse.SC_CREATED);

997

writeJsonResponse(response, createdUser);

998

999

} catch (JsonProcessingException e) {

1000

response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

1001

writeJsonResponse(response, Map.of("error", "Invalid JSON"));

1002

} catch (Exception e) {

1003

response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

1004

writeJsonResponse(response, Map.of("error", "Internal server error"));

1005

}

1006

}

1007

1008

@Override

1009

protected void doPut(HttpServletRequest request, HttpServletResponse response)

1010

throws ServletException, IOException {

1011

1012

String pathInfo = request.getPathInfo();

1013

if (pathInfo == null || pathInfo.equals("/")) {

1014

response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

1015

return;

1016

}

1017

1018

response.setContentType("application/json;charset=UTF-8");

1019

1020

try {

1021

String userId = pathInfo.substring(1);

1022

User user = mapper.readValue(request.getInputStream(), User.class);

1023

user.setId(userId);

1024

1025

User updatedUser = getUserService().updateUser(user);

1026

if (updatedUser != null) {

1027

writeJsonResponse(response, updatedUser);

1028

} else {

1029

response.setStatus(HttpServletResponse.SC_NOT_FOUND);

1030

writeJsonResponse(response, Map.of("error", "User not found"));

1031

}

1032

} catch (Exception e) {

1033

response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

1034

writeJsonResponse(response, Map.of("error", "Internal server error"));

1035

}

1036

}

1037

1038

@Override

1039

protected void doDelete(HttpServletRequest request, HttpServletResponse response)

1040

throws ServletException, IOException {

1041

1042

String pathInfo = request.getPathInfo();

1043

if (pathInfo == null || pathInfo.equals("/")) {

1044

response.setStatus(HttpServletResponse.SC_BAD_REQUEST);

1045

return;

1046

}

1047

1048

response.setContentType("application/json;charset=UTF-8");

1049

1050

try {

1051

String userId = pathInfo.substring(1);

1052

boolean deleted = getUserService().deleteUser(userId);

1053

1054

if (deleted) {

1055

response.setStatus(HttpServletResponse.SC_NO_CONTENT);

1056

} else {

1057

response.setStatus(HttpServletResponse.SC_NOT_FOUND);

1058

writeJsonResponse(response, Map.of("error", "User not found"));

1059

}

1060

} catch (Exception e) {

1061

response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);

1062

writeJsonResponse(response, Map.of("error", "Internal server error"));

1063

}

1064

}

1065

1066

private void writeJsonResponse(HttpServletResponse response, Object data)

1067

throws IOException {

1068

PrintWriter writer = response.getWriter();

1069

mapper.writeValue(writer, data);

1070

writer.flush();

1071

}

1072

}

1073

```

1074

1075

This comprehensive coverage of HTTP request and response processing provides all the tools needed for handling HTTP communications in servlet applications, from basic request processing to advanced features like multipart uploads and HTTP/2 server push.