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'], "\\*"); }); });