Using conditional requests with 100 Continue

Austin Wright <> Mon, 21 October 2019 22:44 UTC

Return-Path: <>
Received: from localhost (localhost []) by (Postfix) with ESMTP id B7F4F120A71 for <>; Mon, 21 Oct 2019 15:44:56 -0700 (PDT)
X-Virus-Scanned: amavisd-new at
X-Spam-Flag: NO
X-Spam-Score: -2.751
X-Spam-Status: No, score=-2.751 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, HTML_MESSAGE=0.001, MAILING_LIST_MULTI=-1, SPF_PASS=-0.001] autolearn=ham autolearn_force=no
Authentication-Results: (amavisd-new); dkim=pass (1024-bit key)
Received: from ([]) by localhost ( []) (amavisd-new, port 10024) with ESMTP id fUEVuW2Cw-Rh for <>; Mon, 21 Oct 2019 15:44:54 -0700 (PDT)
Received: from ( [IPv6:2603:400a:ffff:804:801e:34:0:38]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by (Postfix) with ESMTPS id A6563120A6D for <>; Mon, 21 Oct 2019 15:44:54 -0700 (PDT)
Received: from lists by with local (Exim 4.89) (envelope-from <>) id 1iMgN7-0005J4-8l for; Mon, 21 Oct 2019 22:41:53 +0000
Resent-Date: Mon, 21 Oct 2019 22:41:53 +0000
Resent-Message-Id: <>
Received: from ([2603:400a:ffff:804:801e:34:0:4f]) by with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from <>) id 1iMgN5-0004zE-O7 for; Mon, 21 Oct 2019 22:41:51 +0000
Received: from ([2607:f8b0:4864:20::42a]) by with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from <>) id 1iMgN3-0004O4-Oc for; Mon, 21 Oct 2019 22:41:51 +0000
Received: by with SMTP id b128so9351871pfa.1 for <>; Mon, 21 Oct 2019 15:41:48 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=google; h=from:mime-version:subject:message-id:date:to; bh=JoT7PO+h0QmR5I3rW8HH3MqFEoViMRooSamZEuED7ic=; b=XyASabEB2sb7G4Kz8Nwj5hSNZKoah1gXPahQOKQL+fe4VYdVVjzNQbfW1CNm3WdaZ0 1t1wjbndBv5yk6OoGH2CJbAoVeUKhmDoLSCNtkaNvqoxkfj0TCtng0yXtz5QZuNAx83i Xzr2B3Fk3ZcGJUYUrPXsTCM4WDMeFSKwl70/Y=
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; s=20161025; h=x-gm-message-state:from:mime-version:subject:message-id:date:to; bh=JoT7PO+h0QmR5I3rW8HH3MqFEoViMRooSamZEuED7ic=; b=dqu2Q36RqOSq6spEWqSgS2xWOPWLINjo+Aw+kImKe92hUbRcdzvkZGQUjZ9hkaxJhl Q/enZH95MHtg36FWtN3mgpajFJWIM1dPfelp5r643J60A0SVCcNlB0Q3WAJKr9Rmx0q7 JAOd7fdob8EInc5sVmbVWpMdtBGzog1/oG1ijFfWV+rn6i5PQZGTIbbjSrBE6d03OzwZ 9QQGE6HlqhcHoyoBN9xelvnAzQNk741MJvsPo3oCfjC1TmOXftRIbBtE8iWQq1kx7LZ8 61D9IBl5N/6O4PcjOiWHkMuIuUXWJ+KVFGrpfokCxVNOdboflYdlWnHsIZSnCp+vpCpj P2mA==
X-Gm-Message-State: APjAAAX3GIHxg9jTXrom/14vI9/quqURxm/Q5fWiqjmpQElgUqOvrCNB X7FUhJp+/Es+alP/llsbXXotyh+es+Y=
X-Google-Smtp-Source: APXvYqxttcvxzXa7Ct6Wv6pIRsW270pehubqNB+TZWaYjIjHFJlmdESPpQACNpF8pjTwYzA3tZIo+A==
X-Received: by 2002:a62:1b43:: with SMTP id b64mr483795pfb.56.1571697707179; Mon, 21 Oct 2019 15:41:47 -0700 (PDT)
Received: from [] ( []) by with ESMTPSA id s141sm18748493pfs.13.2019. for <> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Oct 2019 15:41:45 -0700 (PDT)
From: Austin Wright <>
Content-Type: multipart/alternative; boundary="Apple-Mail=_85A2CD6D-948E-46EE-9C52-DECFC094ACC5"
Mime-Version: 1.0 (Mac OS X Mail 13.0 \(3594.4.19\))
Message-Id: <>
Date: Mon, 21 Oct 2019 15:41:44 -0700
X-Mailer: Apple Mail (2.3594.4.19)
Received-SPF: pass client-ip=2607:f8b0:4864:20::42a;;
X-W3C-Hub-Spam-Status: No, score=-6.1
X-W3C-Hub-Spam-Report: BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, W3C_AA=-1, W3C_DB=-1, W3C_IRA=-1, W3C_WL=-1
X-W3C-Scan-Sig: 1iMgN3-0004O4-Oc 3d75f759cee9372efa47583b618401c9
Subject: Using conditional requests with 100 Continue
Archived-At: <>
X-Mailing-List: <> archive/latest/37067
Precedence: list
List-Id: <>
List-Help: <>
List-Post: <>
List-Unsubscribe: <>


I’m reading through RFC 7231 and RFC 7232 to implement an HTTP server that supports a PUT method on a resource, with 100 Continue and 412 Precondition Failed responses; and I am wondering why 412 must be tested last, after all other errors.

The uploaded document must conform to certain media type and validation requirements, perhaps responding with an error like 400 (Bad Request) or 422 (Unprocessable Entity) if the upload is not well-formed. Suppose I issue a request with:

Expect: 100-continue
If-Match: “etag”

In this case, it seems to me the server should issue a 412 Precondition Failed if the resource has been changed, and that I shouldn’t have to upload the entire document just to find out that it has been changed. Yet, RFC 7232 HTTP Conditional Requests says:

> A server MUST ignore all received preconditions if its response to the same request without those conditions would have been a status code other than a 2xx (Successful) or 412 (Precondition Failed). In other words, redirects and failures take precedence over the evaluation of preconditions in conditional requests.

This suggests that I must validate the document in its entirety if I’m going to return a status like 422, before testing the precondition, even if the upload is very long.

(1) Is there a particular reason that the precondition test must be tested after all other 4xx (even 5xx) errors?

Now, I imagine this requirement might have the effect of reducing some race conditions, but even then it would not completely eliminate race conditions, without a way of locking the database/filesystem record for writing.

(2) Are there clients in the wild that would be broken if the precondition test happened earlier? i.e. are there any clients that would incorrectly assume the upload is well-formed if they received a 412 error instead of a 400, 415, and/or 422?

(3) For 100-continue and performance purposes, can this limitation be relaxed so it’s the last thing tested before errors relating to the request entity-body?