Unlocking Efficiency: Expect Headers in HTTP Programming


  1. Client Sends Request
    The client sends an HTTP request that includes the "Expect" header. This header specifies the desired behavior from the server.

  2. Expectation and Response

    • Common Case (100-continue)
      The most common expectation is "100-continue". This tells the server that the client is about to send a large message body and wants the server to first check if it can handle it.
      • Server OK
        If the server is ready for the large message body, it responds with a status code of 100 (Continue). This tells the client to proceed with sending the data.
      • Server Not OK
        If the server cannot handle the large message body, it responds with a status code of 417 (Expectation Failed). This tells the client to stop sending the request and potentially handle the error.
  3. Hop-by-Hop vs End-to-End
    It's important to note that the "Expect" header itself is treated differently than the expectation value:

    • Expect Header
      This header is considered "end-to-end." Any intermediary (like a proxy server) must forward the header along with the request.
    • Expectation Value
      The specific expectation value (like "100-continue") is considered "hop-by-hop." This means an intermediary can decide if it can meet the expectation and send its own response if needed.

Limited Use

It's important to be aware that the "Expect" header is not widely used today. There are other mechanisms for handling large message bodies, and the "100-continue" expectation has some limitations. For example, it's only effective for HTTP/1.1 connections, not HTTP/2.

Here are some resources for further reading:



Client Code (Python)

import requests

# Example with 100-continue expectation for a large file upload
def upload_large_file(url, filename):
  headers = {"Expect": "100-continue", "Content-Type": "application/octet-stream"}
  with open(filename, "rb") as f:
    # Send initial request with headers
    response = requests.put(url, headers=headers)
    
    # Check for 100 Continue response
    if response.status_code == 100:
      # Upload the file data
      response = requests.put(url, data=f, headers=headers)
      # Handle successful or failed upload based on response.status_code
    else:
      # Handle expectation failed scenario (e.g., close file, notify user)
      print(f"Upload failed: {response.status_code}")

# Example usage
upload_large_file("https://example.com/upload", "large_file.data")

Server Code (Node.js)

const http = require('http');

const server = http.createServer((req, res) => {
  if (req.headers.expect === "100-continue") {
    # Check if server can handle the request (e.g., check available storage)
    if (/* conditions met */) {
      res.writeHead(100);  # Send 100 Continue
    } else {
      res.writeHead(417);  # Send 417 Expectation Failed
    }
    res.end();
  } else {
    # Handle requests without Expect header
    # ...
  }
});

server.listen(3000);
  • Remember that "Expect" header usage is not as common today due to limitations and alternative methods for handling large data transfers.
  • These are simplified examples for demonstration purposes. Real-world implementations might involve additional logic and error handling.


  1. Content-Length Header
    This header specifies the size of the request body in bytes. The server can use this information to determine if it has enough space to handle the request before processing it further.

  2. Pre-flight Requests (CORS)
    For Cross-Origin Resource Sharing (CORS) scenarios, browsers can send an OPTIONS request (pre-flight request) before sending the actual request. This allows the server to indicate if it will accept the request with specific headers or methods.

  3. HTTP Chunked Encoding
    This encoding allows the client to send the request body in chunks of data. This can be useful for large uploads where you don't know the total size beforehand. The server can process each chunk independently and provide feedback after each chunk.

  4. Server Push (HTTP/2)
    In HTTP/2, the server can proactively push resources to the client that it anticipates will be needed based on the initial request. This eliminates the need for the client to request resources individually, potentially improving performance.

Choosing the Right Option

  • Server Push
    Improves performance for predictable resource needs, but requires using HTTP/2 and server-side configuration.
  • Chunked Encoding
    Flexible for large uploads with unknown size, but requires server support for handling chunks.
  • Pre-flight Requests
    Useful for CORS scenarios, but adds an extra request-response cycle.
  • Content-Length
    Simple and widely supported, but requires knowing the exact size beforehand.