[Python][Javascript] 无法弄清楚如何将 API 调用从 NEXTjs 网页 GUI 发送到 Python Falcon 后端
[Python][Javascript] can't figure out how to send API calls from a NEXTjs webpage GUI to a Python Falcon backend
我正在尝试从带有简单表单字段的 NEXTjs 前端向位于同一服务器上的后端发送 POST 请求,该服务器是使用 Falcon 的 python 脚本图书馆。 python 脚本本身是 Gunicorn 的 运行 并在 8080 端口上侦听。
两个代码 运行 都很好,没有错误,但是当我尝试提交表单时,我得到的只是一个 415 错误,这似乎表明我正在尝试发送到 API不是受支持的媒体类型,但是正如 answer
中所指出的
Falcon has out of the box support for requests with Content-Type: application/json
由于网页和服务器托管在同一个 VPS 我也尝试在获取调用中使用 127.0.0.1 地址但也没有成功(后端 API 事实上甚至没有回应)
这是后端代码:
#!/usr/bin/env python
# coding=utf-8
import time
import falcon
import json
class Resource(object):
def on_post(self, req, resp, **kwargs):
request_body = req.media
print('POST Request: {}'.format(req))
print('Request body: {}'.format(request_body))
start = time.time()
resp.body = json.dumps({
'count_identical_pairs': count_identical_pairs(request_body),
'computation_time': int((time.time() - start) * 1000)
})
def count_identical_pairs(integers_array):
total = 0
count = dict()
# Type checking
if not isinstance(integers_array, list):
return -1
# Check if N is within the range [0..100,000]
if len(integers_array) > 100000:
return -2
for integer in integers_array:
# Check if each element of the array is within the range [−1,000,000,000..1,000,000,000]
if integer not in range(-1000000000, 1000000000):
return -3
if str(integer) not in count:
count[str(integer)] = 1
else:
count[str(integer)] += 1
for key, value in count.items():
total += value * (value - 1) / 2
return total
api = application = falcon.API()
api.add_route('/count_identical_pairs', Resource())
这是前端:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
class Index extends React.Component {
constructor() {
super();
this.state = {
input_array: [],
};
this.onSubmit = this.onSubmit.bind(this);
this.myHeaders = new Headers();
}
onChange = evt => {
// This triggers everytime the input is changed
this.setState({
[evt.target.name]: evt.target.value,
});
};
onSubmit = evt => {
evt.preventDefault();
console.log('this.state.input_array = ' + this.state.input_array);
console.log('JSON.stringify(this.state.input_array) = ' + JSON.stringify(this.state.input_array));
// Making a post request with the fetch API
// Test payload [1, 7, 7, 5, 7, 5, 6, 1]
fetch('http://vps638342.ovh.net:8080/count_identical_pairs', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8'
},
mode: 'no-cors', // Security hazard?
body: JSON.stringify(this.state.input_array),
redirect: 'follow'
})
.then(response => response.text())
.then(data => console.log('Data: ' + data))
.catch(error => console.log('Error: ' + error))
};
render() {
return (
<form onSubmit={this.onSubmit} >
<input
name="input_array"
type="text"
id="name"
value={this.state.input_array}
onChange={this.onChange}>
</input>
<input type="submit" />
</form>
);
};
}
ReactDOM.render(<Index />, document.getElementById("root"));
编辑 1: 我已经用 Postman 测试了 python 后端 API,我可以看到它已经运行良好,正如你所看到的图为:
编辑 2: 感谢@Maku 这是后端的更新代码,允许所有来源、方法和 header。我是服务器开发的新手,但我猜这不是一种非常安全的编码方式,但至少它有效(如果我找到更推荐的方法,我会添加第三次编辑)
在你的 falcon 服务器中启用 CORS 并在你的 javascript 中删除 'no-cors' 标志,前几天对我有用。
https://github.com/lwcolton/falcon-cors 应该适合你。要测试它,您可以只允许所有来源使用这样的东西(我正在使用另一个 python 框架,所以我没有测试这个确切的猎鹰扩展)
cors = CORS(allow_all_origins=True, allow_all_headers=True)
api = falcon.API(middleware=[cors.middleware])
编辑:添加 allow_all_headers=如评论中所讨论的那样。
我正在尝试从带有简单表单字段的 NEXTjs 前端向位于同一服务器上的后端发送 POST 请求,该服务器是使用 Falcon 的 python 脚本图书馆。 python 脚本本身是 Gunicorn 的 运行 并在 8080 端口上侦听。
两个代码 运行 都很好,没有错误,但是当我尝试提交表单时,我得到的只是一个 415 错误,这似乎表明我正在尝试发送到 API不是受支持的媒体类型,但是正如 answer
中所指出的Falcon has out of the box support for requests with Content-Type: application/json
由于网页和服务器托管在同一个 VPS 我也尝试在获取调用中使用 127.0.0.1 地址但也没有成功(后端 API 事实上甚至没有回应)
这是后端代码:
#!/usr/bin/env python
# coding=utf-8
import time
import falcon
import json
class Resource(object):
def on_post(self, req, resp, **kwargs):
request_body = req.media
print('POST Request: {}'.format(req))
print('Request body: {}'.format(request_body))
start = time.time()
resp.body = json.dumps({
'count_identical_pairs': count_identical_pairs(request_body),
'computation_time': int((time.time() - start) * 1000)
})
def count_identical_pairs(integers_array):
total = 0
count = dict()
# Type checking
if not isinstance(integers_array, list):
return -1
# Check if N is within the range [0..100,000]
if len(integers_array) > 100000:
return -2
for integer in integers_array:
# Check if each element of the array is within the range [−1,000,000,000..1,000,000,000]
if integer not in range(-1000000000, 1000000000):
return -3
if str(integer) not in count:
count[str(integer)] = 1
else:
count[str(integer)] += 1
for key, value in count.items():
total += value * (value - 1) / 2
return total
api = application = falcon.API()
api.add_route('/count_identical_pairs', Resource())
这是前端:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
class Index extends React.Component {
constructor() {
super();
this.state = {
input_array: [],
};
this.onSubmit = this.onSubmit.bind(this);
this.myHeaders = new Headers();
}
onChange = evt => {
// This triggers everytime the input is changed
this.setState({
[evt.target.name]: evt.target.value,
});
};
onSubmit = evt => {
evt.preventDefault();
console.log('this.state.input_array = ' + this.state.input_array);
console.log('JSON.stringify(this.state.input_array) = ' + JSON.stringify(this.state.input_array));
// Making a post request with the fetch API
// Test payload [1, 7, 7, 5, 7, 5, 6, 1]
fetch('http://vps638342.ovh.net:8080/count_identical_pairs', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=utf-8'
},
mode: 'no-cors', // Security hazard?
body: JSON.stringify(this.state.input_array),
redirect: 'follow'
})
.then(response => response.text())
.then(data => console.log('Data: ' + data))
.catch(error => console.log('Error: ' + error))
};
render() {
return (
<form onSubmit={this.onSubmit} >
<input
name="input_array"
type="text"
id="name"
value={this.state.input_array}
onChange={this.onChange}>
</input>
<input type="submit" />
</form>
);
};
}
ReactDOM.render(<Index />, document.getElementById("root"));
编辑 1: 我已经用 Postman 测试了 python 后端 API,我可以看到它已经运行良好,正如你所看到的图为:
在你的 falcon 服务器中启用 CORS 并在你的 javascript 中删除 'no-cors' 标志,前几天对我有用。
https://github.com/lwcolton/falcon-cors 应该适合你。要测试它,您可以只允许所有来源使用这样的东西(我正在使用另一个 python 框架,所以我没有测试这个确切的猎鹰扩展)
cors = CORS(allow_all_origins=True, allow_all_headers=True)
api = falcon.API(middleware=[cors.middleware])
编辑:添加 allow_all_headers=如评论中所讨论的那样。