参数输入 参考示例
在 IHttpCore 中的参数,可以有以下的写法
内置类型
在 IWebCore 种,有一系列的内置类型可以直接引用这些类型分别为:
IRequest
- 表示整个引用
- 写入参数必须是引用的形式,如果直接引用会报错
- 可以是非常量引用,也可以是常量引用。
- 常量引用将限制获取的内容仅为请求信息,为非修改的内容。
- 非常量引用可以获取更多的信息。
- 举例如下:
| #pragma once
#include "http/controller/IHttpControllerInterface.h"
class ArgumentTypeController : public IHttpControllerInterface<ArgumentTypeController, true>
{
Q_GADGET
$AsController(ArgumentTypeController)
public:
ArgumentTypeController();
$GetMapping(emptyRequest)
QString emptyRequest();
$GetMapping(irequestRef)
QString irequestRef(IRequest& request);
$GetMapping(constIRequestRef)
QString constIRequestRef(const IRequest& request);
// $GetMapping(irequest) // this is not valid
QString irequest(IRequest request);
};
|
IResponse
| $GetMapping(iresponseRef)
QString iresponseRef(IResponse& response)
{
response.setHeader("hello", "world");
return "hello world";
}
|
IHttpCookieJar
- 这个是对 cookie 信息的管理
- 包括 请求中带入的cookie, 和响应给客户的cookie
- 举例如下:
| // hello:world, qichu:begining
$GetMapping(cookieJar)
QString cookieJar(IHttpCookieJar& jar){
QString ret;
auto reqCookieKeys = jar.requestCookieKeys();
ret.append(QString::fromStdString(reqCookieKeys.join(",")));
if(jar.getRequestCookies("hello").size() == 0){
qFatal("error");
}
auto reqCookies = jar.requestCookies();
for(auto val : reqCookies.keys()){
ret.append(val.toQString()).append(",").append(reqCookies.value(val).toQString());
}
auto cookie = jar.getRequestCookie("hello");
if(cookie.m_value != "world"){
return "error";
}
return ret;
}
|
| def test_cookieJar():
url = serverAddress + "/cookie/cookieJar"
response = requests.get(url, cookies={"hello":"world", "qichu":"begining"})
assert response.status_code == 200
print(response.text)
|
| $GetMapping(headerJar)
QString headerJar(IHttpHeaderJar& jar){
auto headers = jar.requestHeaderKeys();
if(!jar.containRequestHeaderKey("hello")){
qFatal("error");
}
jar.addResponseHeader("hello", "world");
if(!jar.containResponseHeaderKey("hello")){
qFatal("error");
}
jar.deleteReponseHeader("hello");
if(jar.containResponseHeaderKey("hello")){
qFatal("error");
}
auto& header = jar.responseHeaders();
header.insert("j", "k");
if(!jar.containResponseHeaderKey("j")){
qFatal("error");
}
if(header.value("j") != "k"){
qFatal("error");
}
header.remove("j");
if(jar.containResponseHeaderKey("j")){
qFatal("error");
}
if(jar.responseHeaderKeys().contains("j")){
qFatal("error");
}
return "hello world";
}
|
| def test_headerJar():
url = serverAddress + "/header/headerJar"
headers = {
"hello": "world",
"abcd" : "efgh"
}
response = requests.get(url, headers=headers)
assert response.status_code == 200
assert response.headers.get("Server") == "IWebCore"
assert response.headers.get("Content-Type") == "text/plain; charset=UTF-8"
assert response.text == "hello world"
|
IHttpSessionJar
- 这个是对 session 请求会话的管理。
- IWerbCore 内置一个简单的 session 实现,默认使用这个实现。用户可以实现自己的session
- 示例如下:
| $GetMapping(session, /)
QString SessionArgument::session(IHttpSession &session)
{
session.setValue("hello", "world");
return "hello world";
}
$GetMapping(sessionValue)
QString SessionArgument::sessionValue(IHttpSession &session)
{
return session.getValue("hello").toString();
}
|
| def test_session():
session = requests.Session()
val = session.get(serverAddress + "/session")
print(val.cookies)
val2 = session.get(serverAddress + "/session/sessionValue")
print(val2.text)
val.cookies["ISessionId"] == val2.cookies["ISessionId"]
print(val.cookies["ISessionId"])
print(val2.cookies["ISessionId"])
assert val2.text == "world"
|
IHttpMultiPartJar
- 这个是对 multiPart 请求的合集。可以操作获取 multiPart 的所有内容
- 示例如下:
| $PostMapping(multipartjar)
QString multipartjar(const IHttpMultiPartJar& jar){
return QString::fromStdString(jar.getNames().join(","));
}
|
| def test_multipartjar():
val = requests.post(serverAddress + "/BasicArgument/multipartjar", data={"name": "test"}, files={"file": open("ServerConfig.py", "rb")}, verify= False)
assert val.status_code == 200
assert val.text == "name,file"
print(val.text)
print(val.status_code)
|
IHttpCookiePart
| $GetMapping(cookiePart)
QString cookiePart(IHttpCookiePart name){
return name.m_value.toQString();
}
|
| def test_cookiePart():
val = requests.get(serverAddress + "/BasicArgument/cookiePart", cookies={"name": "cookie"}, verify=False)
assert val.status_code == 200
assert val.text == "cookie"
print(val.text)
print(val.status_code)
|
IHttpMultiPart
| $PostMapping(multipart)
QString multipart(const IHttpMultiPart& name, const IHttpMultiPart& file){
Q_UNUSED(name)
return file.m_content.toQString();
}
|
| def test_mulitpart():
val = requests.post(serverAddress + "/BasicArgument/multipart", data={"name": "test"}, files={"file": open("ServerConfig.py", "rb")}, verify= False)
assert val.status_code == 200
assert val.text == open("ServerConfig.py").read()
print(val.text)
print(val.status_code)
|
限定类型
$Path
- 这个限定只允许参数从 path 参数中查找
- 示例1
| $GetMapping(path, path/<path>)
QString path(QString $Path(path)){
return path;
}
|
| def test_path():
url = serverAddress + "/restrictArg/path/hello"
response = requests.get(url)
assert response.status_code == 200
assert len(response.text) != 0
assert response.text == "hello"
print(response.text)
|
| $GetMapping(shortVal, /shortVal/<name>)
QString shortVal(short $Path(name)){
return QString::number(name);
}
|
| def test_shortVal():
url = serverAddress + "/restrictPath/shortVal/123"
response = requests.get(url)
assert response.status_code == 200
assert response.text == "123"
print(response.text)
def test_shortVal_invalid():
url = serverAddress + "/restrictPath/shortVal/invalid"
response = requests.get(url)
assert response.status_code == 400
print(response.text)
def test_shortVal_negative():
url = serverAddress + "/restrictPath/shortVal/-123"
response = requests.get(url)
assert response.status_code == 200
print(response.text)
assert response.text == "-123"
def test_shortVal_over_max():
url = serverAddress + "/restrictPath/shortVal/32768"
response = requests.get(url)
assert response.status_code == 400
print(response.text)
def test_shortVal_under_min():
url = serverAddress + "/restrictPath/shortVal/-32769"
response = requests.get(url)
assert response.status_code == 400
print(response.text)
|
| $GetMapping(stringVal, /stringVal/<name>)
QString stringVal(QString $Path(name)){
return name;
}
$GetMapping(istringVal, /istringVal/<name>)
QString istringVal(IString $Path(name)){
return name.toQString();
}
$GetMapping(qstringVal, /qstringVal/<name>)
QString qstringVal(QString $Path(name)){
return name;
}
$GetMapping(dateVal, /dateVal/<name>)
QString dateVal(QDate $Path(name)){
return name.toString(Qt::DateFormat::ISODate);
}
$GetMapping(timeVal, /timeVal/<name>)
QString timeVal(QTime $Path(name)){
return name.toString(Qt::DateFormat::ISODate);
}
$GetMapping(dateTimeVal, /dateTimeVal/<name>)
QString dateTimeVal(QDateTime $Path(name)){
return name.toString(Qt::DateFormat::ISODate);
}
$GetMapping(byteVal, /byteVal/<name>)
QString byteVal(QByteArray $Path(name)){
return QString(name);
}
|
$Query
| $GetMapping(query)
QString query(QString $Query(query)){
return query;
}
|
| def test_query():
url = serverAddress + "/restrictArg/query?query=hello"
response = requests.get(url)
assert response.status_code == 200
assert len(response.text) != 0
assert response.text == "hello"
print(response.text)
|
$OptQuery
- 该参数允许query 不存在,或者在 query不存在的时候给定 一个默认值
| $GetMapping(optQuery)
QString optQuery(QString $OptQuery(query)){
return query;
}
$GetMapping(optQueryArg)
QString optQueryArg(QString $OptQuery(query, hello)){
return query;
}
|
| def test_optQuery():
url = serverAddress + "/restrictArg/optQuery?query=hello"
response = requests.get(url)
assert response.status_code == 200
assert len(response.text) != 0
assert response.text == "hello"
print(response.text)
def test_optQuery2():
url = serverAddress + "/restrictArg/optQuery?query="
response = requests.get(url)
assert response.status_code == 200
assert response.text == ""
def test_optQueryArg():
url = serverAddress + "/restrictArg/optQueryArg?query=hello"
response = requests.get(url)
assert response.status_code == 200
assert len(response.text) != 0
assert response.text == "hello"
print(response.text)
def test_optQueryArg2():
url = serverAddress + "/restrictArg/optQueryArg"
response = requests.get(url)
assert response.status_code == 200
assert response.text == "hello"
def test_optQueryArg3():
url = serverAddress + "/restrictArg/optQueryArg?query="
response = requests.get(url)
assert response.status_code == 200
assert response.text == ""
|
| $GetMapping(headerTypeInt)
QString headerTypeInt(int $Header(MyInt))
{
return QString::number(MyInt);
}
$GetMapping(headerType)
QString headerType(IString $Header(MyHeader))
{
return MyHeader.toQString();
}
|
| def test_headerType():
val = requests.get(serverAddress + "/BasicArgument/headerType", headers={"MyHeader": "Yuekeyuan"})
print(val.text)
print(val.status_code)
assert val.status_code == 200
assert val.text == "Yuekeyuan"
def test_headerTypeInt():
val = requests.get(serverAddress + "/BasicArgument/headerTypeInt", headers={"MyInt": "123"})
print(val.text)
print(val.status_code)
assert val.status_code == 200
assert val.text == "123"
|
| $GetMapping(optHeader)
QString optHeader(QString $OptHeader(header)){
return header;
}
$GetMapping(optHeaderArg)
QString optHeaderArg(QString $OptHeader(header, hello)){
return header;
}
|
| def test_optHeader():
url = serverAddress + "/restrictArg/optHeader"
headers = {"header": "hello"}
response = requests.get(url, headers=headers)
assert response.status_code == 200
assert len(response.text) != 0
assert response.text == "hello"
print(response.text)
def test_optHeader2():
url = serverAddress + "/restrictArg/optHeader"
response = requests.get(url)
assert response.status_code == 200
assert len(response.text) == 0
assert response.text == ""
def test_optHeaderArg():
url = serverAddress + "/restrictArg/optHeaderArg"
headers = {"header": "hello"}
response = requests.get(url, headers=headers)
assert response.status_code == 200
assert len(response.text) != 0
assert response.text == "hello"
print(response.text)
def test_optHeaderArg2():
url = serverAddress + "/restrictArg/optHeaderArg"
response = requests.get(url)
assert response.status_code == 200
assert len(response.text) == 5
assert response.text == "hello"
|
$Cookie
- 值从 cookie 中查找
- 注意一点,cookie 一个 name 可以对应多个value, 所以这里支持 QStringList 转换
| $GetMapping(cookieString)
QString cookieString(QString $Cookie(name)){
return name;
}
$GetMapping(cookiesString)
QString cookiesString(QStringList $Cookie(names)){
return names.join(",");
}
|
| def test_cookieString():
val = requests.get(serverAddress + "/BasicArgument/cookieString", cookies={"name": "cookie"}, verify=False)
assert val.status_code == 200
assert val.text == "cookie"
print(val.text)
print(val.status_code)
def test_cookiesStrings():
session = requests.Session()
# Set cookies in the session
session.cookies.set('names', 'cookie_value1')
session.cookies.set('names', 'cookie_value2')
val = session.get(serverAddress + "/BasicArgument/cookiesString")
assert val.status_code == 200
# assert val.text == "cookie; name1=cookie1"
print(val.text)
print(val.status_code)
|
$OptCookie
| $GetMapping(optCookie)
QString optCookie(QString $OptCookie(cookie)){
return cookie;
}
$GetMapping(optCookieArg)
QString optCookieArg(QString $OptCookie(cookie, hello)){
return cookie;
}
|
| def test_optCookie():
url = serverAddress + "/restrictArg/optCookie"
response = requests.get(url, cookies={"cookie": "hello"})
assert response.status_code == 200
assert len(response.text) != 0
assert response.text == "hello"
print(response.text)
def test_optCookie2():
url = serverAddress + "/restrictArg/optCookie"
response = requests.get(url)
assert response.status_code == 200
assert len(response.text) == 0
assert response.text == ""
def test_optCookieArg():
url = serverAddress + "/restrictArg/optCookieArg"
response = requests.get(url, cookies={"cookie": "hello"})
assert response.status_code == 200
assert response.text == "hello"
print(response.text)
def test_optCookieArg2():
url = serverAddress + "/restrictArg/optCookieArg"
response = requests.get(url)
assert response.status_code == 200
assert response.text == "hello"
|
$Session
- 从 session 中获取值,没有的话 返回404状态
- TODO:
$OptSession
TODO:
$Json
- 这个比较复杂
- 先不解释了,以后可能还会改的
- 具体的决策还没想好
| $PostMapping(boolVal, /boolVal)
QString boolVal(bool $Json(name)){
return name ? "true" : "false";
}
$PostMapping(shortVal, /shortVal)
QString shortVal(short $Json(name)){
return QString::number(name);
}
|
| def test_boolVal():
url = serverAddress + "/restrictJson/boolVal"
response = requests.post(url, json={"name": True})
assert response.status_code == 200
assert response.text == "true"
print(response.text)
def test_boolVal_False():
url = serverAddress + "/restrictJson/boolVal"
response = requests.post(url, json={"name": False})
assert response.status_code == 200
assert response.text == "false"
print(response.text)
def test_boolVal_None():
url = serverAddress + "/restrictJson/boolVal"
response = requests.post(url, json={"name": None})
assert response.status_code == 400
def test_boolVal_int():
url = serverAddress + "/restrictJson/boolVal"
response = requests.post(url, json={"name": 1})
assert response.status_code == 200
assert response.text == "true"
print(response.text)
|
| $PostMapping(jsonPointerVal)
QString jsonPointerVal(int $Json(name, value)){
return QString::number(name);
}
|
| def test_jsonPointerVal():
url = serverAddress + "/restrictJson/jsonPointerVal"
response = requests.post(url, json={"name": {"value": 123}})
assert response.status_code == 200
assert response.text == "123"
print(response.text)
url = serverAddress + "/restrictJson/jsonPointerVal"
response = requests.post(url, json={"name": {"value": "hello"}})
assert response.status_code == 400
print(response.text)
url = serverAddress + "/restrictJson/jsonPointerVal"
response = requests.post(url, json={"name": {"value": 123}, "age": {"value": 456}})
assert response.status_code == 200
assert response.text == "123"
print(response.text)
url = serverAddress + "/restrictJson/jsonPointerVal"
response = requests.post(url, json={"name": {"value": "123"}, "age": {"value": "invalid"}})
assert response.status_code == 400
print(response.text)
|
$Body
- 该标签会直接引用 body 的内容,并且将之转换成合适的类型
| $PostMapping(bodyType)
QString bodyType(QString $Body(body)){
return body;
}
|
| def test_BodyType():
val = requests.post(serverAddress + "/BasicArgument/bodyType", data={"name": "test"})
print(val.text)
print(val.status_code)
assert val.status_code == 200
assert val.text == "name=test"
|
直接类型
IJson
- 这个类型和 $Json 限定类型不同的是,限定类型获取的是 json 中的内容,而 IJson 没有限定,获取的是完整的 json 内容。
其他类型
-
数值类型,时间类型,字符串类型
-
获取该值的顺序是
-
body 内容,包括 plainText, form data, json 和 multipart 内容
- query 中的内容
- path 中的内容
- cookie 的内容
- session 的内容
-
header 的内容
-
所以,这个是一个危险的操作,因为如果你想获取 path 中的内容,而query 中有一个同名的内容,那么你获取的内容就和预期的不一样。
Bean 相关类型
IWebCore 支持 Bean 和复合类型
MyBean 定义
| #pragma once
#include "core/bean/IBeanInterface.h"
class MyBean : public IBeanInterface<MyBean>
{
Q_GADGET
public:
MyBean() = default;
MyBean(int id, QString name){
this->index = id;
this->name = name;
}
$BeanField(int, index, 100)
$BeanField(QString, name, "yuekeyuan")
};
|
Bean
| $PostMapping(beanData)
std::string beanData(MyBean bean){
return bean.toJson().dump();
}
|
| def test_beanData():
val = requests.post(serverAddress + "/BasicArgument/beanData", json={"index": 102, "name": "yueqichu"})
print(val.text)
print(val.status_code)
assert val.text == '{"index":102,"name":"yueqichu"}'
assert val.status_code == 200
def test_beanData2():
val = requests.post(serverAddress + "/BasicArgument/beanData", json=[{"index": 102, "name": "yueqichu"},{"index": 103, "name": "yuekeyuan"}])
print(val.text)
print(val.status_code)
# assert val.text == '{"index":102,"name":"yueqichu"}'
assert val.status_code == 500
|
List\
QList\
| $PostMapping(beanDatas)
std::string beanDatas(QList<MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
| def test_beanDataQList():
val = requests.post(serverAddress + "/BasicArgument/beanDatas", json=[{"index": 102, "name": "yueqichu"},{"index": 103, "name": "yuekeyuan"}])
print(val.text)
print(val.status_code)
assert val.json() == [{"index": 102, "name": "yueqichu"}, {"index": 103, "name": "yuekeyuan"}]
assert val.status_code == 200
|
std::list\
| $PostMapping(beanDataStdList)
std::string beanDataStdList(std::list<MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
| def test_beanDataStdList():
val = requests.post(serverAddress + "/BasicArgument/beanDataStdList", json=[{"index": 102, "name": "yueqichu"},{"index": 103, "name": "yuekeyuan"}])
print(val.text)
print(val.status_code)
assert val.json() == [{"index": 102, "name": "yueqichu"}, {"index": 103, "name": "yuekeyuan"}]
assert val.status_code == 200
|
QVector\
std::vector\
Map
QMap\
| $PostMapping(beanDataQMapStdString)
std::string beanDataQMapStdString(QMap<std::string, MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
| def test_beanDataQMapStdString():
val = requests.post(serverAddress + "/BasicArgument/beanDataQMapStdString", json={
"fei" :{"index": 102, "name": "yueqichu"}, "yue": {"index": 103, "name": "yuekeyuan"}})
print(val.text)
print(val.status_code)
assert val.json() == {"fei":{"index":102,"name":"yueqichu"},"yue":{"index":103,"name":"yuekeyuan"}}
assert val.status_code == 200
|
QMap\
| $PostMapping(beanDataQMap)
std::string beanDataQMap(QMap<IString, MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
```python'
def test_beanDataQMap():
val = requests.post(serverAddress + "/BasicArgument/beanDataQMap", json={
"fei" :{"index": 102, "name": "yueqichu"}, "yue": {"index": 103, "name": "yuekeyuan"}})
print(val.text)
print(val.status_code)
assert val.json() == {"fei":{"index":102,"name":"yueqichu"},"yue":{"index":103,"name":"yuekeyuan"}}
assert val.status_code == 200
| #### QMap<QString, Bean>
```cpp
$PostMapping(beanDataQMapQString)
std::string beanDataQMapQString(QMap<QString, MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
| def test_beanDataQMapQString():
val = requests.post(serverAddress + "/BasicArgument/beanDataQMapQString", json={
"fei" :{"index": 102, "name": "yueqichu"}, "yue": {"index": 103, "name": "yuekeyuan"}})
print(val.text)
print(val.status_code)
assert val.json() == {"fei":{"index":102,"name":"yueqichu"},"yue":{"index":103,"name":"yuekeyuan"}}
assert val.status_code == 200
|
std::map\
| $PostMapping(beanDataStdMapQString)
std::string beanDataStdMapQString(std::map<QString, MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
| def test_beanDataStdMapQString():
val = requests.post(serverAddress + "/BasicArgument/beanDataStdMapQString", json={
"fei" :{"index": 102, "name": "yueqichu"}, "yue": {"index": 103, "name": "yuekeyuan"}})
print(val.text)
print(val.status_code)
assert val.json() == {"fei":{"index":102,"name":"yueqichu"},"yue":{"index":103,"name":"yuekeyuan"}}
assert val.status_code == 200
|
std::map\
| $PostMapping(beanDataStdMap)
std::string beanDataStdMap(std::map<IString, MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
| def test_beanDataStdMap():
val = requests.post(serverAddress + "/BasicArgument/beanDataStdMap", json={
"fei" :{"index": 102, "name": "yueqichu"}, "yue": {"index": 103, "name": "yuekeyuan"}})
print(val.text)
print(val.status_code)
assert val.json() == {"fei":{"index":102,"name":"yueqichu"},"yue":{"index":103,"name":"yuekeyuan"}}
assert val.status_code == 200
|
std::map\
| $PostMapping(beanDataStdMapStdString)
std::string beanDataStdMapStdString(std::map<std::string, MyBean> beans){
return IJsonUtil::toJson(beans).dump();
}
|
| def test_beanDataStdMapStdString():
val = requests.post(serverAddress + "/BasicArgument/beanDataStdMapStdString", json={
"fei" :{"index": 102, "name": "yueqichu"}, "yue": {"index": 103, "name": "yuekeyuan"}})
print(val.text)
print(val.status_code)
assert val.json() == {"fei":{"index":102,"name":"yueqichu"},"yue":{"index":103,"name":"yuekeyuan"}}
assert val.status_code == 200
|
复合类型
复合类型, 比如 std::list\ 这种类型, 是由 基础类型 和 container 联合构造而成的。