Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 否';访问控制允许原点';请求的资源上存在标头—;尝试从REST API获取数据时_Javascript_Cors_Fetch Api_Preflight - Fatal编程技术网

Javascript 否';访问控制允许原点';请求的资源上存在标头—;尝试从REST API获取数据时

Javascript 否';访问控制允许原点';请求的资源上存在标头—;尝试从REST API获取数据时,javascript,cors,fetch-api,preflight,Javascript,Cors,Fetch Api,Preflight,我正在尝试从HP Alm的REST API获取一些数据。它与一个小的curl脚本配合得很好——我得到了我的数据 现在,使用JavaScript、fetch和ES6(或多或少)这样做似乎是一个更大的问题。我一直收到以下错误消息: 无法加载获取API。对飞行前请求的响应不正确 通过访问控制检查:未显示“访问控制允许原点”标题 在请求的资源上显示。来源“”是 因此不允许访问。响应的HTTP状态代码为501。 如果不透明响应满足您的需要,请将请求的模式设置为 “无cors”以获取禁用cors的资源 我理

我正在尝试从HP Alm的REST API获取一些数据。它与一个小的curl脚本配合得很好——我得到了我的数据

现在,使用JavaScript、fetch和ES6(或多或少)这样做似乎是一个更大的问题。我一直收到以下错误消息:

无法加载获取API。对飞行前请求的响应不正确 通过访问控制检查:未显示“访问控制允许原点”标题 在请求的资源上显示。来源“”是 因此不允许访问。响应的HTTP状态代码为501。 如果不透明响应满足您的需要,请将请求的模式设置为 “无cors”以获取禁用cors的资源

我理解这是因为我试图从本地主机中获取数据,解决方案应该使用CORS。现在我想我真的做到了,但不知怎么的,它要么忽略了我在标题中写的内容,要么问题出在其他地方

那么,是否存在实施问题?我做错了吗?很遗憾,我无法检查服务器日志。我真的有点困在这里了

function performSignIn() {

  let headers = new Headers();

  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');

  headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
  headers.append('Access-Control-Allow-Credentials', 'true');

  headers.append('GET', 'POST', 'OPTIONS');

  headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));

  fetch(sign_in, {
      //mode: 'no-cors',
      credentials: 'include',
      method: 'POST',
      headers: headers
    })
    .then(response => response.json())
    .then(json => console.log(json))
    .catch(error => console.log('Authorization failed : ' + error.message));
}
我用的是铬。我也尝试过使用Chrome CORS插件,但随后我收到另一条错误消息:

响应中“Access Control Allow Origin”标头的值 当请求的凭据模式为时,不能为通配符“*” “包括”。因此,不允许使用源“” 通道由发起的请求的凭据模式 XMLHttpRequest由withCredentials属性控制


这个答案涵盖了很多方面,因此分为三个部分:

  • 如何使用CORS代理解决“无访问控制允许源站标头”问题
  • 如何避免CORS飞行前
  • 如何解决“访问控制允许源标题不能是通配符”的问题

如何使用CORS代理来避免“无访问控制允许源站标头”问题

如果您不控制前端代码向其发送请求的服务器,而该服务器的响应问题只是缺少必要的
Access control Allow Origin
头,那么您仍然可以通过CORS代理发出请求来完成工作

您可以使用中的代码轻松运行自己的代理。
您还可以使用5个命令,在2-3分钟内轻松地将自己的代理部署到Heroku:

git clone https://github.com/Rob--W/cors-anywhere.git
cd cors-anywhere/
npm install
heroku create
git push heroku master
在运行这些命令之后,您将在运行自己的CORS Anywhere服务器,例如,
https://cryptic-headland-94862.herokuapp.com/

现在,将代理的URL作为请求URL的前缀:

