另一个“发送后无法设置标题”

时间:2018-09-27 13:36:31

标签: node.js express sparql

我收到“发送后无法设置标头”错误,我理解这可能是由于我的服务器多次发送了响应,但是我的代码似乎并非如此,至少在表面上。我向dbpedia进行查询以获得一些资源,然后将其发送回我的客户端。这是代码:

app.get("/",function(req,res,next){
    if (req.query.titolo){
        var response ;
        let [ artist, title ] = getArtistTitle(req.query.titolo);
        title = title.replace(" ","_");//for dbpedia resource names
        const prefixes = {
            dbo: "http://dbpedia.org/ontology/",
            db: "http://dbpedia.org/resource/"
        }
        DbPediaClient.setOptions('application/sparql-results+json',prefixes);
        DbPediaClient.query("SELECT ?abstract WHERE { db:"+title+
        " dbo:abstract ?abstract. FILTER langMatches(lang(?abstract),'en') }")
        .then((data)=>{
            response = data["results"]["bindings"][0]["abstract"]["value"] ;
            return res.json({abstract: response}) ;
        })
        .catch((error)=>{
            console.log(error);
        });
    }
});

我使用virtuoso-sparql-client向http://dbpedia.org/sparql进行查询(DbPediaClient在此函数之外初始化)。我已经尝试使用res.send而不是res.json,它仍然会给出相同的错误。顺便说一下,这是

Error: Can't set headers after they are sent.
    at validateHeader (_http_outgoing.js:491:11)
    at ServerResponse.setHeader (_http_outgoing.js:498:3)
    at ServerResponse.header (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/node_modules/express/lib/response.js:767:10)
    at ServerResponse.send (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/node_modules/express/lib/response.js:170:12)
    at DbPediaClient.query.then (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/server.js:43:15)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

如果您需要更多信息,请询问。

1 个答案:

答案 0 :(得分:3)

Express是一个处理请求/响应周期的框架,该框架通过遍历与HTTP请求中指定的路径匹配的路由,并让您的代码在每次匹配中发送响应,或者如果未发送响应则调用next() 。这里的问题是您有以下问题:

app.get("/",function(req,res,next){
    res.sendFile(...);
    next();
});

app.get("/",function(req,res,next){
    if (req.query.titolo){
        ...
        res.json(...);
    }
});

此代码表示

  

每当我收到对/的HTTP请求,然后发送一些HTML,然后,如果该请求在查询中包含titolo,则也发送一些JSON。

Express告诉您,由于您已经发送了HTML,因此您无法发送其他任何内容。

一种解决方案是将API路由移到HTML上方:

app.get("/",function(req,res,next){
    if (req.query.titolo){
        ...
        res.json(...);
    } else {
      next();
    }
});

app.get("/",function(req,res){
    res.sendFile(...);
});

这意味着

  

每当我收到对/的HTTP请求时,如果该请求在查询中包含titolo,则发送一些JSON,否则发送一些HTML。

但是我的建议是将API路由移动到与静态文件的路由不冲突的其他路径,这对于HTTP服务器而言更为常见。