7

I make a POST request and the request just sits, pending until it eventually fails. I've monitored the nginx logs and the node server logs and the request doesn't even register. This works for anyone else that I've had test it except one other colleague. If I use the edge browser or a different computer it works fine.

I have attempted to make POST requests to other (custom) servers and it hangs on options there as well. I have also made the POST request with jQuery and it fails the same way.

It's maybe worth noting that I am using the withCredentials flag.

Headers:

Provisional headers are shown
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:GET
Origin:http://localhost:8080
Referer:http://localhost:8080/<path>
User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36

The request:

  public login(user) {
    const endpoint = `http://<url>`;

    let headers = new Headers();
    headers.append('Content-type', 'application/json');

    return this.http
      .post(endpoint, JSON.stringify(user), {
        headers: headers,
      });

  }

I subscribe to the call in my component:

this._accountService.login(this.user)
        .subscribe(res => {
            console.log("logged in!");
            if (res.json().status === "success") {
                window.location.href = `/home/${this.org}/${this.product}`;
            }
            else {
                // What other options are there?
                console.log("Do something else maybe?");
            }
        },
        err => {
            this.invalidLogin = true;
            console.log("Ye shall not pass!");
        });

Successful user's headers

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:<url>
Origin:<url>
Referer:<url>
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.33 Safari/537.36

From chrome://net-internals/#events

t=61869793 [st=    0] +REQUEST_ALIVE  [dt=60162]
                       --> has_upload = false
                       --> is_pending = true
                       --> load_flags = 34624 (DO_NOT_SAVE_COOKIES | DO_NOT_SEND_AUTH_DATA | DO_NOT_SEND_COOKIES | MAYBE_USER_GESTURE | VERIFY_EV_CERT)
                       --> load_state = 14 (WAITING_FOR_RESPONSE)
                       --> method = "OPTIONS"
                       --> net_error = -1 (ERR_IO_PENDING)
                       --> status = "IO_PENDING"
                       --> url = "<url>"
t=61929955 [st=60162]   -HTTP_STREAM_PARSER_READ_HEADERS
                         --> net_error = -324 (ERR_EMPTY_RESPONSE)
t=61929955 [st=60162]   -HTTP_TRANSACTION_READ_HEADERS
                         --> net_error = -324 (ERR_EMPTY_RESPONSE)
t=61929955 [st=60162]   -URL_REQUEST_START_JOB
                         --> net_error = -324 (ERR_EMPTY_RESPONSE)
t=61929955 [st=60162]    URL_REQUEST_DELEGATE  [dt=0]
t=61929955 [st=60162] -REQUEST_ALIVE
                       --> net_error = -324 (ERR_EMPTY_RESPONSE)

I'm really guessing this is related to something that is cached in my browser(s) but I really cannot find what. I've cleared all cookies and anything that could be stored. Where else can I check to clear things? This is clearly something local to my computer/browser (and one other unfortunate person).

Aarmora
  • 1,143
  • 1
  • 13
  • 26
  • http://stackoverflow.com/questions/10143093/origin-is-not-allowed-by-access-control-allow-origin – Günter Zöchbauer Jun 14 '16 at 09:04
  • This is not related to Angular. The server you're accessing needs to support CORS requests. `OPTIONS` is a preflight request made by the browser autonomically. If it doesn't returned the expected `Access-Control-Allow-...` headers, it doesn't even try to send the actual request. – Günter Zöchbauer Jun 14 '16 at 09:06
  • @GünterZöchbauer I have CORS enabled. The request works for other computers and browsers. – Aarmora Jun 14 '16 at 09:13
  • I can't tell. It depends on how the headers look exactly that the server returns. The header origins might match other computers origin but not where you load your application from. Angular is not involved in any way with this. This can only be fixed on the server. – Günter Zöchbauer Jun 14 '16 at 09:16
  • @GünterZöchbauer I have this deployed to a webserver and that is where the others are making their requets to. If I make the request to their it fails the same way. I have access to the server if that would help. That is where I am monitoring nginx and the node logs. – Aarmora Jun 14 '16 at 09:21
  • 1
    You would need to post the headers the server receives and the header it responds with the OPTIONS request for anybody to be able to help. It would be helpful to see the sent headers from requests made from computers where its working as well for compairson. – Günter Zöchbauer Jun 14 '16 at 09:23
  • Are the others using the same browser version? – Günter Zöchbauer Jun 14 '16 at 09:23
  • @GünterZöchbauer Everywhere I have monitored won't even register my request. Besides the nginx access.log and error.log, where else could I look to check these headers? I'll post another, successful user's headers now. – Aarmora Jun 14 '16 at 09:34
  • You can make the request to a custom server and print the headers. You can also make the `OPTIONS` request to the server from a console application and print what it returns. CORS is only relevant for the browser and won't have any effect for programs outside the browser. You could even use `curl` http://prefetch.net/blog/index.php/2005/10/18/printing-http-headers-with-curl/, http://stackoverflow.com/questions/14481850/how-to-send-a-http-options-request-from-the-command-line – Günter Zöchbauer Jun 14 '16 at 09:37
  • You might get better support if you fix the tags. Look for a CORS tag instead of angular2. – Günter Zöchbauer Jun 14 '16 at 14:02
  • 1
    @GünterZöchbauer Good call, I've updated it accordingly. – Aarmora Jun 14 '16 at 14:16
  • have you tried using wireshark/fiddler or similar to snoop the packets going out from your PC or into the server? – Brad Zacher Jun 23 '16 at 23:58
  • @BradZacher I just installed but I don't really know what I'm looking for. I see the ip of the place I'm hitting but I don't know how to differentiate requests. – Aarmora Jun 24 '16 at 13:32
  • You should be able to see the content of each message that gets sent/received. You should be able to snoop the plaintext http request in one of the packets (as long as you're not on https,else it gets harder...) – Brad Zacher Jun 24 '16 at 14:16
  • What do the chrome dev tools say? – Legends Jun 30 '16 at 16:10
  • @Legends The request never completes and returns `OPTIONS http:// net::ERR_EMPTY_RESPONSE` – Aarmora Jun 30 '16 at 16:31
  • You said, based on the logs, it's never hitting the node server? A few things I would check at this point - try making a non-cors request. Try disabling your antivirus (if any). Check your firewall (all though I don't know if that would apply to loopback). I say this because you said it works on other computers. I would suggest fiddler because it can track localhost calls. What is the error that shows up in chrome in the network tab? – Zach Jun 30 '16 at 21:16
  • I also wonder if your server is setup to respond to [preflight OPTIONS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests) requests made by these browsers in CORS calls. Could you show your node.js/CORS setup? – Zach Jun 30 '16 at 21:20
  • Thats what I'm thinking as well Zach in my answer. The server appears to be connecting, but its not sending a response. – Ian Belcher Jun 30 '16 at 21:20
  • @zach I've tried wireshark but I couldn't really make sense of it. Is Fiddler pretty easy to sort through? – Aarmora Jul 01 '16 at 13:02
  • @zach Simple requests (get) work without any problem. It's only when doing non-simple requests (post, delete). – Aarmora Jul 01 '16 at 13:03

4 Answers4

2

Please try to subscribe() to the observable.

return this.http
  .post(endpoint, JSON.stringify(user), {
    headers: headers,
  }).subscribe(() => console.log("POST done!"));
zpul
  • 1,535
  • 1
  • 14
  • 19
  • Sorry, that is just my service, which is called by my component. My component is subscribed. I should clarify that. – Aarmora Jun 14 '16 at 10:09
  • @Aarmora did you tried to step into the post call to see what is the last step it executes? – zpul Jun 14 '16 at 10:11
  • It makes the full call but the request just hangs at pending. No callback comes back as the connection is refused. – Aarmora Jun 14 '16 at 10:22
  • @Aarmora try looking at chrome://net-internals (Events) to see if you see the reason why it is pending. – zpul Jun 14 '16 at 11:43
  • This is really interesting! I added the return above. Does it give any ideas to you? – Aarmora Jun 14 '16 at 13:30
1

Have you tried setting the 'Cache-Control' in your headers? I think in jQuery you can simply set

$.ajax({    
  cache: false 
});

or adding a header with a regular ajax request

request.setRequestHeader("Cache-Control", "no-cache"); 
BrianDiesel
  • 168
  • 5
  • I had not heard of this. I did just try it and didn't get a different result. Good suggestion, though. – Aarmora Jun 30 '16 at 12:16
1

There are issues with CORS and using localhost as the domain (which you have listed in the ORIGIN headers). Typically CORS / OPTIONS requests don't work properly when localhost is involved for certain security reasons, but hanging isn't normally what happens so this might not be the correct answer but its worth a shot!

Try adding a new host to your local machine and removing localhost from the equation. Just throwing this idea out there and hope that it might help you out!

As per comment below

Your server appears to allow the connection, but it does not appear to send a response. Are you able to post the headers from a successful OPTIONS request to prove that the server is actually able to handle these requests.

Ian Belcher
  • 5,583
  • 2
  • 34
  • 43
  • Unfortunately this same thing happens when calling from localhost or from the webserver with a domain and DNS set. Thanks, though. – Aarmora Jun 30 '16 at 12:07
  • Another thing is that your server is not returning a response due to some logic issue either via cookie / credential or for some other reason. Are you able to add the POST and the OPTION endpoints of your server side code that handles these requests? – Ian Belcher Jun 30 '16 at 13:16
  • Yes, the server works fine for anyone else or for me on Edge. It only does not work on Chrome and firefox. – Aarmora Jun 30 '16 at 14:12
  • Your logs appear as though you are making a connection but your server is not returning a response which would suggest that there is an issue server side. Also, just checking that your colleges are also setting up a xdomain situation to actually create an OPTIONS preflight as the return header you've included is for the POST response, not the OPTIONS response. – Ian Belcher Jun 30 '16 at 19:53
  • i.e. Is there proof that the server actually does return OPTIONS 200||204 OK headers. – Ian Belcher Jun 30 '16 at 20:03
  • A successful response's headers are already on the question, unless I misunderstand what you are asking. – Aarmora Jul 01 '16 at 13:01
  • Those are the successful POST _request_ headers. The OPTIONS _response_ headers will contain `Access-Control-Allow-Methods` and this call fires before the POST request when you are doing a request from a different domain and tells the browser what permissions it has. My theory is that your colleges are not getting the issue because they are not doing xdomain calls and are hence not seeing the issue that your server is not setup for OPTIONS requests. What are you using on your server to respond to these OPTIONS requests? – Ian Belcher Jul 01 '16 at 19:31
  • I will try to get the OPTIONS response headers. They are making a xdomain call, as they are making the call from the same place. The webserver gives me the error, but not the them. The calls are identical. It calls from a domain to an api on a separate subdomain. – Aarmora Jul 01 '16 at 19:45
1

Why don't you just prevent getting into OPTIONS request loop . It really drives you crazy at times . Other browsers do not trigger OPTIONS request but chrome and firefox does to ensure CORS . I have successfully used this library named as xdomain from github , and it really works !! Their github introduction page introduce xdomain as a CORS alternative . And most importantly i used it in JQuery , but it also does support Angular's http service . Have a look at it . It may help you for good :) . Here's the link to library Xdomain CORS Alternative

Saurabh Chaturvedi
  • 2,028
  • 2
  • 18
  • 39