Issue #2339491 by corbacho, dawehner, larowlan, effulgentsia, webflo: Ajax requests on forms with files fail on IE 9
parent
4936e3d6af
commit
9c0bfb2d3b
|
@ -765,6 +765,7 @@ services:
|
|||
arguments: ['@element_info']
|
||||
tags:
|
||||
- { name: render.main_content_renderer, format: drupal_ajax }
|
||||
- { name: render.main_content_renderer, format: iframeupload }
|
||||
main_content_renderer.dialog:
|
||||
class: Drupal\Core\Render\MainContent\DialogRenderer
|
||||
arguments: ['@title_resolver']
|
||||
|
|
|
@ -115,6 +115,42 @@ class AjaxResponse extends JsonResponse {
|
|||
if ($this->data == '{}') {
|
||||
$this->setData($this->ajaxRender($request));
|
||||
}
|
||||
|
||||
// IE 9 does not support XHR 2 (http://caniuse.com/#feat=xhr2), so
|
||||
// for that browser, jquery.form submits requests containing a file upload
|
||||
// via an IFRAME rather than via XHR. Since the response is being sent to
|
||||
// an IFRAME, it must be formatted as HTML. Specifically:
|
||||
// - It must use the text/html content type or else the browser will
|
||||
// present a download prompt. Note: This applies to both file uploads
|
||||
// as well as any ajax request in a form with a file upload form.
|
||||
// - It must place the JSON data into a textarea to prevent browser
|
||||
// extensions such as Linkification and Skype's Browser Highlighter
|
||||
// from applying HTML transformations such as URL or phone number to
|
||||
// link conversions on the data values.
|
||||
//
|
||||
// Since this affects the format of the output, it could be argued that
|
||||
// this should be implemented as a separate Accept MIME type. However,
|
||||
// that would require separate variants for each type of AJAX request
|
||||
// (e.g., drupal-ajax, drupal-dialog, drupal-modal), so for expediency,
|
||||
// this browser workaround is implemented via a GET or POST parameter.
|
||||
//
|
||||
// @see http://malsup.com/jquery/form/#file-upload
|
||||
// @see https://drupal.org/node/1009382
|
||||
// @see https://drupal.org/node/2339491
|
||||
// @see Drupal.ajax.prototype.beforeSend()
|
||||
$accept = $request->headers->get('accept');
|
||||
|
||||
if (strpos($accept, 'text/html') !== FALSE) {
|
||||
$this->headers->set('Content-Type', 'text/html; charset=utf-8');
|
||||
|
||||
// Browser IFRAMEs expect HTML. Browser extensions, such as Linkification
|
||||
// and Skype's Browser Highlighter, convert URLs, phone numbers, etc. into
|
||||
// links. This corrupts the JSON response. Protect the integrity of the
|
||||
// JSON data by making it the value of a textarea.
|
||||
// @see http://malsup.com/jquery/form/#file-upload
|
||||
// @see http://drupal.org/node/1009382
|
||||
$this->setContent('<textarea>' . $this->data . '</textarea>');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -91,20 +91,6 @@ class ViewSubscriber implements EventSubscriberInterface {
|
|||
return $response;
|
||||
}
|
||||
|
||||
public function onIframeUpload(GetResponseForControllerResultEvent $event) {
|
||||
$response = $event->getResponse();
|
||||
|
||||
// Browser IFRAMEs expect HTML. Browser extensions, such as Linkification
|
||||
// and Skype's Browser Highlighter, convert URLs, phone numbers, etc. into
|
||||
// links. This corrupts the JSON response. Protect the integrity of the
|
||||
// JSON data by making it the value of a textarea.
|
||||
// @see http://malsup.com/jquery/form/#file-upload
|
||||
// @see http://drupal.org/node/1009382
|
||||
$html = '<textarea>' . $response->getContent() . '</textarea>';
|
||||
|
||||
return new Response($html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the methods in this class that should be listeners.
|
||||
*
|
||||
|
|
|
@ -23,9 +23,11 @@ class MainContentRenderersPass implements CompilerPassInterface {
|
|||
*/
|
||||
public function process(ContainerBuilder $container) {
|
||||
$main_content_renderers = [];
|
||||
foreach ($container->findTaggedServiceIds('render.main_content_renderer') as $id => $attributes) {
|
||||
$format = $attributes[0]['format'];
|
||||
$main_content_renderers[$format] = $id;
|
||||
foreach ($container->findTaggedServiceIds('render.main_content_renderer') as $id => $attributes_list) {
|
||||
foreach ($attributes_list as $attributes) {
|
||||
$format = $attributes['format'];
|
||||
$main_content_renderers[$format] = $id;
|
||||
}
|
||||
}
|
||||
$container->setParameter('main_content_renderers', $main_content_renderers);
|
||||
}
|
||||
|
|
|
@ -92,8 +92,7 @@ class ReadTest extends RESTTestBase {
|
|||
// and hence when there is no matching REST route, the non-REST route is
|
||||
// used, but it can't render into application/hal+json, so it returns a 406.
|
||||
$this->assertResponse('406', 'HTTP response code is 406 when the resource does not define formats, because it falls back to the canonical, non-REST route.');
|
||||
$expected_message = '{"message":"Not Acceptable.","supported_mime_types":["text\\/html","application\\/vnd.drupal-ajax","application\\/vnd.drupal-dialog","application\\/vnd.drupal-modal"]}';
|
||||
$this->assertIdentical($expected_message, $response);
|
||||
$this->assertTrue(strpos($response, '{"message":"Not Acceptable.","supported_mime_types":') !== FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
namespace Drupal\Tests\Core\Ajax;
|
||||
|
||||
use Drupal\Core\Ajax\AjaxResponse;
|
||||
use Drupal\Core\Render\Element\Ajax;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
/**
|
||||
* @coversDefaultClass \Drupal\Core\Ajax\AjaxResponse
|
||||
|
@ -68,5 +70,21 @@ class AjaxResponseTest extends UnitTestCase {
|
|||
$this->assertSame($commands[0], array('command' => 'three', 'class' => 'test-class'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the support for IE specific headers in file uploads.
|
||||
*
|
||||
* @cover ::prepareResponse
|
||||
*/
|
||||
public function testPrepareResponseForIeFormRequestsWithFileUpload() {
|
||||
$request = Request::create('/example', 'POST');
|
||||
$request->headers->set('Accept', 'text/html');
|
||||
$response = new AjaxResponse([]);
|
||||
$response->headers->set('Content-Type', 'application/json; charset=utf-8');
|
||||
|
||||
$response->prepare($request);
|
||||
$this->assertEquals('text/html; charset=utf-8', $response->headers->get('Content-Type'));
|
||||
$this->assertEquals($response->getContent(), '<textarea>[]</textarea>');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue