Last Flutter2 for Web, I wrote a blog site that went live and we simply encapsulated the Web request. We are happy to run the project on Chrome, but do not see the data, through the developer tools, reported the following error:

This is a cross – domain error.

Our webpage address is http://localhost:62924, and then the page sent a request, and the interface domain name of the request is D6579fc5-C18b-443b-a2ef-01c2b6be51d5.bspapp.com, so their domain names are inconsistent, and there is cross-domain. It is protected by the same origin policy and therefore cannot interact with data.

What is cross-domain

If the protocol, domain name, and port are the same, it is considered to be in the same domain. If one of the three conditions is inconsistent, it is not considered to be in the same domain.

Even if it is our own domain name server, and the secondary domain name or the tertiary domain name is inconsistent, there will be cross-domain, such as: data interaction between http://img.loveli.site and http://blog.loveli.site, cross-domain.

All browsers now implement the same origin policy.

The same-origin policy was introduced in the browser by Netscape in 1995: when an Ajax request is sent, only data resources that are responded to by the same-domain server are received.

The purpose of the same origin policy is to ensure the security of user information and prevent malicious websites from stealing data.

Cross-domain solutions

How can data from two different domains interact smoothly? The most typical schemes in the early stage are:

  • JSONP
  • Sympatric agent

JSONP uses the SRC attribute of script tag to realize cross-domain data interaction, because when the browser parses THE HTML code, the browser gives the ability of HTTP request to tags with SRC attribute, and is not restricted by cross-domain, using SRC to send HTTP requests. The server directly returns a section of JS code function call, put the server data in the function argument, the front end of the response function written in advance ready to callback, receive data, to achieve cross-domain data interaction;

function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type"."text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};
Copy the code

Local proxy is to use Ajax to send requests to the background in the same domain, carrying the address and parameters of the real request. After receiving the request, the background directly forwards the request according to the address and parameters. Because the background can directly simulate the HTTP client to send requests, there is no cross-domain problem. The background receives the response data and then returns it to the front-end browser as is, so as to realize cross-domain data interaction.

JSONP and co-domain proxy, in essence, do not solve the problem of Ajax cross-domain, but bypass this problem and find a new way to achieve cross-domain data interaction, on the level of data interaction can be regarded as a temporary solution when the technology is not mature; However, JSONP and co-domain proxy have been used for many years, of course, cross-domain problems also exist for many years, finally someone can not look down, put forward the browser and server cross-domain communication security communication strategy ———— cross-domain resource sharing, referred to as CORS;

CORS (Online Solution)

CORS stands for Cross-Origin Resource Sharing. It is a W3C standard and a fundamental solution for cross-source AJAX requests.

CORS requires both browser and server support. Currently, all browsers support this feature. Therefore, the key to CORS communication is the server. As long as the server implements the CORS interface, cross-source communication is possible.

Because of the specificity of this article, we will not modify the server, so how the server implements CORS will not be explained. To learn more about CORS, read:

  • Cross-domain resource sharing (CORS
  • Cross-source Resource Sharing (CORS)

Request Forwarding (development scenario)

Since we don’t want to modify online servers, how do we solve cross-domain problems?

In fact, it is also simple, we locally implement proxy forwarding server, and configure CORS.

So let’s take you through it

Creating a CLI Project

How to create a CLI application?

  • Step 1 Install dart:

    $ brew tap dart-lang/dart
    $ brew install dart
    Copy the code
  • Creating a CLI application:

    $ dart create -t console-full cli
    Copy the code

    Use the dart create command to create a CLI project using the console-full template

    • bin/cli.dart, which contains a top-level main() function. This function is the entry point to your application
    • lib/cli.dartDart contains some functional function methods that will be imported into the bin/cli.dart file.
    • pubspec.yamlContains application metadata, including package information on which the application depends and required versions, just like the Flutter project
  • Run the application

    $ cd cli
    $ dart run
    Hello world: 42!
    Copy the code

Now that we have a CLI application, let’s implement the proxy server.

Proxy server

Since the web page is now accessed through localhost, we need to create a local server to forward the request.

We set up a proxy server with port 4500.

First we need to introduce shelf_Proxy in pubspec.yaml:

shelf_proxy: ^ 0.1.0 from + 7
Copy the code

Dart is then implemented in bin/cli.dart:

import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_proxy/shelf_proxy.dart';

void main(List<String> arguments) async {
  
  var reqHandle = proxyHandler("https://d6579fc5-c18b-443b-a2ef-01c2b6be51d5.bspapp.com");
  
  /// Bind local port 4500 and forward to a real server
  var server = await shelf_io.serve(reqHandle, 'localhost'.4500);
  
  // Set the request policy to allow all
  server.defaultResponseHeaders.add('Access-Control-Allow-Origin'.The '*');
  server.defaultResponseHeaders.add('Access-Control-Allow-Credentials'.true);
  print('Serving at http://${server.address.host}:${server.port}');
}
Copy the code

A simple proxy server was quickly implemented with shelf_Proxy, and it was running again

$ dart run
Serving at http://localhost:4500
Copy the code

Next, we need to modify the web-demo code in lib/config.dart:

/// The development environment
class ConfigDebug extends Config {
  @override
  String get baseUrl => "http://localhost:4500/http/";
}
Copy the code

In ConfigDebug, set baseUrl to the address of our local proxy server.

Dart ConfigDebug:

  // Configure the project environment
  if (kDebugMode) {
    locator.registerSingleton<Config>(ConfigDebug());
  } else {
    locator.registerSingleton<Config>(ConfigProduct());
  }
Copy the code

Rerun our project:

Data request successful!

conclusion

Cross-domain, which is very easy to encounter in development. The solution, by way of earlier solutions through JSONP and co-domain proxies (among others, of course), did not fundamentally solve the problem. It makes sense to implement CORS through the server.

We did not configure CORS for the online server. We directly created the local server and configured CORS to forward requests to the online server and play a role of transfer. Self-sufficiency!

Refer to the

  • Cross-domain and CORS that everyone should know about
  • Browser same origin policy and its circumvention method
  • Get started: command-line and server apps

To join Flutter wechat group, please follow the official account OldBirds