Skip to content

Archive

HTTP

70 articles
Cybersecurity 13 Sep 2026 7 min read

Cache Keys Are Security Boundaries at the HTTP Edge

Cache Keys Are Security Boundaries at the HTTP Edge A reverse proxy can receive two requests that an application considers different and still treat them as the same cache entry. That gap is enough to turn a response intended for one request context into a response served to many others. The issue is not caching in isolation. It is disagreement about identity. Applications make decisions from headers, query parameters, cookies, paths, host information, and sometimes values added by upstream infrastructure. A shared cache uses a smaller set of inputs to decide whether a stored response matches a later request. If an input changes application behavior but does not participate in the cache key, that input crosses a security boundary without being represented in cache identity.

Go 13 Sep 2026 4 min read

Bound HTTP Request Bodies with http.MaxBytesReader in Go

An HTTP handler that decodes a request body without a byte limit can consume far more input than its application-level schema suggests. A JSON object with three fields may still arrive inside a multi-gigabyte body. Decoder validation controls structure; it does not establish a transport-sized boundary. Go’s http.MaxBytesReader places that boundary directly around the request body. It returns an io.ReadCloser that permits reads up to a configured limit and reports an error when code attempts to read beyond it.

Go 12 Sep 2026 5 min read

Reject Cross-Origin State Changes with http.CrossOriginProtection

A browser can send credentials with a request that was initiated from another site. For state-changing endpoints, accepting that request without checking its origin can expose an application to cross-site request forgery. Go’s net/http package includes CrossOriginProtection for placing that check at an HTTP handler boundary. The type does not attempt to identify every browser request. It applies a specific policy based on request method and cross-origin signals, while allowing requests that lack those browser-origin signals. Its behavior is narrow enough that endpoint semantics still matter.

Go 12 Sep 2026 5 min read

Interleave HTTP Request Reads and Response Writes in Go

An HTTP handler that writes its response before finishing the request body has a protocol-sensitive edge case. With HTTP/1, Go’s server normally consumes the unread request body before it begins writing the response. That default keeps ordinary handlers simple, but it conflicts with handlers that intentionally exchange data in both directions at the same time. http.ResponseController.EnableFullDuplex changes that behavior for the current request. It tells the server that the handler intends to interleave reads from Request.Body with writes to the ResponseWriter.

Go 12 Sep 2026 5 min read

Flush Buffered HTTP Data with http.ResponseController in Go

An HTTP handler can write bytes without making those bytes immediately visible to the client. The server, transport, middleware, or another layer may buffer response data. For handlers that emit incremental output, http.ResponseController.Flush provides an explicit request to push buffered data toward the client. The operation belongs to the current response. It does not turn a normal handler into a separate transport protocol, and it does not guarantee that every intermediary on the network will forward each chunk at the same instant. Its useful contract is narrower: ask the active response writer to flush data it has buffered.

Software Engineering 12 Sep 2026 8 min read

Conditional HTTP Writes with Entity Tags

Conditional HTTP Writes with Entity Tags A client reads a resource, edits its local copy, and sends a replacement several seconds later. During that interval another client may have committed a different replacement. A plain PUT has no statement about the representation on which the edit was based, so the server can accept a request whose starting state is already obsolete. HTTP conditional requests can carry that missing premise. A response entity tag identifies a selected representation, and If-Match makes a later request conditional on a current representation matching one of the supplied tags. For state-changing methods, that turns representation identity into an explicit concurrency boundary.

Tech 12 Sep 2026 5 min read

Browser Cache and Stale Web Files

A website can change on its server while one browser still shows an older image, script, or page response. Opening the same address in another browser may show the new version immediately. That difference often comes from the browser’s HTTP cache, which can reuse stored responses instead of downloading the same bytes again. The browser cache is not simply a folder of files that are either present or absent. HTTP gives cached responses a freshness state and provides validators that can check whether stored content still matches the server. Those rules determine when reuse avoids a network transfer and when the browser has to contact the server again.

Cybersecurity 11 Sep 2026 9 min read

Validate Host Authority Before Trusting Request Metadata

HTTP applications often need to know which host a client intended to reach. Frameworks expose that value through fields such as Host, request.host, or a parsed request authority. It can look like infrastructure metadata, but at an application boundary it is commonly influenced by the client. That distinction matters when an application uses the value for security-sensitive work. A hostile authority can affect absolute links, redirects, cache entries, tenant selection, origin checks, or routing decisions if the application accepts it without a trust policy.

Cybersecurity 11 Sep 2026 10 min read

Reject Ambiguous HTTP Request Framing

A reverse proxy and an application server can both accept the same HTTP connection and still disagree about where one request ends and the next begins. That disagreement is more than a parsing bug. On a reused connection, bytes that one component treats as part of a request can be interpreted by another component as the start of a second request. This class of problem is called HTTP request smuggling, or more generally HTTP desynchronization. The practical defensive goal isn’t to recognize every historical attack variation. It is to make request boundaries unambiguous at every hop, reject malformed framing instead of guessing, and test the exact proxy-to-backend path that production traffic uses.

Go 10 Sep 2026 7 min read

Set Per-Response Write Deadlines in Go with http.ResponseController

A server-wide WriteTimeout is a useful safety net, but some handlers have different timing needs. A small JSON response and a streaming export shouldn’t necessarily share the same write budget. When the deadline belongs to one response rather than the whole server, Go’s http.ResponseController gives the handler a direct way to set it. http.ResponseController.SetWriteDeadline applies a write deadline to the current response. It also solves a practical middleware problem: instead of asserting a concrete optional interface at every call site, a handler can ask the controller to find the capability through compatible ResponseWriter wrappers.

Go 07 Sep 2026 9 min read

Handle Go HTTP Response Bodies Without Leaking Connections

An HTTP request can appear to work while quietly making later requests more expensive. A common cause in Go clients is mishandling http.Response.Body: forgetting to close it, returning before cleanup is arranged, or assuming that an HTTP error status is returned as a Go error. The important mental model is that a successful Client.Do call gives your code ownership of a stream, not a byte slice. The response headers have arrived, but the body is consumed as you read it. Your code must decide how much of that stream it needs and must close it when finished.

Software Engineering 02 Sep 2026 9 min read

Preventing Lost Updates with HTTP ETags and Conditional Requests

Two clients can read the same resource, make different edits, and then save them seconds apart. Without a concurrency check, the later write can silently replace the earlier one. This is the lost update problem. HTTP already provides a protocol-level mechanism for avoiding that failure: validators such as entity tags (ETags) combined with conditional request headers. Used correctly, they let a client say, “apply this change only if the resource is still the version I read.”

Web Development 02 Sep 2026 5 min read

HTTP Range Requests for Efficient Partial Downloads

HTTP range requests let a client ask for only part of a representation instead of downloading the entire body. They are useful for resumable downloads, media seeking, large files, and clients that need a known byte segment. The core mechanism is simple, but correct servers need to distinguish valid ranges, unsatisfiable ranges, validators, and ordinary full responses. A client requests a byte range A request can include: Range: bytes=1000-1999 If the server supports the request and the selected representation is 8,000 bytes long, it can respond:

Web Development 02 Sep 2026 5 min read

HTTP Content Negotiation and Correct Vary Headers

One URL can sometimes represent the same resource in several formats. An API might return JSON or CSV, while a documentation endpoint might return HTML or plain text. HTTP content negotiation lets a client express which representation it can accept. The server chooses a response and tells caches which request headers influenced that choice. The second part is easy to miss: if the response changes based on a request header, shared caches need the correct Vary metadata.

Web Development 01 Sep 2026 3 min read

Use HTTP 103 Early Hints Without Breaking Page Delivery

A server may need time to produce an HTML response even though it already knows that the page will require a stylesheet or other critical resource. HTTP 103 Early Hints lets the server send selected Link hints before the final response so a supporting client can begin useful work sooner. The optimization is optional: the final response still determines the page result. Understand the response sequence A simplified exchange looks like this:

Go 01 Sep 2026 7 min read

Token Bucket Rate Limiting in Go

Rate limiting protects a service from traffic spikes, accidental client loops, and workloads that consume more resources than the system can safely handle. A useful limiter should do more than enforce a fixed request count: it should allow small bursts while keeping the long-term request rate bounded. The token bucket algorithm provides exactly that behavior. This guide implements a small, concurrency-safe token bucket using only Go’s standard library and then shows how to use it in an HTTP service.

Go 01 Sep 2026 8 min read

Testing Go HTTP Handlers with httptest

HTTP handlers are one of the easiest parts of a Go service to test well. You usually do not need to bind a real network port, start the entire application, or depend on an external test framework. Go’s standard library provides net/http/httptest, which can construct HTTP requests, capture handler responses, and even start temporary HTTP servers when a real client-server round trip matters. This guide builds a small JSON endpoint and tests it at several useful levels.

Web Development 01 Sep 2026 6 min read

Liveness and Readiness Health Checks for Backend Services

Health endpoints look simple, but their semantics directly affect how a production platform routes traffic and restarts applications. A poorly designed check can turn a temporary database slowdown into a restart loop or send requests to an instance that has not finished initializing. The most useful model separates two questions: Liveness: Is this process still capable of running? Readiness: Should this instance receive new traffic right now? Those questions sound similar, but they should usually have different answers and different failure behavior.

Web Development 01 Sep 2026 8 min read

Idempotency Keys for Safe API Retries

Retries are essential in distributed systems. Networks fail, clients time out, load balancers reset connections, and responses sometimes disappear after a server has already committed a write. The dangerous case is a retry of a non-idempotent operation. If a client sends POST /orders, times out, and sends the same request again, the server may create two orders even though the user intended one. An idempotency key gives the client a stable identifier for one logical operation. The server remembers the result associated with that key and can return the same result when the request is retried.

Web Development 01 Sep 2026 4 min read

HTTP Conditional Requests with ETag and Last-Modified

HTTP caching is not only about choosing a long max-age. Applications often need clients to revalidate data because a resource can change, while still avoiding retransmitting the full representation when it has not changed. HTTP validators solve that problem. The two common validators are ETag and Last-Modified. Freshness and validation are different A freshness directive can tell a cache that a response may be reused without contacting the server for a period:

Go 01 Sep 2026 7 min read

Graceful HTTP Server Shutdown in Go

Stopping a web server with Ctrl+C looks harmless during development, but production deployments need a more careful shutdown process. If a process exits immediately, active HTTP requests can be interrupted, clients may receive connection errors, and in-flight work can be left unfinished. Go’s standard library already provides the pieces needed for a clean shutdown. The main tools are os/signal, context, and http.Server.Shutdown. This guide shows a practical pattern for shutting down an HTTP server when the process receives SIGINT or SIGTERM.

Go 01 Sep 2026 8 min read

Go Context Timeouts and Request Cancellation

A Go HTTP handler can outlive the request that started it unless the work inside the handler pays attention to cancellation. That matters when a client disconnects, an upstream request takes too long, or a database query is no longer useful. Go solves this with context.Context. Every incoming *http.Request already has a context, and that context is canceled when the client connection closes, the request is canceled by HTTP/2, or the handler returns. You can also derive a shorter deadline for work that should not consume the entire request lifetime.