Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing response value on ajax result. #2007

Open
maierson opened this issue Oct 5, 2016 · 16 comments
Open

Missing response value on ajax result. #2007

maierson opened this issue Oct 5, 2016 · 16 comments

Comments

@maierson
Copy link

maierson commented Oct 5, 2016

Hi guys,

I'm trying to do a simple ajax call and get a response but i get an answer with null response value.

RxJS version:
"rxjs": "^5.0.0-beta.12"

Code to reproduce:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/dom/ajax';

 Observable.ajax({
        url: window.location.origin + "/api/book/load",
        method: "POST",
        responseType: "json",
        body: {
            key: "userKey",
            sessionId: "oisudofiu"
        },
        headers: {
            "Accept": "application/json, text/plain, */*",
            "cache-control": "no-cache"
        }
    }).subscribe(
        xhr => console.log("LOADED ", JSON.stringify(xhr, null, 2)),
        error => console.log("ERROR ", JSON.stringify(error, null, 2)),
        () => console.log("COMPLETE"))

Expected behavior:
Get a response with result information

Actual behavior:
Missing response information on Ajax response

{
  "originalEvent": {
    "isTrusted": true
  },
  "xhr": {},
  "request": {
    "async": true,
    "crossDomain": false,
    "withCredentials": false,
    "headers": {
      "Accept": "application/json, text/plain, */*",
      "cache-control": "no-cache",
      "X-Requested-With": "XMLHttpRequest",
      "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    "method": "POST",
    "responseType": "json",
    "timeout": 0,
    "url": "http://localhost:8888/api/book/load",
    "body": "key=userKey&sessionId=oisudofiu"
  },
  "status": 200,
  "responseType": "json",
  "response": null
}

Additional information:
If i make the same call with axios against the same (jersey) REST endpoint I get back the correct data. The endpoint is configured to ignore params and respond with "Result of book loaded" string. Here is the axios response:

{
  "data": "\"Result of book loaded\"",
  "status": 200,
  "statusText": "OK",
  "headers": {
    "date": "Wed, 05 Oct 2016 16:27:40 GMT",
    "cache-control": "no-cache",
    "expires": "Mon, 01 Jan 1990 00:00:00 GMT",
    "server": "Development/1.0",
    "content-length": "27",
    "content-type": "application/json;charset=utf-8"
  },
  "config": {
    "transformRequest": {},
    "headers": {
      "Accept": "application/json, text/plain, */*",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    "timeout": 0,
    "xsrfCookieName": "XSRF-TOKEN",
    "xsrfHeaderName": "X-XSRF-TOKEN",
    "maxContentLength": -1,
    "method": "post",
    "baseURL": "http://localhost:8888/api",
    "url": "http://localhost:8888/api/book/load",
    "data": "key=user&sessionId=password"
  },
  "request": {}
}

Thanks a lot for any help.

(EDIT by @Blesh to add code color formatting)

@benlesh
Copy link
Member

benlesh commented Oct 5, 2016

Interesting, it makes me wonder if it has something to do with it being a POST or not.

@benlesh
Copy link
Member

benlesh commented Oct 5, 2016

@maierson is this, by chance, something that is open source that we can look at? Do you have a minimum replication case we can see? Or perhaps could we get a copy of the raw HTTP response so we can try to spoof it locally and replicate the issue?

@maierson
Copy link
Author

maierson commented Oct 5, 2016

Hi Ben,

Thanks for looking into this. The project is not open source but I'm at the beginning of porting a large project to react and want to get all my (ahem) ducks in a row before I do all the porting. I'll put a boilerplate together as soon as I get a chance.

Some more details. I'm using typescript 2.0, redux-observable. I'm calling a resteasy java endpoint. The error also misses the error message. If I wrap a promise with Observer.fromPromise(promise) then I am able to get the response and error messages but that kind of defeats the point of being able to cancel out of it.

I've also tried with Rx v4 + rx-dom Rx.DOM.ajax() and there I get the response message but still have no access to the error message.

I'll look into getting you the raw HTTP response - just have to restore the setup.

@maierson
Copy link
Author

maierson commented Oct 6, 2016

@Blesh - i did some more digging and figured out the reason for result missing. It's because the server actually sends back a text response and the post call was configured to get a json call. Once i change the ajax call configuration to responseType: "text" I am able to get the result.

The axios promise is configured with "Accept": "application/json, text/plain, */*" header so it's why there is no issue there.

This probably should raise an error instead of returning a response with empty result.

The error not providing a message issue still remains. Here is the HTTP call info (see the Response containing the error message returned from the server):

Response Headers:
    HTTP/1.1 400 Bad Request
    Server: Development/1.0
    Date: Thu, 06 Oct 2016 00:06:10 GMT
    Content-Length: 94
    Content-Type: text/plain
    Cache-Control: no-cache
    Expires: Mon, 01 Jan 1990 00:00:00 GMT
Request Headers:
    POST /.............. HTTP/1.1
    Host: localhost:8888
    Connection: keep-alive
    Content-Length: 23
    Origin: http://localhost:8888
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Accept: */*
    Referer: http://localhost:8888/story/aghrb2xvcmh1YnIlCxIHQXBwVXNlchiAgICAgICACgwLEgRCb29rGICAgICAyP4LDA
    Accept-Encoding: gzip, deflate
    Accept-Language: en-US,en;q=0.8
    Cookie: localhost=2290043D016369E05F850832B69C7FF471016480D081D8926A3A7CA80E90C107
Form data:
    key=test&sessionId=null
Response:
    The id of the item you are trying to request is invalid on our system. Please try again.

And this is the error payload from the observer's catch method

{
  "message": "ajax error 400",
  "xhr": {},
  "request": {
    "async": true,
    "crossDomain": false,
    "withCredentials": false,
    "headers": {
      "X-Requested-With": "XMLHttpRequest",
      "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
    },
    "method": "POST",
    "responseType": "text",
    "timeout": 0,
    "url": "http://localhost:8888/....................",
    "body": "key=test&sessionId=null"
  },
  "status": 400
}

@benlesh
Copy link
Member

benlesh commented Oct 8, 2016

I see. This seems like something we can fix. I'll give it some thought.

@jjasonclark
Copy link

I have run into the same issue. The code works as expected under Chrome. But under Firefox the Ajax response is blank. Changing the responseType to text does show me the response. Seems it only fails on the JSON type.

Hope the extra information helps.

@adregan
Copy link

adregan commented Nov 30, 2016

Whew, am I glad for your comment @jjasonclark—at work I use Firefox Dev, but at home, I use the regular FF (version 50), and I thought I was going crazy ("this thing was just working at the office!").

I can confirm that I am getting an null for the response field, but only in Firefox 50. I haven't experienced it at all on the Dev edition or in chrome.

@cescoferraro
Copy link

cescoferraro commented Apr 10, 2018

I am working on 3rd party API that talks json, but sends simple string as errors, which should be fine hence a string is a valid json format. But its not because the error object always return null if the response is a string. I assume responseType is json by default.

using "rxjs": "^5.5.2"

@muthukumarse
Copy link

Guys, any workaround for this issue, I got this issue too

when server trying to redirect by sending .....
xhr.response - null
xhr.reponseType - json instead of text/html

so there is no way to redirect to login based on the response.

@aaronjensen
Copy link

aaronjensen commented Oct 19, 2018

Found a benchmark comparing xhr + JSON.parse vs responseType = 'json'. AFAICT, there's not much reason to use responseType = 'json'.

useFetch x 4.86 ops/sec ±1.39% (28 runs sampled)
useXhr x 9.83 ops/sec ±1.42% (49 runs sampled)
useXhrWithResponseTypeJson x 5.24 ops/sec ±1.82% (30 runs sampled)

(I reran this benchmark on Chrome 69)

The workaround for us would be to set responseType: 'text' and parse the json ourselves:

ajax({
  url: 'https://api.trello.com/1/batch/', 
  responseType: 'text',
  }).pipe(map(r => ({...r, response: JSON.parse(r.response), responseType: 'json'})))
  .subscribe(console.log, e => {
    console.log('fail', e.response)
  }, console.log)

Example here:
https://stackblitz.com/edit/typescript-4y5sch?file=index.ts

Maybe rxjs make the IE fallback code the primary code and remove the responseType setting?

@muthukumarse
Copy link

@aaronjensen

Exactly the same I did to solve my problem.

We have to be careful if requestType is Json or text we can parse. Otherwise i.e. blob we just move on

@rudolfschmidt
Copy link

Hey guys, a guly workaround is not a solution. ajax.get or ajax.post need to have a response value if ther is any given by the server. I face the same issue here using ajax.post to send params and receive a string. its just null. Its a no go bug. Please fix it as soon as possible or remove the method completely if you cannot make it work to not confuse further developers.

@taylor-cedar
Copy link

We have unfortunately used a forked version of RXJS because of this bug. Has there been any pushback to submit a PR to fix?

@kochmaxence
Copy link

What's the status on this? It's opened since 2016 and seems like it's still an issue.

@iamleson98
Copy link

hey guys!
What an interesting problem!
This issue was opened since 2016, back in the day, i did'nt know anything about coding.
Today i know it and wanna share a little bit.

1, loading chartjs from a CDN using rxjs/ajax:

ajax("https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js")
    .subscribe(
        data => {
            console.log(data.response);
        },
        error => console.error(error)
);
/*
RESULT:  null
*/

I tended to give up and made friend with axios
But googling let me found this issue
2, loading with some config configured:

ajax({
  url: "https://cdn.jsdelivr.net/npm/chart.js@2.9.3/dist/Chart.min.js",
  responseType: "blob"
}).subscribe(
  data => {
    const script = document.createElement("script");
    script.src = URL.createObjectURL(data.response);
    document.body.appendChild(script);
    script.onload = function() {
      console.log(typeof Chart);
    };
  },
  error => console.error(error)
);

/*
   RESULT: 'function' meaning chartjs was fetched successfully. Lol
*/

Thank you for your help!

@laosandegudai
Copy link

So it will continue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests