在nodejs服务器和ABAP服务器上使用jsonp
In my blog Cross domain request in ABAP and Java with two workaround I introduce the step how to deal with Cross Domain issue using Cross-origin resource sharing ( CORS ) supported by almost all modern browsers.
And there is another alternative for cross domain issue, that is JSONP which can work on legacy browsers which predate CORS support.
In this blog, I will first explain how to use JSONP and then introduce the secret behind it.
JSONP in nodeJS server
Suppose I have two employee ID lookup service hosted by the port 3000 and 3001 in my local server. The service will simply return employee name by ID.
The client web page is hosted in port 3000. According to same origin policy, the web page hosted in port 3000 is allowed to access the service hosted in localhost:3000, but forbidden for localhost:3001.
Let’s now do a verification. This is my server listening to port 3000:
const express = require('express');
const app = express();
const port = 3000;
var path = require('path');
var repo = {
"I042416": "Jerry",
"I042417": "Tom",
"I042418": "Jim"
}
app.use(express.static(path.join(__dirname, 'public')));
app.get('/request', (request, response) => {
console.log("The employee ID sent from Client:" + request.query.id);
response.json({
UserName: repo[request.query.id] + " ( handled in port 3000 )"
});
});
app.listen(port, (err) => {
if (err) {
return console.log('something bad happened', err)
}
console.log(`server is listening on ${port}`)
});
And this is my client page which allows end user to type the employee ID and send the query request:
<html>
<body>
<form action="">
ID: <input type="text" id = "inumber" name="ID" value="I042416"><br>
<input type="submit" value="Submit">
</form>
</body>
<script src="jquery1.7.1.js"></script>
<script>
$(document).ready(function(){
$("form").click(function(e){
e.preventDefault();
var data = {
id: $("#inumber").val()
};
$.ajax({
type: 'GET',
data: data,
url: 'http://localhost:3000/request',
dataType: 'json',
success: function(data) {
alert(data.UserName);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('error ' + textStatus + ' ' + errorThrown);
}
});
});
});
</script>
</html>
When I click Submit button, I get query response returned from service in port 3000 as expected:
And this is the log output in the console of service in port 3000:
Now I make small modification on the web page in port 3000, forcing it to send request to port 3001 instead:
And resend the id query, this time I saw the expected cross domain error message:
How to resolve cross domain issue using JSONP
Both minor changes in client and server side are necessary.
In service working in port 3001, I add a new service end point “request_jsonp”:
app.get('/request_jsonp', (request, response) => {
console.log("This service supports JSONP now: " + request.query.id);
var data = "{" + "UserName:'" + repo[request.query.id] + " ( handled in port 3001 )'"
+ "}";
var callback = request.query.callback;
var jsonp = callback + '(' + data + ');';
response.send(jsonp);
response.end();
});
In client web page, I change the send AJAX data type from json to jsonp, and inform server that “please parse the callback function name from literal “callback” in request header.
$.ajax({
type: 'GET',
data: data,
url: 'http://localhost:3001/request_jsonp',
dataType: 'jsonp',
jsonp: 'callback',
jsonpCallback: 'jsonpCallback',
success: function(data) {
alert(data.UserName);
},
error: function(jqXHR, textStatus, errorThrown) {
console.log('error ' + textStatus + ' ' + errorThrown);
}
});
Now send the query again from localhost:3000 page, and the request could successfully reach service in localhost:3001, handled there and return to localhost:3000 again:
Magic behind JSONP
In fact, no magic at all. The mechanism of JSONP just utilize the “benefit” that the HTML
When I send the AJAX call with data type jsonp, a new script element is created on the fly. The employee ID specified by end user is also appended as a query field in request header.
In server side, the response to this JSONP request is NOT json data, but a fragment of executable JavaScript code. I add a print statement to make it more clear:
Once this response returns to client side, it will get executed immediately there as a reaction to jsonp request sent from client.
For more detail explanation you can refer to Wikipedia How JSONP works.
JSONP in ABAP Server
Suppose I have a web page in system AG3/001 which would like to access service in AG3/815. Create a ICF service in AG3/815:
AG3/001 has port 44354 and AG3/815 port: 44356 The web page is put in AG3/001 which has almost exactly the same code in previous nodeJS chapter. This request fails as expected.
Now enhance the ICF handler class with JSONP support: return a string which contains executable JavaScript code instead:
METHOD if_http_extension~handle_request.
DATA(lv_userid) = server->request->get_form_field( 'id' ).
DATA(lv_callback) = server->request->get_form_field( 'callback' ).
DATA(lv_name) = COND #( WHEN lv_userid = 'I042416' THEN 'Jerry' ELSE 'Unknown').
DATA(lv_response) = |{ UserName:'{ lv_name }'}|.
DATA(lv_jsonp) = |{ lv_callback }({ lv_response });|.
server->response->append_cdata(
data = lv_jsonp
length = strlen( lv_jsonp ) ).
ENDMETHOD.
And click on submit button of web page in AG3/001, this time it works:
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法