Core Restful requests not working when sent with subrequests

Created on 7 February 2019, almost 6 years ago
Updated 8 December 2023, about 1 year ago

Hello guys.

I've been playing a bit with this module, and I got it working easy/nicely with jsonapi. However, it is not the case with core RESTFul module. For example, this works perfectly (without using subrequests):

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
  $.get('http://example.com/rest/session/token?_format=json').done(function(data) {
    var csrfToken = data;
    var SIMPLE_OAUTH_TOKEN = 'A token returned by simple_oauth requesting /oauth/token. Or any other authentication method.';
    
    var nodeData = {
      '_links': {
        'type': {
          'href': 'http://example.com/rest/type/node/content_type_b'
        }
      },
      'type': {
        'target_id': 'content_type_b'
      },
      'title': {
        'value': 'Example of Node type B'
      }
      '_embedded': {
        'http://example.com/rest/relation/node/content_type_b/field_content_type_a': [
          {
            'uuid': [
              {
                'value': '1b0aeef5-80a8-4e09-b187-d41cd639f5dd'
              }
            ]
          }
        ]
      }
    };  
    $.ajax({
      'url': 'http://example.com/node?_format=hal_json',
      'method': 'POST',
      'data': JSON.stringify(nodeData),
      'dataType': 'json',
      'headers': {
        'Content-Type': 'application/hal+json',
        'X-CSRF-Token': csrfToken,
        'Authorization': 'Bearer ' + SIMPLE_OAUTH_TOKEN,
      },
      'success': function (node) {
        console.log('Node response:');
        console.dir(node);
      },
      'error': function (XMLHttpRequest, textStatus, errorThrown) {
        console.log(errorThrown);     
      }
    });
       
  });
</script>

But trying to do the same by using subrequests, it doesn't work:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
  $.get('http://example.com/rest/session/token?_format=json').done(function(data) {
    var csrfToken = data;
    var SIMPLE_OAUTH_TOKEN = 'A token generated by simple_oauth requesting /oauth/token. Or any other authentication method.';

    var nodeData = {
      '_links': {
        'type': {
          'href': 'http://example.com/rest/type/node/content_type_b'
        }
      },
      'type': {
        'target_id': 'content_type_b'
      },
      'title': {
        'value': 'Example of Node type B'
      }
      '_embedded': {
        'http://example.com/rest/relation/node/content_type_b/field_content_type_a': [
          {
            'uuid': [
              {
                'value': '1b0aeef5-80a8-4e09-b187-d41cd639f5dd'
              }
            ]
          }
        ]
      }
    };

    var subrequestsPayloads = [
      {
        'action': 'create',
        'requestId': 'restful_node_save',
        'body': JSON.stringify(nodeData),
        'uri': 'http://example.com/node?_format=hal_json', // As shown into the RESTFul resource, using module "restui".
        'headers': {
          'Content-Type': 'application/hal+json',
          'X-CSRF-Token': csrfToken,
          'Authorization': 'Bearer ' + SIMPLE_OAUTH_TOKEN,
        }
      }
    ];
              
    $.ajax({
      'url': 'http://example.com/subrequests?_format=json',
      'method': 'POST',
      'data': JSON.stringify(subrequestsPayloads),
      'dataType': 'json',
      'headers': {
        'Content-Type': 'application/json',
        'X-CSRF-Token': csrfToken,
        'Authorization': 'Bearer ' + SIMPLE_OAUTH_TOKEN,
      },
      'success': function (data) {
        console.log('Node response:');
        console.dir(data);
      },
      'error': function (XMLHttpRequest, textStatus, errorThrown) {
        console.dir(errorThrown);     
      }
    });
       
  });
</script>

In last case (subrequests), it returns HTML (also, keep note on the "text/html" header). Of course, the new node is not being created. Also, no errors are shown in dblog:

I'ld like any advice, if I'm missing something.

NOTES: I made this test with 2 content types: This one tries to create a node of type "content_type_b" referencing another one of type "content_type_a", into the field "field_content_type_a" (single value).

πŸ› Bug report
Status

Needs work

Version

3.0

Component

Code

Created by

πŸ‡¨πŸ‡΄Colombia waspper

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • πŸ‡ΊπŸ‡ΈUnited States dillix

    We need reroll for 3.x-dev.

  • πŸ‡ΊπŸ‡ΈUnited States mglaman WI, USA

    This needs tests.

    The module does not take into account query parameters, such as "?_format=json" which, in my case, makes authentication fail. Patch at #3 fixes the issue for me.

    But it should, but I think this is where it breaks down.

    $query = parse_url($data->uri, PHP_URL_QUERY) ?: [];

    However, the query can be lost if it is a non-GET request:

        $request = Request::create(
          $path,
          static::getMethodFromAction($data->action),
          empty($data->body) ? $query : $data->body,
          $master_request->cookies ? $master_request->cookies->all() : [],
          $master_request->files ? $master_request->files->all() : [],
          $master_request->server ? $master_request->server->all() : [],
          empty($data->body) ? '' : Json::encode($data->body)
        );
    

    The path is passed without query parameters. And the query parameters are lost if there is a request body.

Production build 0.71.5 2024