这里主要是学习官网提供的路由方案
一、代码结构
router.h 里是路由代码,主要引入HttpService,用来定义路由地址,并与控制器关联。
#ifndef HV_HTTPD_ROUTER_H
#define HV_HTTPD_ROUTER_H
#include "HttpService.h"
#include "handler/admin.h"
class Router {
public:
// 添加的管理员控制器
static void RegisterAdmin(HttpService& http){
http.POST("/api/v1/admin/checklogin", Admin::checklogin);
};
};
#endif // HV_HTTPD_ROUTER_H
二、控制器
控制器代码里生命周期分成三步:
- preprocessor
- handler
- postprocessor
下面代码展示了从请求的body里取出内容,并转化为json读值的过程。
admin.h
#ifndef HV_HTTPD_ADMIN_H
#define HV_HTTPD_ADMIN_H
#include "HttpMessage.h"
#include <iostream>
/**
* 管理员控制器
**/
class Admin {
public:
// preprocessor => handler => postprocessor
static int preprocessor(HttpRequest* req, HttpResponse* resp) {
req->ParseBody();
resp->content_type = APPLICATION_JSON;
#if 0
// authentication sample code
if (strcmp(req->path.c_str(), "/login") != 0) {
string token = req->GetHeader("token");
if (token.empty()) {
response_status(resp, 10011, "Miss token");
return HTTP_STATUS_UNAUTHORIZED;
}
else if (strcmp(token.c_str(), "abcdefg") != 0) {
response_status(resp, 10012, "Token wrong");
return HTTP_STATUS_UNAUTHORIZED;
}
return 0;
}
#endif
return 0;
}
static int postprocessor(HttpRequest* req, HttpResponse* resp) {
// printf("%s\n", resp->Dump(true, true).c_str());
return 0;
}
/**
* 登陆校验
**/
static int checklogin(HttpRequest* req, HttpResponse* resp){
// printf("接收json %s \n" ,req->json.dump().c_str());
if(req->content_type!=APPLICATION_JSON){
return response_status(resp, HTTP_STATUS_BAD_REQUEST);
}
resp->content_type = APPLICATION_JSON;
hv::Json reqJson =hv::Json::parse(req->body);
string username = reqJson["username"];
string password = reqJson["password"];
if(username.empty() || password.empty()){
response_status(resp, 60204, "密码错误");
return HTTP_STATUS_BAD_REQUEST;
}else if(strcmp(username.c_str(), "admin") != 0){
response_status(resp, 60204, "账号或密码错误");
return HTTP_STATUS_BAD_REQUEST;
}else if(strcmp(password.c_str(), "123456") != 0){
response_status(resp, 60204, "账号或密码错误");
return HTTP_STATUS_BAD_REQUEST;
}else{
// 随便返回一个登陆成功消息
hv::Json ret;
ret["code"] = 20000;
ret["data"] = {{"token","test"},{"avatar","test.png"},{"name",reqJson["username"]}};
resp->json=ret;
return 200;
}
}
private:
static int response_status(HttpResponse* resp, int code = 200, const char* message = NULL) {
resp->Set("code", code);
if (message == NULL) message = http_status_str((enum http_status)code);
resp->Set("message", message);
resp->Set("data","");
resp->DumpBody();
return code;
}
};
#endif // HV_HTTPD_ADMIN_H
三、 启动程序
httpd.cpp采用的是官方example原来内容,基本没有变化,只在最下方把控制器注册稍微改动了一下:
// pidfile
create_pidfile();
// 管理员控制类路由
Router::RegisterAdmin(g_http_service);
g_http_server.service = &g_http_service;
ret = http_server_run(&g_http_server);
return ret;
运行效果:
在 html 文件夹里放入前端代码,即可与控制器后端代码交互。后面有时间时在此基础上完善一下简单的后台框架。