HTTP If-None-Match header not working correctly

@Simeon I believe this may be a bug but I can’t tell if this would be something wrong with Codea’s implementation or an underlying library.

The code below just needs running a couple of times to reproduce the issue described.

-- HttpIssue

-- Expected result:
--  When requesting the URL the 'If-None-Match' header should be respected and return a '304 Not Modified' status
--  if the etag value we provide matches that on the server.

-- Actual result:
--  Even when the etag we send with the request in the header matches that in the header we receive back, we are
--  still only provided with a 200 status.

-- I have verified this actually performs a request and the response is not cached in the larger WebRepo project
-- using the GitHub API. The API provides a rate limit count in the response headers which are decrementing with
-- each request like this when they shouldn't be.

-- Using CURL with the same url and header this issue does not reproduce and everything behaves as expected returning
-- a 304 status

function setup()
    
    local function on_success(data, status, headers)
        print("Response status:", status)
        print("ETag received:", headers.Etag)
        if status == 200 then -- New response
            print("New Response")
            saveLocalData("etag", headers.Etag)
        elseif status == 304 then -- Response changed
            print("Not modified")
        else
            print("No Response")
        end
    end
    
    local function on_fail(err)
        error(err)
    end
    
    local http_params = {
        ["method"] = "HEAD",
        ["headers"] = {
            ["If-None-Match"] = readLocalData("etag")
        }
    }
    print("ETag sent with request:", http_params.headers["If-None-Match"])
    
    http.request("https://codea.io", on_success, on_fail, http_params)
end

This actually seems to be returning a 304 ‘Error’ if I close and restart the Codea app completely :confused:

Ah, I have no idea why but as soon as I add the Github API ‘ Authorization’ request header & token everything breaks… Seems like it could be on GitHubs end

So I have no clue why this is happening but I’ve narrowed it down to the request params.

local http_params = {
        ["method"] = "GET",
        ["headers"] = {
            ["Authorization"] = "token " .. api_token,
            ["Accept"] = "application/vnd.github.v3+json",
            ["If-None-Match"] = readLocalData("sha:/" .. path)
        }
    }

If I remove either Authorization or Accept (or both) then it consistently returns the 304 error in the failure callback instead. This also works using CURL with all 3 headers.

I personally don’t think it should be classifying it as a failure either.

@Simeon Is Codea perhaps using NSURLRequest or NSURLConnectionDataDelegate ?

If so the comments on this SO question could be useful.

Having looked at this a little more it seems incredibly inconsistent. I can (sometimes) receive a 304 error signalling that I should be using my cached value, so I do. But then if I cause it to succeed with a 200 status (by removing any header from the request) the rate limit value returned in the response header has decreased for the 304 request too!

I feel like iOS or some system API caching is playing havoc with the requests.

@Steppers thanks for bringing this to my attention. I’ll look into it too