ABAP 应用服务器的 HTTP 响应状态码 (Status Code)

最近笔者参与了 SAP Commerce Cloud 的标准开发,我们调用微软云平台 Azure 上创建 Lambda Function 的Restful API来创建 Lambda Function:

在开发过程中发现该 API 工作不太稳定,同样的输入,时不时会返回 HTTP 400 Bad Request:Encountered an error (InternalServerError) from host runtime
这个错误并不是总能重现。

通过排查,最后我们确认这个问题和我们调用 API 的代码无关,于是给 Azure 报了一个 bug:

在分析定位问题时,不由得让我怀念起以前在 ABAP On-Premise 上做开发的一个便利之处——大多数问题都可以通过在 ABAP 应用服务器端调试来找到根源。
本文记录了 2016 年时,SAP 成都研究院 CRM 开发团队在开发 SAP CRM Fiori 应用时的一些技术讨论,关于 HTTP 请求的响应状态码的差异。
当时我们用 Chrome 打开 SAP Fiori 应用,在 Chrome 开发者工具的 network 标签里,观察到有的请求响应码为 HTTP 200,有的却是 HTTP 304.

HTTP 200 和 HTTP 304 理论上的差异解析,网上一搜一大把:
本文我们从一个实际的例子出发,观察 ABAP 服务器分别是在何种情况下,返回 HTTP 200 和 304 这两个状态码的,帮助大家加深理解。
分几种情况进行讨论。
第一种情况:HTTP 200 OK
第二种情况:HTTP 304 Not Modified
第三种情况:HTTP 200(from Cache)
首先进行第一轮测试。
将这种来自 SAP UI5 标准库文件的 url 粘贴到浏览器里访问:
https://<host>:7080/sap/bc/ui5_ui5/ui2/ushell/resources/~20160308134900~/sap/fiori/core-min-0.js
得到 HTTP 200 状态码:

大家想过没有,上图高亮的 HTTP 响应头部字段,比如 last-modified, 是在 ABAP 服务器上哪段代码里被填充的?
SAP NetWeaver 7.3 EHP1 ABAP 系统和 UI Addon 或 SAP NetWeaver 7.4 SPS01 或更高版本的 SAPUI5 库团队提供程序,可以用于在 Eclipse 和 ABAP 系统上的 SAPUI5 库之间同步 SAPUI5 应用程序资源。
作为 SAP Business Suite 系统 7.00 及更高版本(尤其是 7.31 版本)的替代方案,您可以使用交互式 ABAP 报告/UI5/UI5_REPOSITORY_LOAD 或/UI5/UI5_REPOSITORY_LOAD_HTTP,它们提供了类似的功能。与 SAPUI5 Repository Team Provider 相比,它没有提供内置的代码合并。这里,可以使用一个单独的源代码库,如 git 或 Subversion (SVN)。
灵活运用 Jerry 文章 SAP错误消息调试之七种武器:让所有的错误消息都能被定位 介绍的办法,顺利通过调试的方式,找到准确的位置如下:

上述代码的逻辑:
(1) 第九行,服务器试图从 HTTP 请求的头部字段中,提取名为 If-Modified-Since 的字段值,因为这是我第一次请求该 JavaScript 文件,而这个字段的值逻辑上应该等于第一次请求到达服务器后,从服务器返回的响应结构里名为 last-modified 字段的值。
在我的第一轮测试里,因为是第一次请求该文件,HTTP 请求头部没有包含 If-Modified-Since 字段,所以服务器解析出的值为空,即变量 lv_modified_since 为空。
(2) 在我使用的 ABAP 服务器上,JavaScript 文件 core-min-0.js 最后修改的时间戳为 20160316205045. 因此,两个变量 lv_change_time_char 和 lv_change_time_string 都被附上了这个值。

下面第 20 行代码展示了前文 HTTP 200 状态码的截图里,HTTP 响应字段 cache-control 被填充的地方。

第二种情况:HTTP 304 Not Modified
之前 Chrome 浏览器里打开的 url:
https://<host>:7080/sap/bc/ui5_ui5/ui2/ushell/resources/~20160308134900~/sap/fiori/core-min-0.js
不用关闭这个浏览器窗口,直接按 F5 刷新,这次收到的响应码不再是 HTTP 200 OK,而是 HTTP 304 Not Modified.

为什么会产生这种差异呢?按 F5 之后仔细观察请求头部,发现第二次请求,浏览器发出的 HTTP 请求里,If-Modified-Since 字段包含的就是第一个请求里从服务器端返回的 last-modified 字段值。

按 F5 刷新的这个请求到了服务器端,这一次 ABAP 服务器成功解析出请求字段 If-Modified-Since 的值:

将客户端发送过来的这个 If-Modified-Since 时间戳,同服务器端该文件最后修改的时间戳进行比较(即下图第 26 行 AND 后的第二个判断条件),发现二者相等,因此在第 28 行返回 HTTP 304 Not Modified.

第三种情况:HTTP 200(from Cache)
关掉 Chrome,再打开,再访问同一 url,此时 Chrome 直接从自身的 cache 里返回该 JavaScript 文件,而不是向 ABAP 服务器上发起请求。因此服务器上所有 ABAP 断点均不会触发。

再回到 Jerry 遇到的那个 Azure 上执行 function 创建 API 遇到的 HTTP 400 Bad request 的 incident,至本文发稿时为止还是未能得到解决。

尽管 Azure 的 Function Host 运行时也是开源的,但不能调试,我拿着这些海量代码也没辙,目前 Github 上看到的就有多达 967 个开着的issue.

从开发者遇到问题后调试定位这个角度上说,还是 ABAP On-Premises 方便啊。
感谢阅读。
版权声明: 本文为 InfoQ 作者【Jerry Wang】的原创文章。
原文链接:【http://xie.infoq.cn/article/a218503e6276f26a5b284328c】。文章转载请联系作者。
评论