If you load up a copy of a fresh spankin' new 8.x installation in the iOS simulator, instead of getting lovely responsive Bartik, you instead get this:

I tracked this down to http://drupalcode.org/project/drupal.git/blob/refs/heads/8.x:/core/lib/D... (the onView() method of the core/lib/Drupal/Core/EventSubscriber/ViewSubscriber.php class). The following code:
$method = 'on' . $this->negotiation->getContentType($request);
...returns 'xml' on the iOS simulator, and 'html' in Chrome on the desktop. And because there is no onXml function, it bails.
This doesn't happen with a real iPhone 4s, nor does it happen with Safari on Snow Leopard, but it does happen with the iOS simulator that's part of XCode. I'm filing it as a normal bug just in case it's endemic of a larger problem. Is this how a browser reacts when it doesn't understand the HTML5 doctype?
| Comment | File | Size | Author |
|---|---|---|---|
| #36 | i1716790-35.patch | 3.76 KB | attiks |
| #36 | interdiff.txt | 994 bytes | attiks |
| #30 | i1716790-30.patch | 3.49 KB | attiks |
| #28 | unique_accept.txt | 6.71 KB | attiks |
| #28 | wrong_headers.csv_.txt | 56.37 KB | attiks |
Comments
Comment #1
Crell commentedThat's highly weird. It sounds like the Simulator is sending the wrong Accept header. Can you drop some debug code into the negotiation library to see what it's actually sending?
We want to change that mechanism anyway once we have the ability to, but it's good to know what broken systems we have to deal with. :-/
Comment #2
mcjim commentedI was using the iOS Simulator throughout Drupalcon (as part of working on the mobile initiative for 8.x), re-installing regularly, and didn't notice this.
I wonder if it's particular to the version? I'm using version 5.1 on Mountain Lion and
$this->negotiation->getContentType($request);returns 'html'.Comment #3
webchickHm. Possibly! I'm on Snow Leopard. If no one else is seeing this we can probably close this issue.
Comment #4
edward_or commentedI get the same error on iOS Simulator Snow Leopard.
I have access to a device running ios3.1 and I get the same error on that.
Comment #5
mcjim commentedI'll download the iOS 4 and 3 simulators and test on those.
Comment #6
mcjim commentedAh! On Mountain Lion, doesn't appear to be an (easy) way to get hold of the older simulators.
Managed to test on an actual iPod Touch running 4.2.1 and can confirm the problem exists there also. Have changed the issue title as it's an iOS issue in general, not just a simulator one.
Comment #7
Crell commentedSo let me understand this...
Older versions of iOS asked for an HTML page using a mime type of 'text/xml', 'application/xml', or 'application/x-xml' (the three mime types that would map to "xml" right now) when what they want to get back is text/html? That cannot possibly be right, or it would have broken a few zillion other systems by now.
What's the actual mime type that's being sent/received? Can you throw some debug lines into the code to get the raw Accept header?
Comment #8
mcjim commentediOS 4.2.1 request headers:
iOS 5.1 request headers:
The main difference in the accept header is the ordering: in 4.2.1 application/xml and application/xhtml+xml come before text/html.
Comment #9
mcjim commentedLooking into this further, iOS 4.2.1 returns the following for
$request->getAcceptableContentTypes()in the getContentType method of the ContentNegotiation class:and
$format = $request->getFormat($mime_type);is not null, soxmlgets returned.Comment #10
Crell commentedOh Apple, you so silly... And by silly, I mean *expletive deleted*
I believe the current logic will match the first listed type. Why Safari Mobile is asking for raw undefined XML data as a higher preference to HTML I have no bloody idea, but we may need to hard code text/html as the first check for now. We still need to clean up that negotiation library, but... *sigh*
Comment #11
jessebeach commentedI just logged the same issue on Android devices at version 2.3.3
#1802882: Pages requested on older Android devices (verified on 2.3.3) return a page with the error "Unsupported Media Type"
I'll close as a duplicate. I'm trying to get header info out of Charles now.
Comment #12
webchickHighlighting that this is not just an Apple problem. :)
Comment #13
nod_tag
Comment #14
attiks commentedThis is a webkit problem, caused by a 'strange' design decision, for some reason they choose to use the accept headers from FF 2.0, it is fixed in later version (FF fixed it in FF 3.0)
Related issues:
Bumping this to major, but no idea if this is 'our' problem.
Comment #15
Crell commentedIt looks like we'll have to figure out some way to work around this webkit bug, even if it's not our problem per se. :-( Probably as part of whatever cleanup we do to the content negotiation system.
Which, I think Fabpot just said he's going to look into, so I'll make sure he's aware of this issue. :-)
Comment #16
attiks commentedI found a closed issue for symfony at https://github.com/symfony/symfony/pull/564
Comment #17
sunI've experienced this bug on each and every Android mobile device I got into my hands in the past six months or so. (testing the web site of my local DUG)
D7 sites are working fine, so this presents a really critical regression.
It's a little strange that the same bug does not occur on symfony.com. I therefore wonder whether this really is a upstream bug in Symfony, or whether it isn't caused by our own code.
In any case, we cannot release with this.
Comment #18
attiks commentedThis isn't a symfony problem, but it would be nice if they got a solution.
Problem is caused by this code , it returns as soon as it finds a valid format:
Very ugly working fix, see http://picturefill8.h011.attiks.com:
Comment #19
chx commentedIf I were fixing this bug I would hardwire "^application/xml,application/xhtml+xml,text/html" and parse it as HTML.
Comment #20
chx commentedComment #21
attiks commentedI think it's safer to check only for text/html since all browsers will be sending this. If you add others you will complicate things for services.
something like this
Comment #22
fabianx commented#20: Needs work as my Android sends:
So it tries hard :-D.
#21:
Works, BUT:
I am not sure this will work in all circumstances, because it completely ignores the order.
Comment #23
attiks commented#22 patch in #21 ignores the order, AFAIK this is the only way to make sure we always find the text/html part. I'm assuming that non-browser clients aren't going to send text/html, but not tested.
Comment #24
sunI collected the browser Accept headers mentioned in this and all referenced issues, and turned them into a regression test.
Chrome 2009 fails, too.
Comment #25
attiks commentedSome examples of browsers sending the wrong headers (list of UA):
Source: http://whatheaders.com/data/
PS: In the same data files are even request without any accept header :/
Comment #26
sunDidn't see #22 yet. Incorporated.
That said, #22 is not entirely clear - those are two separate Accept headers from separate requests, right?
Comment #27
fabianx commented@sun: My Android (Nexus One, Froyo 2.2) sends first the first header (application), then if that fails it tries again with the second header (text). Only the first header needs to be supported IMHO.
If the header is accepted, then the second header (text) is never send.
Comment #28
attiks commentedI analyzed the data a bit further:
In total the xml file contains 3508 request, from those 354 (10%) are not starting with */*, text/* or text/html
Those 354 request (wrong_headers.csv) contain 33 unique accept headers (unique_accept.txt)
Comment #30
attiks commentedCombined patch from #21 and #26
Comment #31
damien tournoud commentedPlease refactor this so that we use the parsed
$request->getAcceptableContentTypes()instead of this ugly (and incorrect) string parsing.Comment #32
damien tournoud commentedComment #33
attiks commented#31 you mean something like this:
Care to clarify the " incorrect"
Comment #34
fabianx commentedI agree with #31.
Pseudo-Code (not working):
Comment #35
Crell commentedIn general I agree with the approach of "if there's text/html in there anywhere, it wins". Browsers tend to be crap at Accept headers, but anything else should be fairly sane with what it sends so we can trust them to not be stupid.
Comment #36
attiks commentedSince there's no way to map them all at once, we have to loop through all mime types.
If HTML is found, it is returned, otherwise the first valid found is returned.
Comment #37
shyamala commentedPatch #36 works on Sony Ericsson android device and ipad simulator 4.3
Before the patch is applied, get an error "Unsupported Media Type". Able to access the site after applying the patch.
Comment #38
attiks commentedWe need to decide first:
Keep in mind that this code gets executed for every request.
Comment #39
webchickIs it possible to decide this with benchmarks? Or would the difference be too negligible? I understand why #36 is more correct, but we might indeed want to optimize here by knowingly choosing a less correct pattern in the interest of speed.
Comment #40
Crell commentedI wouldn't worry about micro-optimising this at this point. For now let's just make it work, since this code path may end up rarely used if we get proper conneg in place and SCOTCH has its way (which I hope it does). Focus on most reliable/robust for now.
Comment #41
Crell commentedBah, stupid issue forms...
Comment #42
attiks commentedso that means #36 is up for review
Comment #43
shyamala commented+1 for #36
Patch #36 works on Sony Ericsson android device and ipad simulator 4.3
Before the patch is applied, get an error "Unsupported Media Type". Able to access the site after applying the patch.
Comment #44
fabianx commentedPerformance is fine:
This compares core requested via "Accept: text/html,application/xml,application/xhtml+xml;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" vs. #36 with "Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5".
Such 2 additional calls to getFormat, which result in 12 calls to strpos. One call to getFormat takes around 22 microsecs.
=> to scale this to a worst case: 22 microsecs * number of formats in accept header. Lets assume 20 => 400 microsecs => 0.4 ms.
=> Micro Optimization as Crell said. The rest is measuring delta.
=> RTBC!
Comment #45
webchickGreat, thanks a ton folks! Another critical bug bites the dust! :D
Committed and pushed to 8.x.
Comment #46.0
(not verified) commentedx