Javascript Zeit(Vercel)现在无服务器身份验证请求因CORS而失败

Javascript Zeit(Vercel)现在无服务器身份验证请求因CORS而失败,javascript,cors,authorization,serverless,vercel,Javascript,Cors,Authorization,Serverless,Vercel,在执行修补程序/发布/放入请求时,我无法正确处理CORS问题,该请求来自浏览器,发送带有承载令牌的授权头(这在浏览器外部和获取请求时正常工作) 如果有帮助的话,我将使用授权端 这是我的now.jsonheaders部分,我尝试了很多组合,但都没有从浏览器中成功 我尝试使用npmcors包,但没有成功 尝试在now.json中添加routes 尝试使用res.addHeader() 还尝试手动处理选项请求,执行以下操作: 最后,这是我得到的错误 Access to XMLHttpReque

在执行
修补程序
/
发布
/
放入
请求时,我无法正确处理CORS问题,该请求来自浏览器,发送带有
承载令牌的
授权
头(这在浏览器外部和
获取
请求时正常工作)

如果有帮助的话,我将使用授权端


这是我的
now.json
headers部分,我尝试了很多组合,但都没有从浏览器中成功


  • 我尝试使用npm
    cors
    包,但没有成功
  • 尝试在
    now.json中添加
    routes
  • 尝试使用
    res.addHeader()
  • 还尝试手动处理
    选项
    请求,执行以下操作:
  • 最后,这是我得到的错误

    Access to XMLHttpRequest at 'https://api.example.org/api/users' from origin 'https://example.org' has been blocked by CORS policy: 
    Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
    

    不知道我错了什么,也不知道如何正确处理。

    我可以通过使用绕过此问题

    我检查了一下,与我手动使用
    res.setHeader
    尝试做的事情没有太大区别,我猜可能遗漏了什么

    然而,我不明白为什么
    now.json
    中的设置不能正常工作,我需要在无服务器函数中手动执行此操作

    不管怎么说,万一有人找到了这篇文章,我最终得到了这样的结果:

    从“micro-cors”导入micro;
    函数MyApi(req,res){
    如果(请求方法==“选项”){
    返回res.status(200.end();
    }
    //在此之后正常处理其他请求
    }
    const cors=micro();
    导出默认cors(MyApi);
    
    我可能会用自己编写的解决方案再试一次,以便更好地了解出了什么问题,也因为我不想要额外的依赖关系

    如果我这样做,将更新此答案


    编辑:在深入检查之后,我发现另一个问题是库
    express jwt
    jwt
    解析失败时专门更改
    res
    对象

    我有一个小型中间件,它通过以下操作打破了一切:

    wait authValidateMiddlware(req,res);
    

    wait
    失败时,由于
    express jwt
    在不知不觉中更改了
    res
    标题(设置错误),然后我尝试手动设置
    res
    标题,试图自己正确处理错误,因此引发了一些问题“多次更改
    res
    标头”。

    我遇到了类似的问题,通过将标头添加到路由中解决了该问题,如下所示:

    "routes": [
        {
          "src": ".*",
          "methods": ["GET", "POST", "OPTIONS"],
          "headers": {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept",
            "Access-Control-Allow-Credentials": "true"
          },
          "dest": "index.js",
          "continue": true
        },
        {
          "src": "/user/login", "methods": ["POST"], "dest": "index.js"
        }
      ]
    
    请记住添加
    继续:true


    我当时的情况也差不多。我在Vercel(现在)中有两个无服务器功能,我希望任何人都可以使用它们。我解决问题的方法类似于

    首先,我的项目根目录中有以下
    now.json

    {
      "routes": [
        {
          "src": "/api/(.*)",
          "headers": {
            "Access-Control-Allow-Origin": "*",
            "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept",
            "Access-Control-Allow-Credentials": "true"
          },
          "continue": true
        },
        {
          "src": "/api/(.*)",
          "methods": ["OPTIONS"],
          "dest": "/api/cors"
        }
      ]
    }
    
    以下是两种路线配置的细分:

    {
      "src": "/api/(.*)",
      "headers": {
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept",
        "Access-Control-Allow-Credentials": "true"
      },
      "continue": true
    }
    
    • “src”:/api/(.*)
    匹配任何转到
    /api/*
    的请求

    • “标题”:[…]
    将CORS标头应用于路由,表示允许CORS

    • “继续”:true
    在应用CORS头之后,继续查找其他路由匹配项。这允许我们将CORS头应用于所有路由,而不必为每个路由应用。例如,现在
    /api/auth/login
    /api/main/sub/resource
    都将应用CORS头

    {
      "src": "/api/(.*)",
      "methods": ["OPTIONS"],
      "dest": "/api/cors"
    }
    
    此配置的作用是拦截所有
    HTTP/OPTIONS
    请求,即CORS飞行前检查,并将它们重新路由到
    /api/CORS
    的特殊处理程序

    routes配置分解的最后一点将我们引向
    /api/cors.ts
    函数。处理程序如下所示:

    从'@now/node'导入{NowRequest,NowResponse};
    导出默认值(请求:NowRequest,响应:NowResponse)=>{
    返回res.status(200.send();
    }
    

    该处理程序所做的基本上是接受CORS飞行前
    选项
    请求,并以
    200/OK
    对其作出响应,向客户表示“是的,我们对CORS业务开放。”

    我对CORS和Vercel无服务器功能有类似的问题

    经过大量的尝试→ 失败的过程我刚刚找到了解决方案


    解决 太长,读不下去了 最简单的解决方案,就是使用

    并有一个类似的实现

    import { NowRequest, NowResponse } from '@now/node';
    import microCors from 'micro-cors';
    
    const cors = microCors();
    
    const handler = (request: NowRequest, response: NowResponse): NowResponse => {
      if (request.method === 'OPTIONS') {
        return response.status(200).send('ok');
      }
    
      // handle incoming request as usual
    };
    
    export default cors(handler);
    

    更长的版本,但没有任何新的依赖项 使用
    vercel.json
    处理请求头

    vercel.json

    {
      "headers": [
        {
          "source": "/.*",
          "headers": [
            {
              "key": "Access-Control-Allow-Origin",
              "value": "*"
            },
            {
              "key": "Access-Control-Allow-Headers",
              "value": "X-Requested-With, Access-Control-Allow-Origin, X-HTTP-Method-Override, Content-Type, Authorization, Accept"
            },
            {
              "key": "Access-Control-Allow-Credentials",
              "value": "true"
            }
          ]
        }
      ]
    }
    
    自我尝试后,在上述设置中有两个重要键

  • 您必须根据需要设置
    访问控制允许原点
  • Access Control Allow Headers
    中,必须在其值中包含
    Access Control Allow Origin
  • 然后在无服务器函数中,还需要处理

    /api/index.ts

    const handler = (request: NowRequest, response: NowResponse): NowResponse => {
      if (request.method === 'OPTIONS') {
        return response.status(200).send('ok');
      }
    
      // handle incoming request as usual
    };
    


    我建议阅读中的代码,这是一个非常简单的代码,您可以在几分钟内理解它将做什么,这使我不担心将其添加到依赖项中。

    接受的答案对我不起作用。但是vercel现在似乎有了,他们的示例代码是:

    const allowCors=fn=>async(req,res)=>{
    res.setHeader('Access-Control-Allow-Credentials',true)
    res.setHeader('Access-Control-Allow-Origin','*'))
    //另一种选择
    //res.setHeader('Access-Control-Allow-Origin',req.headers.Origin);
    res.setHeader('Access-Control-Allow-Methods','GET,OPTIONS')