Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
ArthurYang
Product and Topic Expert
Product and Topic Expert
359

本文档目的是帮助您初步了解CAP+Nodejs的后端如何暴露接口被外部消费,阅读时间约为0.5小时。

 

使用前提是完成CAP for Nodejs开发入门练习,和CAP for Nodejs部署入门练习

 

如果您对BTP感兴趣,BTP个人精选内容目录 | SAP Blogs 可能有更多你需要的内容

 

本文档包含以下部分:

1.在本地环境下启动服务并使用postman调用接口

2.将代码部署到BTP后使用postman调用接口

 

1.在本地环境下启动服务并使用postman调用接口

修改srv/risk-service.cds为如下代码,移除所有安全相关配置并额外向外发布一个service:

 

using { sap.ui.riskmanagement as my } from '../db/schema';
@path: 'service/risk'
service RiskService {
  entity Risks as projection on my.Risks;
    annotate Risks with <li-user uid="1599241" login="odata"></li-user>.draft.enabled;
  entity Mitigations as projection on my.Mitigations;
    annotate Mitigations with <li-user uid="1599241" login="odata"></li-user>.draft.enabled;
}

service ExternalAPI {
    entity testRisks as projection on my.Risks;
    action checkDescr(riskId: String) returns{
        descr: String;
    };
}

 

 这里新建的service下包含一个entity和一个actionaction接收一个String返回一个String

添加文件srv/service-auth.cds,将先前去除的安全相关配置统一放在这里

using { RiskService } from './risk-service';
annotate RiskService.Risks with @(requires: 'authenticated-user');
annotate RiskService.Mitigations with @(restrict : [
            {
                grant : [ 'READ' ],
                to : [ 'RiskViewer' ]
            },
            {
                grant : [ '*' ],
                to : [ 'RiskManager' ]
            }
        ]);

 

接下来修改srv/risk-service.js,添加以下代码,以确定先前定义的action的逻辑

 

const db = await cds.connect.to('db');
        // 实现 checkDescr action
    this.on('checkDescr', async (req) => {
        let tx = cds.transaction(req);
        // 获取输入参数 riskId
        const { riskId } = req.data;
        console.log(riskId,"xxxxx  request received xxxxxxxxxxxxxxx");
        // 从数据库命名空间中获取名为Risks的表
        const {Risks} = db.entities("sap.ui.riskmanagement");
        try {
            // 查询数据库,获取与riskId对应的descr字段
            const riskResult = await tx.run(SELECT.from(Risks).columns('descr').where({ID:riskId}).limit(1));

            if (riskResult) {
                // 如果找到了对应的risk记录,返回descr
                console.log(riskResult[0].descr,"xx record found xxxxxxxxxxxxx");
                return { descr: riskResult[0].descr };
            } else {
                // 如果没有找到对应的risk,抛出错误
                req.error(404, `Risk with ID ${riskId} not found`);
            }
        } catch (error) {
            // 如果数据库查询出错,返回错误
            req.error(500, `Failed to fetch risk description: ${error.message}`);
        }
    });

 

 

本地启动后端来查看效果

cds watch

此时命令行会显示4004的链接,按住ctrl后鼠标左键单击即可打开

ArthurYang_0-1733827484981.png

但由于BAS运行在容器中,要访问到这里的4004,

a.可以在BAS安装rest插件https://github.com/Huachao/vscode-restclient来访问 

b.也可以使用本地postman,首先按住Ctrl单击BAS内提示的localhost:4004 URL来打开后端预览页面,此时可以F12打开开发者工具,找到Application应用这个Tab,再找到Storag-Cookies,会得到一个CookieName和一个CookieValue

ArthurYang_1-1733827580737.png

例如workspaces-xx-xxxkj_WSR_SESSIONID和

xLix6/X4iaJ8p+1MxxoyHRmFvgdln9yVv4N1y0aSzqaeWV+NMjHRfXXNgrRpHESOGSJE4g8Yg9zCBOyzFJIcmA==

 

然后在postman内新建request:

使用POST方法,URL为后端预览页面URL+/odata/v4/external-api/checkDescr

添加一个header,其Key为 cookie 其Value为 CookieName=CookieValue

另外再添加一个header为Content-Type:application/json

Body为

{

    "riskId":"20466922-7d57-4e76-b14c-e53fd97dcb11"

}

 

最后点击Send,发送请求,查看结果

 

 

2.将代码部署到BTP后使用postman调用接口

为了体现权限区分,这里修改srv/risk-service.cds中的RiskService entity Risks权限中READ分配的对象从RiskViewer修改为authenticated-user(这个权限指的是所有用户,但一般仅作为技术用户用于系统集成,不用于来自前端的访问,详情查阅CDS-based Authorization | capire

 

在根目录打包并部署后,让我们从postman调用平台上的API

 

首先获取调用权限:进入子账户 实例与租用 实例 cpapp-auth, 在右侧的弹窗中找到服务键值,单击创建,命名为postmanTest 再单击创建,最后点击刚刚创建的服务键值的名字,即可获得clientidclientsecretapiurl这几个参数,再进入子账户 空间 dev cpapp-srv ,保存routeURL

 

然后创建获取token用的postman request

使用GET方式,URL为apiurl+/oauth/token?grant_type=client_credentials,Auth为Basic Auth,Username为clientid,Password为clientsecret, Headers添加Content-Type:application/json的属性,此时点击Send即可看到回复,回复中的access_token即为后续调用所需的认证参数

 

再创建调用接口的postman request:

使用GET方法,URL为cpapp-src的route+/odata/v4/service/risk/Risks, Auth为No Auth, Headers添加Content-Type:application/json和Authorization:Bearer access_token,这里Bearer后有一个空格,access_token则为上一步获取的token

Body留空,即可READ到Risks这个entity,切换URL并添加body后还可以访问到之前定义的ExternalAPI服务

 

关于本文内容有任何问题或见解,欢迎在评论区留下你的想法,如果需要帮助,也可以直接联系到我 arthuryang1996@foxmail.com,感谢你的时间