Page MenuHomePhabricator

404 responses do not specify CORS headers
Closed, ResolvedPublic

Description

All responses from RESTBase, even errors, should include Cross-Origin Resource Sharing headers so that unprivileged clients, such as browsers, can examine the responses. Currently cross-origin headers are set for successful responses but 404s do not specify any which, in the case of the browser Fetch API, causes them to appear as TypeErrors with little detail. See below in Chromium and Firefox (note the different URLs!):

OK

$ fetch('https://appservice.wmflabs.org/en.wikipedia.org/v1/page/mobile-sections/Nonexistent_title').then(console.log)
Response {type: "cors", url: "https://appservice.wmflabs.org/en.wikipedia.org/v1/page/mobile-sections/Nonexistent_title", redirected: false, status: 404, ok: false, …}

// Headers...
access-control-allow-headers:accept, x-requested-with, content-type
access-control-allow-origin:*
access-control-expose-headers:etag
content-encoding:gzip
content-security-policy:default-src 'self'; object-src 'none'; media-src *; img-src *; style-src *; frame-ancestors 'self'
content-type:application/json; charset=utf-8
date:Tue, 05 Dec 2017 14:59:53 GMT
server:nginx/1.13.6
status:404
vary:Accept-Encoding
x-content-security-policy:default-src 'self'; object-src 'none'; media-src *; img-src *; style-src *; frame-ancestors 'self'
x-content-type-options:nosniff
x-frame-options:SAMEORIGIN
x-webkit-csp:default-src 'self'; object-src 'none'; media-src *; img-src *; style-src *; frame-ancestors 'self'
x-xss-protection:1; mode=block

Missing CORS headers

$ fetch('https://en.wikipedia.org/api/rest_v1/page/mobile-sections/Nonexistent_title').then(console.log)
Uncaught (in promise) TypeError: Failed to fetch
GET https://en.wikipedia.org/api/rest_v1/page/mobile-sections/Nonexistent_title net::ERR_FAILED

// Headers...
age:0
cache-control:private, max-age=0, s-maxage=0, must-revalidate
content-encoding:gzip
content-length:170
content-location:https://en.wikipedia.org/api/rest_v1/page/mobile-sections/Nonexistent_title
content-type:application/problem+json
date:Tue, 05 Dec 2017 15:00:21 GMT
server:restbase1017
set-cookie:WMF-Last-Access-Global=05-Dec-2017;Path=/;Domain=.wikipedia.org;HttpOnly;secure;Expires=Sat, 06 Jan 2018 12:00:00 GMT
set-cookie:GeoIP=US:TN:Cordova:35.14:-89.77:v4; Path=/; secure; Domain=.wikipedia.org
set-cookie:WMF-Last-Access=05-Dec-2017;Path=/;HttpOnly;secure;Expires=Sat, 06 Jan 2018 12:00:00 GMT
set-cookie:CP=H2; Path=/; secure
status:404
strict-transport-security:max-age=106384710; includeSubDomains; preload
vary:Accept-Encoding
via:1.1 varnish-v4, 1.1 varnish-v4
x-analytics:https=1;nocookies=1
x-cache:cp1053 pass, cp1068 pass
x-cache-status:pass
x-client-ip:73.252.38.252
x-request-id:0398e947-d9cd-11e7-86d1-e1c75b48fb7a
x-varnish:481340269, 768463128

Fixing this bug should include adding a few tests. Something like:

it('Should fetch CORS headers even for missing pages on mobile-sections', () => {
    return preq.get({
        uri: `${server.config.bucketURL}/mobile-sections/Nonexistent_title`
    })
    .catch((res) => {
        assert.deepEqual(res.status, 404);
        assert.deepEqual(res.headers['access-control-allow-origin'], "\\*");
    });
});

Event Timeline

mobrovac subscribed.

Huh, this is likely happening because adding CORS is now a filter operation in RESTBase, but they are not obeyed for 4xx and 5xx responses.

Filters are executed for errors as well, but we mistakenly were only adding headers under .then and not .catch

Mentioned in SAL (#wikimedia-operations) [2017-12-07T11:05:35Z] <mobrovac@tin> Started deploy [restbase/deploy@097ba7d]: Add CORS headers to erroneous responses as well - T182103

Mentioned in SAL (#wikimedia-operations) [2017-12-07T11:10:59Z] <mobrovac@tin> Finished deploy [restbase/deploy@097ba7d]: Add CORS headers to erroneous responses as well - T182103 (duration: 05m 24s)

mobrovac reassigned this task from Niedzielski to Pchelolo.
mobrovac triaged this task as Medium priority.
mobrovac edited projects, added Services (done), RESTBase-API; removed Services (next).

The fix has been deployed and verified. All public REST API responses have the CORS headers set now.