Web Technologies

Chapter 7
Server-Side Web Development

Bachelors Program in AI & ML
Web Technologies   •   Bachelor

Server-Side Web Development

Introduction and Context

Server-side web development is the construction of software that runs on a web server and responds to requests from browsers, mobile applications, and other clients. Unlike client-side code, which executes primarily in a user’s browser, server-side code performs tasks such as routing requests, applying business rules, accessing databases, managing sessions, authenticating users, rendering pages, and returning structured data.

A modern server application is not merely a collection of URL handlers. It is a controlled system that must remain understandable, testable, secure, observable, and maintainable as usage grows. Frameworks such as Django, Laravel, Spring Boot, ASP.NET Core, Express, FastAPI, and NestJS provide reusable mechanisms for common concerns, but developers remain responsible for architectural decisions and secure implementation.

This chapter uses framework-neutral concepts and Python-like pseudocode. Specific syntax differs among frameworks, but the underlying principles are broadly transferable.

Learning Objectives

By the end of this chapter, students should be able to:

1. Explain the request–response model and the major components of a server application.

2. Design routes, controllers, middleware, templates, and service layers.

3. Manage sessions, authentication, and authorization appropriately.

4. Validate input and distinguish validation from sanitization and output encoding.

5. Apply dependency management and secure configuration practices.

6. Implement logging and basic operational observability.

7. Identify common security, privacy, reliability, and maintainability risks.

8. Evaluate a server-side design for a realistic application scenario.

1. The Server-Side Request–Response Model

A client sends an HTTP request containing a method, target URL, headers, and sometimes a body. The server receives the request, identifies a route, executes application logic, and returns an HTTP response. A response includes a status code, headers, and an optional body.

Common methods include GET for retrieval, POST for creating or processing data, PUT for replacing a resource, PATCH for partial modification, and DELETE for removal. GET requests should generally be safe, meaning that repeating them does not intentionally change server state. PUT and DELETE are commonly designed to be idempotent: performing the same operation repeatedly has the same intended final effect. POST is not inherently idempotent.

Status codes communicate broad outcomes. A 2xx response indicates success, 3xx redirection, 4xx a client-side problem, and 5xx a server-side problem. For example, 200 means successful retrieval, 201 successful creation, 400 malformed input, 401 missing or invalid authentication, 403 authenticated but not permitted, 404 resource not found, and 500 an unexpected server failure. A well-designed API uses these codes consistently without revealing sensitive internal details.

A typical processing pipeline is:

Client → web server or reverse proxy → application middleware → router → controller or handler → service layer → data-access layer → response renderer.

The reverse proxy may terminate TLS, serve static files, apply rate limits, and forward requests to application processes. The application should not assume that every incoming value is trustworthy, including headers, cookies, query parameters, path parameters, uploaded files, or JSON fields.

2. Application Structure and Separation of Concerns

A small prototype can place routing and business logic in one file. This becomes difficult to test and maintain as the system grows. A layered structure commonly separates:

  • Routes: map HTTP methods and paths to handlers.
  • Controllers or handlers: translate HTTP input into application operations and format responses.
  • Services: implement business rules and coordinate operations.
  • Repositories or data-access objects: communicate with databases and external systems.
  • Models or schemas: represent domain data and validate its structure.
  • Templates or serializers: produce HTML or JSON.
  • Configuration: provide environment-specific settings.

Separation does not require excessive abstraction. Its purpose is to give each component a clear responsibility. For example, a controller should not contain complex pricing rules or raw SQL when those concerns can be tested independently in a service and repository.

A useful dependency direction is from outer concerns toward inner business logic: HTTP and database details depend on application services, while core business rules should not depend unnecessarily on a particular web framework. This improves portability and testability.

3. Routing

Routing selects a handler based on an HTTP method and URL pattern. A route such as `GET /courses/{course_id}` may bind the path value to a handler parameter. Routes should express resources and actions clearly. Consistent naming helps client developers and reduces ambiguity.

A route may be static, parameterized, nested, or versioned. Examples include `/users`, `/users/42`, `/users/42/orders`, and `/api/v1/orders`. Route ordering matters in some frameworks: a general pattern can capture a request before a more specific route if it is registered first.

