drupal_goto() is evil: how to handle?

Events happening in the community are now at Drupal community events on www.drupal.org.
RobKoberg's picture

I am dealing with the password reset form and the one time login link and getting a CORS error since drupal is trying to redirect on the server. I can usually handle form redirects but drupal_goto is a problem. How do you handle it in a headless environment with an HTML client on a different server?

I wonder if this group should maintain a current drupal with an empty drupal_goto function?

Comments

Better, a drupal_goto that

RobKoberg's picture

Better, a drupal_goto that checks if arg(0)=='admin'

This seems to work for

RobKoberg's picture

This seems to work for me:

function drupal_goto($path = '', array $options = array(), $http_response_code = 302) {
  if (arg(0) != 'admin') {
    return;
  }
...

which sucks, but...

Ended up using (at least for

RobKoberg's picture

Ended up using (at least for now...):

function drupal_goto($path = '', array $options = array(), $http_response_code = 302) {
  if (arg(0) != 'admin') {
    $response = array();
    $response['path'] = $path;
    $response['options'] = $options;
    $response['httpResponseCode'] = $http_response_code;
    drupal_json_output($response);
    exit();
  }
...

That way the client can determine where to go more effectively. Just returning causes the one time log in link page act like it has been hit twice.

Use a better equipped client?

miro_dietiker's picture

If you use guzzle as a http client, you can tell it how to deal with redirects.
Althoguh it's common, a client follows redirects by default, this can usually be suppressed.

http header can contain relevant metadata beside the payload and indeed that's what the http headers are designed for. It's not good practice to push everything into JSON response, if http supports it natively.

I guess the redirect is somehow wrongly passed to the browser by your alternative head, due to http limitations. It seems more, your http client code is buggy than drupal_goto being the real problem.

Not sure I follow. I am not

RobKoberg's picture

Not sure I follow. I am not sure what you describe is possible from within a browser. The client is a modern browser (IE9 or better). There are two servers here, for example:

  • www.example.com - angular app hosted on an AWS S3 -- static files
  • cms.example.com - drupal CMS hosted on EC2s

A application/json request is made from www.example.com to cms.example.com. I get a CORS error when the Location returns with a url from cms.example.com.

I tried to do a mymodule_drupal_goto_alter and change the path to be a URL from the angular app server, but I still get a CORS error. See image:

Only local images are allowed.

If you are reading the above

RobKoberg's picture

If you are reading the above message in your email client, here is a link to the image I mention in the comment: http://imgur.com/yZpNOQu

more info on this. A solution

RobKoberg's picture

more info on this. A solution might be to set:

Header always set Access-Control-Allow-Origin "*"

But then you cannot use XHR.withCredentials=true. That is, you would not be able to use Drupal's cookie authentication.

Perhaps the CORS headers could be managed in the PHP code rather than the .htaccess and set withCredentials to true only when authenticated. For now at least I will stick with the core hack and document well for my project.

This doesn't seem to work

miro_dietiker's picture

From the angular docs:
https://docs.angularjs.org/api/ng/service/$http

Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning that the error callback will not be called for such responses.

See also related discussions:
https://groups.google.com/forum/#!topic/angular/GKkdipdMbdo

So you are right, for this kind of a limited client, drupal_goto doesn't work.
In Drupal 8, a RedirectResponse is used to replace drupal_goto.

Even though a web browser is

RobKoberg's picture

Even though a web browser is a "limited client," it will probably be used as a client a bit more than guzzle. This will be a problem for a t('headless') drupal 8 too. there are ways to workaround it, but it is not pretty.

How would someone handle this in D8? I am not too familiar with the code and PHP OOP in general, but I don't see it (or Response) implementing an interface so where you can set the implementation you want to use.

Perhaps there could be some way to configure redirect behavior and not force it. Or perhaps it could check for a request param to determine whether the client or server should handle redirects

No need to hack the core...

RobKoberg's picture

Just had a duh moment. I can just return JSON with the redirect path in the alter and exit() there. No need to hack the core.

Headless Drupal

Group organizers

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: