'XMLHttpRequest cannot load' Error on HTTP

2019-08-09 19:32发布

问题:

I've lately been trying to build a Dart client that communicates with my Dart docker server. If I run this url (localhost:8080/id/6192449487634432) on any browser I get back a JSON that I've set up, however, if a use

HttpRequest
    .getString ("http://localhost:8080/id/6192449487634432")
    .then (print);

on the Dart client, I get this weird error

XMLHttpRequest cannot load http://localhost:8080/id/6192449487634432. No 'Access-Control-Allow-Origin' 
header is present on the requested resource. Origin 'http://localhost:8081' is therefore not allowed access.

I've searched and some workarounds have been to build a PHP proxy (no thanks). I am new to web development in general and I definitely don't know what a proxy is or how to build one. Is there a clean solution I could use? I have a Redstone server and and AngularDart client.

Thanks a lot!

回答1:

This happens when your client app is served from a different server than your docker server. This is a browser issue, not specific to Dart. Luckily, the solution is easy.

Be sure to send CORS headers from your server, on every request. The easiest way to solve this is to add the following header:

Access-Control-Allow-Origin: *

I don't know the specifics of Redstone, but be sure to set the header key Access-Control-Allow-Origin and value * on GET, HEAD, and POST methods. Yes, you need to set this header on HEAD requests because sometimes the browser does a HEAD request to check if CORS is enabled.

Learn more about CORS at http://enable-cors.org/



回答2:

As mentioned above setting the Access-Control-Allow-Origin header allows HTTP requests from the browser to go to other URLs than the origin the client was loaded from. Another option is to serve the Dart client from the same server as you are accessing.

Depending on your environment and whether you are using Dartium or a JavaScript browser

If you are using Dart on App Engine Managed VMs we have built-in support for this, so that requests for the client files are proxied to pub serve during development and served from the output from pub build when deployed. See A Client-Server Example.

If you are running a plain Dart server right now there is no canned solution for switching between pub serve and pub build. You can run pub build and serve the files out of the web/build directory.

We are working on making the solution provided for Dart on App Engine Managed VMs more generally available.



回答3:

Particularly to redstone, you can solve the problem as follows. Add to your server-side code this snippet

// if not yet there
import 'package:redstone/server.dart' as app;

@app.Interceptor(r'/.*')
  interceptor() {
  app.chain.next(() {
    app.response = app.response.change(headers: {
      "Access-Control-Allow-Origin": "*"
    });
  });
}

you can read more on interceptors in the redstone wiki