Good routing practice includes:

  • Use HTTP methods consistently.
  • Validate path parameters before using them.
  • Avoid exposing implementation details in URLs.
  • Define predictable error responses.
  • Version public APIs when incompatible changes are expected.
  • Keep authorization checks close to the protected operation.

Routing is not authorization. The fact that a user can reach `/admin/reports` does not mean that the user is permitted to access it.

4. Middleware and the Request Pipeline

Middleware is software that executes before, after, or around a request handler. It is appropriate for cross-cutting concerns such as request logging, correlation identifiers, authentication extraction, compression, CORS policy, rate limiting, and exception handling.

Conceptually, middleware may be represented as nested functions:

`response = M1(M2(M3(handler(request))))`

The exact implementation differs by framework. Middleware should be ordered deliberately. For example, an exception-handling layer must be able to observe errors raised by inner components, while authentication information must be available before an authorization check. Middleware should remain small and predictable; business-specific decisions usually belong in services or authorization policies.

A common error is to trust middleware merely because it ran. Middleware can attach an identity to a request, but the handler must still check whether that identity has the required permission for the particular resource.

5. Server-Rendered Templates and APIs

A server-rendered application generates HTML on the server using a template engine. Templates combine fixed presentation with controlled values supplied by the application. They are useful for content-heavy sites, administrative interfaces, and applications where initial page delivery and search indexing are important.

Template engines should escape values by default. If user input is inserted into HTML without context-appropriate escaping, cross-site scripting (XSS) may result. Developers should not disable auto-escaping unless the content is trusted and the context is fully understood. HTML, JavaScript, CSS, URL, and attribute contexts have different escaping requirements.

An API commonly returns JSON rather than HTML. API design requires stable field names, clear status codes, validation errors that are useful but not revealing, pagination for large collections, and consistent authentication mechanisms. A backend may support both HTML templates and APIs, but the response representation should be explicit and tested.

6. Sessions and State Management

HTTP is stateless: each request is independent unless the application associates requests with stored state. A session commonly uses a random session identifier stored in a browser cookie, while session data is stored server-side or in a trusted session store.

Important cookie attributes include:

  • `Secure`: sends the cookie only over HTTPS.
  • `HttpOnly`: prevents ordinary JavaScript from reading the cookie.
  • `SameSite`: limits cross-site sending and helps reduce certain cross-site request forgery attacks.
  • Appropriate expiration: limits the lifetime of the credential.

Session identifiers must be unpredictable and must be rotated after login or privilege changes to reduce session fixation risk. Logout should invalidate the server-side session where applicable. Applications should avoid putting sensitive information directly in client-controlled cookies unless it is authenticated and protected by a carefully designed mechanism.

Session storage may be in application memory, a database, or a distributed cache. In-memory storage is simple but fails when requests are distributed among multiple servers unless session affinity is used. A shared store supports horizontal scaling but introduces availability, expiration, and operational concerns.

7. Authentication and Authorization

Authentication answers “Who is the subject?” Authorization answers “What may that subject do?” Confusing these concepts is a major security defect.

Authentication may use passwords, external identity providers, passkeys, one-time codes, or certificates. Passwords must never be stored as plaintext. They should be processed using a modern adaptive password-hashing algorithm such as Argon2id, bcrypt, or scrypt, with a unique salt and an appropriately configured work factor. Password policies should encourage strong, unique passwords and should support multi-factor authentication for sensitive accounts.

A typical login sequence is:

1. Receive credentials over an encrypted connection.

2. Locate the account without exposing whether an email exists through overly specific errors.

3. Verify the password hash using a password-hashing library.

4. Establish a new authenticated session or issue a carefully protected token.

5. Record security-relevant events without logging the password or token.

Authorization models include role-based access control (RBAC), where permissions are assigned to roles, and attribute-based access control (ABAC), where decisions use attributes such as department, ownership, location, or time. Object-level authorization is essential: a user allowed to view one invoice must not automatically view another invoice merely by changing an identifier in the URL.

Authorization should be deny-by-default, centralized where practical, and tested with both permitted and denied cases. Administrative interfaces require especially strong controls, including reauthentication or multi-factor authentication for high-impact operations.

8. Validation, Sanitization, and Safe Data Handling

Validation checks whether input satisfies expected requirements. It should occur at the boundary of the system and, when necessary, again near sensitive operations. Examples include checking required fields, data types, length, range, allowed enumerations, file size, and cross-field relationships.

Validation is not the same as sanitization. Sanitization transforms input, whereas validation decides whether input is acceptable. Output encoding is a separate operation that makes data safe for a particular output context. These concepts should not be treated as interchangeable.

Database queries should use parameterized statements or a carefully implemented query builder. Constructing SQL by concatenating user input creates injection risk. Similarly, shell commands, file paths, template expressions, and dynamic code require context-specific safe APIs.

Validation errors should identify fields and acceptable requirements without exposing stack traces, database details, or internal architecture. Server-side validation is mandatory even when client-side validation exists, because clients can be bypassed.

9. Dependency Management and Secure Configuration

Modern applications depend on frameworks, libraries, runtime components, and system packages. A dependency manifest records required packages and version constraints; a lock file records a reproducible resolution where supported. Reproducible builds reduce the chance that development and production use different dependency versions.

Professional dependency management includes reviewing transitive dependencies, applying security updates, removing unused packages, scanning for known vulnerabilities, and testing upgrades. A vulnerability scanner is helpful but does not replace code review and threat analysis.

Configuration should be externalized from source code. Environment variables or a secret-management system may provide database URLs, cryptographic keys, and service credentials. Secrets must not be committed to source control, embedded in client-side bundles, or printed in logs. Production configuration should fail safely when required secrets are missing rather than silently using insecure defaults.

A useful distinction is configuration versus secret material. Port numbers and feature flags are configuration; database passwords, signing keys, and API tokens are secrets. Both require controlled deployment, but secrets need stronger access controls, rotation, auditing, and often centralized storage.

10. Logging, Monitoring, and Error Handling

Logging records events for debugging, security investigation, and operational analysis. Structured logs, commonly JSON objects, are easier for systems to search than unstructured messages. Useful fields include timestamp, severity, request or correlation identifier, route, response status, duration, and a privacy-safe user or session reference.

Applications should distinguish levels such as debug, information, warning, and error. They should not log passwords, access tokens, session identifiers, full payment data, or unnecessary personal information. Logs require retention limits and access controls because they may contain sensitive data.

Error handling should provide users with safe, meaningful responses while preserving diagnostic information for authorized operators. A global exception handler can convert unexpected exceptions into a generic 500 response and record the incident internally. Exposing a stack trace to a public client can reveal paths, queries, library versions, or credentials.

Observability also includes metrics and traces. Useful metrics include request rate, error rate, latency, saturation, authentication failures, and queue depth. Distributed tracing links operations across services using a correlation or trace identifier. Monitoring should support action, not merely collect data.

11. Security and Governance Foundations

Server applications face threats including injection, broken access control, cross-site scripting, cross-site request forgery, insecure authentication, sensitive-data exposure, misconfiguration, vulnerable dependencies, and denial-of-service attacks. Threat modeling helps teams identify assets, trust boundaries, attackers, and abuse cases before implementation.

Transport Layer Security (TLS) protects data in transit, but it does not make an application automatically secure. Access control, input handling, session protection, secure headers, dependency maintenance, and operational controls remain necessary.

Privacy principles require collecting only necessary data, explaining its purpose, limiting retention, protecting it from unauthorized access, and supporting applicable legal rights. Depending on jurisdiction and context, regulations may impose requirements concerning personal data, breach notification, accessibility, financial information, health information, or children’s data. Developers should involve legal and security specialists rather than assuming that a technical control alone establishes compliance.

12. Worked Example: A Course Registration Service

Consider an illustrative university course-registration application. Students browse courses, enroll if eligible, and withdraw. Instructors view rosters; administrators manage courses.

A route might be `POST /courses/{course_id}/enroll`. The controller first authenticates the session, validates that `course_id` is a valid identifier, and calls an enrollment service. The service checks whether the student is active, whether prerequisites are satisfied, whether the course is full, and whether the student is already enrolled. It then performs the enrollment in a database transaction.

The authorization policy differs by operation. A student may enroll themselves but may not enroll another student. An instructor may view the roster for a course they teach but not for unrelated courses. An administrator may create or close a course. These decisions should be based on the authenticated identity and the target object, not only on the URL.

A race condition can occur if two students attempt to claim the last available seat simultaneously. A robust design uses a transaction and a database constraint or locking strategy so that capacity cannot be exceeded. The application should return a clear conflict response when the seat is no longer available.

The system logs enrollment success, failure category, duration, and a correlation identifier, but not session cookies or unnecessary personal data. It exposes generic errors to clients and sends detailed diagnostics to restricted monitoring systems. Tests cover successful enrollment, missing authentication, insufficient prerequisites, duplicate enrollment, unauthorized access, and concurrent final-seat attempts.

The outcome is not merely a working endpoint. The design integrates routing, middleware, validation, authorization, transactions, logging, privacy, and operational behavior. This illustrates why server-side development is a systems discipline rather than only a programming exercise.

13. Contemporary Developments and AI Relevance

Server applications increasingly use containers, orchestration platforms, managed databases, serverless execution, and event-driven architectures. These approaches can improve deployment flexibility but also introduce distributed-state, observability, cold-start, cost, and vendor-dependence concerns.

AI-enabled applications add further server-side responsibilities. A backend may authenticate users, enforce quotas, retrieve documents, call a model provider, filter outputs, and record usage. Prompt content can contain personal or confidential information, so data governance and retention must be explicit. Applications should validate model-generated output before using it in commands, database queries, or user-visible workflows. Model responses are probabilistic and must not be treated as authoritative without appropriate verification.

Challenges and Limitations

Frameworks accelerate development but can conceal important behavior. Automatic binding, permissive serialization, default CORS settings, or generated authentication flows may be unsafe when misunderstood. Distributed systems make sessions, transactions, retries, and logging more complex. Strong security controls can introduce usability and operational costs. Excessive abstraction can slow development, while insufficient structure produces fragile code. Good engineering balances simplicity, risk, performance, and maintainability through testing and evidence.

Best-Practice Checklist

  • Use HTTPS and secure cookie attributes.
  • Separate authentication from authorization.
  • Enforce object-level authorization and deny by default.
  • Validate input on the server and use parameterized database queries.
  • Escape output according to its context.
  • Keep secrets outside source code and rotate them.
  • Pin or lock dependencies and patch vulnerabilities.
  • Use structured, privacy-aware logs.
  • Return safe errors and monitor meaningful operational signals.
  • Test negative, unauthorized, concurrent, and failure scenarios.
  • Document configuration, data retention, and incident procedures.

Chapter Summary

Server-side web development implements the request–response lifecycle and coordinates routing, middleware, business services, data access, rendering, and APIs. Robust applications separate concerns, validate untrusted input, use safe database access, and distinguish authentication from authorization. Sessions require protected cookies, suitable storage, rotation, and invalidation. Dependency manifests, lock files, externalized configuration, and secret management support reliable deployment. Structured logging, metrics, tracing, and safe error handling provide observability without exposing sensitive data. Security and privacy are architectural responsibilities involving access control, output encoding, TLS, dependency maintenance, threat modeling, and governance. The course-registration case demonstrates how these principles work together in a realistic transaction-sensitive application.

Key Terms

Request–response cycle: The process by which a client request is interpreted and answered by a server.

Route: A rule mapping an HTTP method and URL pattern to application behavior.

Middleware: Software that processes requests or responses around a handler.

Controller: A component that translates transport-level input into application operations.

Service layer: A component containing business rules and use-case coordination.

Template engine: Software that generates documents such as HTML from templates and data.

Session: Server-associated state used to relate multiple requests to a client or user.

Authentication: Verification of a subject’s identity.

Authorization: Determination of what an authenticated subject may do.

RBAC: Role-based access control, assigning permissions through roles.

ABAC: Attribute-based access control, making decisions from subject, object, and context attributes.