https://cryptic-headland-94862.herokuapp.com/https://example.com
添加代理URL作为前缀会导致通过代理发出请求,然后:

  • 将请求转发到
    https://example.com
  • https://example.com
  • 访问控制允许原点
    标题添加到响应中
  • 将带有添加的头的响应传递回请求的前端代码
  • 然后浏览器允许前端代码访问响应,因为带有
    访问控制允许原点的响应是浏览器看到的

    即使请求触发浏览器执行CORS飞行前
    选项
    请求,这也会起作用,因为在这种情况下,代理还会发回飞行前成功所需的
    访问控制允许标头
    访问控制允许方法
    标头


    如何避免CORS飞行前检查

    问题中的代码会触发CORS预飞行,因为它会发送
    授权
    标题

    即使没有它,
    Content-Type:application/json
    头也会触发预飞行

    “飞行前”的意思是:在浏览器尝试问题代码中的
    POST
    之前,它将首先向服务器发送一个
    OPTIONS
    请求,以确定服务器是否选择接收具有
    Authorization
    内容类型:application/json
    标题的跨源
    POST

    它与一个小的curl脚本配合得很好——我得到了我的数据

    要使用
    curl
    进行正确测试,必须模拟浏览器发送的飞行前
    选项
    请求:

    curl -i -X OPTIONS -H "Origin: http://127.0.0.1:3000" \
        -H 'Access-Control-Request-Method: POST' \
        -H 'Access-Control-Request-Headers: Content-Type, Authorization' \
        "https://the.sign_in.url"
    
    …带有
    https://the.sign_in.url
    替换为您实际登录的
    URL

    浏览器需要从该
    选项
    请求中看到的响应必须具有如下标题:

    import express from 'express';
    const emailRouter = require('./routes/email');  // in my case, I was sending an email through a form in ReactJS
    const fs = require('fs');
    const https = require('https');
    
    const app = express();
    const port = 8000;
    
    // CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
    app.all('*', (req, res, next) => {
        res.header("Access-Control-Allow-Origin", "https://localhost:3000");
        next();
    });
    
    // Routes definition
    app.use('/email', emailRouter);
    
    // HTTPS server
    const credentials = {
      key: fs.readFileSync('server.key'),
      cert: fs.readFileSync('server.crt')
    };
    
    const httpsServer = https.createServer(credentials, app);
    httpsServer.listen(port, () => {
        console.log(`Back-end running on port ${port}`);
    });
    
    访问控制允许原点:http://127.0.0.1:3000
    访问控制允许方法:POST
    访问控制允许标头:内容类型、授权
    
    如果
    选项
    响应不包含这些标题,那么浏览器将立即停止,甚至不会尝试发送
    POST
    请求。此外,响应的HTTP状态代码必须是2xx,通常为200或204。如果是任何其他状态代码,浏览器将立即停止

    问题中的服务器使用501状态代码响应
    选项
    请求,这显然意味着它试图表明它没有实现对
    选项
    请求的支持。在这种情况下,其他服务器通常使用405“不允许使用方法”状态代码进行响应

    因此,如果服务器以405或501或200或204以外的任何方式响应该
    选项
    请求,或者如果服务器没有以这些必要的响应头响应,则您永远无法从前端JavaScript代码直接向该服务器发出
    POST
    请求

    避免触发问题案例飞行前准备的方法是:

    • 如果服务器不需要
      授权
      
      var cors = require('cors')
      
      app.use(cors()) // Use this after the variable declaration
      
      credentials: 'include',
      
         async function get_ajax_data(){
             var _reprojected_lat_lng = await $.ajax({
                                      type: 'GET',
                                      dataType: 'jsonp',
                                      data: {},
                                      url: _reprojection_url,
                                      error: function (jqXHR, textStatus, errorThrown) {
                                          console.log(jqXHR)
                                      },
                                      success: function (data) {
                                          console.log(data);
      
                                          // note: data is already json type, you
                                          //       just specify dataType: jsonp
                                          return data;
                                      }
                                  });
      
      
       } // function               
      
      @Value( "${app.allow.origins}" )
          private String allowOrigins;    
      @Bean
      public WebMvcConfigurer corsConfigurer() {
                  System.out.println("allow origin: "+allowOrigins);
                  return new WebMvcConfigurerAdapter() {
                      @Override
                      public void addCorsMappings(CorsRegistry registry) {
                          registry.addMapping("/**")
                          //.allowedOrigins("http://localhost")
                          .allowedOrigins(allowOrigins)
                          .allowedMethods("PUT", "DELETE","GET", "POST");
                      }
                  };
              }
      
      headers.append('Access-Control-Allow-Origin', 'http://localhost:3000');
      headers.append('Access-Control-Allow-Credentials', 'true');
      
      headers.append('GET', 'POST', 'OPTIONS');
      
      Access-Control-Allow-Origin : http://localhost:3000
      Access-Control-Allow-Credentials : true
      Access-Control-Allow-Methods : GET, POST, OPTIONS
      Access-Control-Allow-Headers : Origin, Content-Type, Accept
      
      function performSignIn() {
          let headers = new Headers();
      
          headers.append('Content-Type', 'application/json');
          headers.append('Accept', 'application/json');
          headers.append('Authorization', 'Basic ' + base64.encode(username + ":" +  password));
          headers.append('Origin','http://localhost:3000');
      
          fetch(sign_in, {
              mode: 'cors',
              credentials: 'include',
              method: 'POST',
              headers: headers
          })
          .then(response => response.json())
          .then(json => console.log(json))
          .catch(error => console.log('Authorization failed : ' + error.message));
      }
      
      $URL = $_GET['url'];
      echo json_encode(file_get_contents($URL));
      die();
      
      fetch('https://example.com/no-cors.php' + '?url=' + url)
        .then(response=>{*/Handle Response/*})`
      
      <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteCond %{REQUEST_METHOD} ^OPTIONS
        RewriteRule .* . [F]
      </IfModule>
      
      <IfModule mod_rewrite.c>
        RewriteEngine off
        RewriteCond %{REQUEST_METHOD} ^OPTIONS
        RewriteRule .* . [F]
      </IfModule>
      
      post(
          this.serverUrl, dataObjToPost,
          {
            headers: new HttpHeaders({
                 'Content-Type':  'application/json',
               })
          }
      )
      
      header("Access-Control-Allow-Origin: http://localhost:4200");
      header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
      header("Access-Control-Allow-Headers: Content-Type, Authorization");
      
      $postdata = file_get_contents("php://input");
      $request = json_decode($postdata);
      print_r($request);
      
      server.key & server.crt
      
      import express from 'express';
      const emailRouter = require('./routes/email');  // in my case, I was sending an email through a form in ReactJS
      const fs = require('fs');
      const https = require('https');
      
      const app = express();
      const port = 8000;
      
      // CORS (Cross-Origin Resource Sharing) headers to support Cross-site HTTP requests
      app.all('*', (req, res, next) => {
          res.header("Access-Control-Allow-Origin", "https://localhost:3000");
          next();
      });
      
      // Routes definition
      app.use('/email', emailRouter);
      
      // HTTPS server
      const credentials = {
        key: fs.readFileSync('server.key'),
        cert: fs.readFileSync('server.crt')
      };
      
      const httpsServer = https.createServer(credentials, app);
      httpsServer.listen(port, () => {
          console.log(`Back-end running on port ${port}`);
      });
      
      https.createServer(credentials, (req: any, res: any) => {
        res.writeHead(200);
        res.end("hello world from SSL\n");
      }).listen(port, () => {
        console.log(`HTTPS server listening on port ${port}...`);
      });
      
          await axios.get(`https://localhost:8000/email/send`, {
              params: {/* whatever data you want to send */ },
              headers: {
                  'Content-Type': 'application/json',
              }
          })
      
      HTTPS=true SSL_CRT_FILE=server.crt SSL_KEY_FILE=server.key npm start
      
      const cors = require('cors');
      
      const userRouter = require('./routers/user');
      
      expressApp = express();
      expressApp.use(cors());
      expressApp.use(express.json());
      expressApp.use(userRouter);
      
      fetch(sign_in, {
              mode: 'no-cors',
              credentials: 'include',
              method: 'POST',
              headers: headers
          })
          .then(response => response.json())
          .then(json => console.log(json))
          .catch(error => console.log('Authorization failed : ' + error.message));
      }
      
      app.use((req, res, next) =>{
      res.setHeader('Access-Control-Allow-Origin', '*');
      res.setHeader('Access-Control-Allow-Headers','Origin, X-Requested-With, Content-Type,Accept, Authortization');  
      res.setHeader('Acces-Control-Allow-Methods','GET, POST, PATCH, DELETE');
      
      `[[redirects]]
          from = "/cors-proxy/*"
          to = ":splat"
          status = 200
          force = true`
      
      services.AddCors(); 
      
      app.UseCors(options =>
           options.WithOrigins("http://localhost:8080")
                  .AllowAnyHeader()
                  .AllowAnyMethod());
      
      make sure you add this before - app.UseRouting();
      
      npm install cors
      
      const cors = require('cors');
      app.use(cors());