|
54 | 54 | - id: cors-header |
55 | 55 | title: Access-Control-Allow-Origin on every response |
56 | 56 | area: remote-interface |
57 | | - status: decided |
| 57 | + status: fixed |
58 | 58 | canonical: >- |
59 | 59 | Every response from every endpoint carries Access-Control-Allow-Origin, on both |
60 | 60 | platforms. Android already does so for responses that reach respond(); iOS sends |
|
63 | 63 | browser client most needs to read the body. |
64 | 64 | affects: |
65 | 65 | android: >- |
66 | | - Adds "Access-Control-Allow-Origin: *" to every response |
67 | | - (RemoteServer.java, respond()). |
| 66 | + Adds "Access-Control-Allow-Origin: *" to every response; since the |
| 67 | + cors-error-paths fix on the development branch (2026-08) it is set before a |
| 68 | + request is dispatched rather than in respond() |
| 69 | + (RemoteServer.java, CorsHTTPServer.handleTransaction). |
68 | 70 | ios: >- |
69 | | - Sends no CORS header at all |
70 | | - (ExperimentWebServer.swift; GCDWebServer adds none by default). |
| 71 | + Fixed on the development branch 2026-08: every handler's completion is |
| 72 | + wrapped to add "Access-Control-Allow-Origin: *", and the static file |
| 73 | + handler was replaced so the web interface files carry it too |
| 74 | + (ExperimentWebServer.swift, cors()). Covered by an integration test |
| 75 | + (WebServerCORSTests) that checks success, error and 404 responses. |
| 76 | + The released app still sends no CORS header at all. |
71 | 77 | verified: >- |
72 | | - Confirmed on hardware 2026-08-02: Android 1.2.1-beta2 (build 1020102, |
73 | | - Pixel 9 Pro, from development) against iOS 1.2.0 (build 17272, |
74 | | - iPhone15,2, App Store build). The iOS WebServer sources are identical |
75 | | - on master and development, so the store build behaves as the |
76 | | - development branch here. |
| 78 | + Divergence confirmed on hardware 2026-08-02: Android 1.2.1-beta2 (build |
| 79 | + 1020102, Pixel 9 Pro, from development) against iOS 1.2.0 (build 17272, |
| 80 | + iPhone15,2, App Store build). The iOS fix is verified by an automated |
| 81 | + test against the running server, not yet by a cross-platform hardware |
| 82 | + comparison. |
77 | 83 | summary: >- |
78 | | - A web page served from anywhere else can read the API of an Android phone but |
79 | | - not of an iPhone, because only Android sends a CORS header. This is invisible |
80 | | - to the bundled interface, which is served by the phone itself, but it decides |
81 | | - whether a browser-based client can work at all - so a tool built and tested |
82 | | - against Android fails against iOS with an opaque browser error. |
| 84 | + A web page served from anywhere else could read the API of an Android phone |
| 85 | + but not of an iPhone, because only Android sent a CORS header. The iOS |
| 86 | + development branch now sends it on every response, including errors, so the |
| 87 | + platforms agree once that ships. The entry stays until the release carrying |
| 88 | + the fix is out, because the released iOS app still fails browser-based |
| 89 | + clients with an opaque CORS error. |
83 | 90 |
|
84 | 91 | - id: get-no-parameters |
85 | 92 | title: /get without any parameters |
|
480 | 487 | - id: cors-error-paths |
481 | 488 | title: Android drops the CORS header on requests that throw |
482 | 489 | area: remote-interface |
483 | | - status: decided |
| 490 | + status: fixed |
484 | 491 | canonical: >- |
485 | | - Follows from the group A decision: once no request reaches an unhandled |
486 | | - exception, every response is produced by respond() and carries the CORS header. |
487 | | - Nothing separate needs doing, but the entry stays until that is true, because a |
488 | | - browser client seeing an opaque CORS failure instead of an error message is the |
489 | | - symptom that will be noticed first. |
| 492 | + Every response carries the CORS header, whatever produced it. Originally |
| 493 | + expected to follow from the group A decision (no request reaching an unhandled |
| 494 | + exception), but now guaranteed at the server level on Android independent of |
| 495 | + that: the header is set before a request is dispatched, so jlhttp's own error |
| 496 | + pages carry it too, and a handler exception is turned into a plain 500 instead |
| 497 | + of reaching jlhttp's connection handling, which would discard the header. |
490 | 498 | affects: |
491 | 499 | android: >- |
492 | | - Adds "Access-Control-Allow-Origin: *" in respond(), which an unhandled |
493 | | - exception never reaches - jlhttp then serves its own text/html error page |
494 | | - without the header. Confirmed on a device: /export with no format and |
495 | | - /get with an unknown reference buffer both answer without CORS, while every |
496 | | - successful endpoint includes it (RemoteServer.java). |
| 500 | + Fixed on the development branch 2026-08: the header is added for every |
| 501 | + request before dispatch (RemoteServer.java, CorsHTTPServer.handleTransaction) |
| 502 | + and unhandled handler exceptions become jlhttp 500 error responses that keep |
| 503 | + it (withErrorResponse()). Confirmed on a device: success (single header, not |
| 504 | + duplicated), the two throwing requests (/export with no format, /get with an |
| 505 | + unknown reference buffer), 404, 405/501 on unknown methods and OPTIONS all |
| 506 | + carry the header. The released app still drops it on requests that throw. |
497 | 507 | ios: >- |
498 | | - Sends no CORS header anywhere, so the distinction does not arise. |
| 508 | + Sends the CORS header on every response including error responses since |
| 509 | + the cors-header fix on the development branch (2026-08); the released |
| 510 | + app sends none anywhere, so the distinction does not arise there. |
499 | 511 | verified: >- |
500 | | - Confirmed on hardware 2026-08-02: Android 1.2.1-beta2 (build 1020102, |
501 | | - Pixel 9 Pro, from development) against iOS 1.2.0 (build 17272, |
502 | | - iPhone15,2, App Store build). The iOS WebServer sources are identical |
503 | | - on master and development, so the store build behaves as the |
504 | | - development branch here. |
| 512 | + Divergence confirmed on hardware 2026-08-02: Android 1.2.1-beta2 (build |
| 513 | + 1020102, Pixel 9 Pro, from development) against iOS 1.2.0 (build 17272, |
| 514 | + iPhone15,2, App Store build). The Android fix verified on hardware |
| 515 | + 2026-08-07 (development build, Pixel 9 Pro) against the error paths listed |
| 516 | + above; not yet by a cross-platform comparison. |
505 | 517 | summary: >- |
506 | | - Android's CORS support is inconsistent with itself: successful responses |
507 | | - carry the header and requests that raise an exception do not. A browser |
508 | | - client therefore cannot read the error, and sees an opaque CORS failure |
| 518 | + Android's CORS support was inconsistent with itself: successful responses |
| 519 | + carried the header and requests that raise an exception did not. A browser |
| 520 | + client therefore could not read the error, and saw an opaque CORS failure |
509 | 521 | instead of the status code - the case where a useful message matters most. |
510 | | - Distinct from cors-header, which is about iOS having no CORS at all; fixing |
511 | | - that one would not fix this. |
| 522 | + Distinct from cors-header, which is about iOS having no CORS at all. Both |
| 523 | + development branches now send the header on every response; the entry stays |
| 524 | + until the releases carrying the fixes are out. |
512 | 525 |
|
513 | 526 | - id: res-content-type |
514 | 527 | title: Content-Type of a resource served by /res |
|
0 commit comments