Validation: Checking whether input satisfies defined requirements.

Output encoding: Transforming data so it is safe in a particular output context.

Parameterized query: A database query separating code from supplied values.

Dependency: External software required by an application.

Secret: Sensitive credential or key requiring controlled protection.

Structured logging: Recording events as consistently structured fields.

Correlation identifier: A value linking logs and operations belonging to one request or transaction.

CSRF: Cross-site request forgery, an attack that induces an authenticated browser to make an unwanted request.

XSS: Cross-site scripting, injection of executable content into a user’s browser context.

Review Questions

Short Answer Questions

1. What is the difference between authentication and authorization?

2. Why should server-side validation be performed even when client-side validation exists?

3. State two important cookie security attributes and their purposes.

4. What is the role of middleware in a web application?

5. Why should secrets be excluded from source code and ordinary logs?

Long Answer Questions

1. Explain the request-processing pipeline from reverse proxy to response, including the role of routing, middleware, controllers, services, and repositories.

2. Compare server-rendered templates with JSON APIs, including security and design considerations.

3. Describe a secure login and session-management process.

4. Explain how structured logging, metrics, tracing, and error handling contribute to observability.

5. Discuss the relationship between dependency management, secure configuration, reproducible builds, and operational security.

Analytical / Application Questions

1. A student can change `/courses/101` to `/courses/102` and view another course’s private roster. Identify the design failure and propose an authorization solution.

2. An application stores sessions only in process memory but is deployed across five load-balanced servers. Analyze the likely failure and recommend two viable designs.

3. Design the processing steps for a course-enrollment endpoint that must prevent duplicate enrollment, unauthorized registration, and overbooking when many students submit requests simultaneously.

Multiple Choice Questions with Answers

Question 1

Which responsibility belongs primarily to authorization?

A. Verifying a password hash

B. Determining whether a user may edit a resource

C. Creating a session identifier

D. Parsing an HTTP method

Correct Answer: B. Determining whether a user may edit a resource

Question 2

Which cookie attribute prevents ordinary client-side JavaScript from reading the cookie?

A. Secure

B. SameSite

C. HttpOnly

D. Expires

Correct Answer: C. HttpOnly

Question 3

What is the safest general approach for incorporating user values into SQL queries?

A. String concatenation

B. Parameterized queries

C. Base64 encoding

D. HTML escaping

Correct Answer: B. Parameterized queries

Question 4

What does a 403 HTTP status generally indicate?

A. Successful creation

B. Missing resource

C. Authenticated but not permitted

D. Unexpected server failure

Correct Answer: C. Authenticated but not permitted

Question 5

Which component should normally contain business rules such as checking course prerequisites?

A. Service layer

B. DNS resolver

C. Browser cache

D. TLS certificate

Correct Answer: A. Service layer

Question 6

Why is session rotation after login useful?

A. It compresses responses

B. It reduces session fixation risk

C. It removes the need for authorization

D. It makes HTTP stateful by default

Correct Answer: B. It reduces session fixation risk

Question 7

Which practice best protects passwords at rest?

A. Plaintext storage

B. Reversible encryption only

C. Adaptive password hashing with unique salts

D. URL encoding

Correct Answer: C. Adaptive password hashing with unique salts

Question 8

What is the main purpose of structured logs?

A. To make logs easier for systems to search and analyze

B. To allow passwords to be reconstructed

C. To replace all application tests

D. To expose stack traces to users

Correct Answer: A. To make logs easier for systems to search and analyze

Question 9

Why are database transactions important in the final-seat enrollment example?

A. They guarantee unlimited capacity

B. They help coordinate concurrent updates consistently

C. They eliminate the need for authentication

D. They convert HTML into JSON

Correct Answer: B. They help coordinate concurrent updates consistently

Question 10

Which statement correctly distinguishes validation from output encoding?

A. Validation checks acceptability; encoding makes data safe for an output context

B. They are identical operations

C. Encoding replaces authorization

D. Validation is needed only in browsers

Correct Answer: A. Validation checks acceptability; encoding makes data safe for an output context

Web Technologies
Chapter 7 of 14