Let's Go
开发 web 服务程序
概述
开发简单 web 服务程序 cloudgo,了解 web 服务器工作原理。
任务目标
- 熟悉 go 服务器工作原理
- 基于现有 web 库,编写一个简单 web 应用类似 cloudgo。
- 使用 curl 工具访问 web 程序
- 对 web 执行压力测试
任务要求
编程 web 服务程序 类似 cloudgo 应用。
- 支持静态文件服务
- 支持简单 js 访问
- 提交表单,并输出一个表格(必须使用模板)
- 使用 curl 测试
- 使用 ab 测试
初探web服务程序
支持静态文件访问
首先我们先设置路由,并在main函数启动端口,这样我们就可以在相应端口下访问网页
func initRoutes(mx *mux.Router, formatter *render.Render) {
webRoot := os.Getenv("WEBROOT")
if len(webRoot) == 0 {
if root, err := os.Getwd(); err != nil {
panic("Could not retrive working directory")
} else {
webRoot = root
//fmt.Println(root)
}
}
}
func main() {
n := NewServer()
n.Run(":3000")
}
然后我们编写静态页面模板index.html
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
Sample Go Web Application!!
<div>
<p class="greeting-id">The ID is {{.ID}}</p>
<p class="greeting-content">The content is {{.Content}}</p>
</div>
</body>
</html>
接着我们设置数据绑定,将数据绑定至我们输出的html页面下
func homeHandler(formatter *render.Render) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
formatter.HTML(w, http.StatusOK, "index", struct {
ID string `json:"id"`
Content string `json:"content"`
}{ID: "8675309", Content: "Hello from Go!"})
}
}
mx.HandleFunc("/", homeHandler(formatter)).Methods("GET")
运行main函数启动端口初始化路由我们就可以完成简单的静态文件访问
进行curl测试
使用ab进行压力测试
支持简单的js访问
为了能支持简单的js访问,我们首先编写js文件hello.js
$(document).ready(function() {
$.ajax({
url: "/api/test"
}).then(function(data) {
$('.greeting-id').append(data.id);
$('.greeting-content').append(data.content);
});
});
这段代码非常简单,输出了一个 匿名结构 ,并 JSON (JavaScript Object Notation) 序列化输出。
func apiTestHandler(formatter *render.Render) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
formatter.JSON(w, http.StatusOK, struct {
ID string `json:"id"`
Content string `json:"content"`
}{ID: "8675309", Content: "Hello from Go!"})
}
}
mx.HandleFunc("/api/test", apiTestHandler(formatter)).Methods("GET")
mx.PathPrefix("/static").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir(webRoot+"/assets/"))))
运行main函数启动端口初始化路由我们就可以通过api/test读取相应的json数据
进行curl测试
使用ab进行压力测试
提交表单并输出表格
我们首先编写带表格的模板方便接收提交的表单进行数据绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Welcome</title>
</head>
<body>
<table border="1">
<tr>
<td>username</td>
<td>{{.Username}}</td>
</tr>
<tr>
<td>password</td>
<td>{{.Password}}</td>
</tr>
</table>
</body>
</html>
接着编写提交表单的界面
<html>
<head><title></title></head>
<body>
<form action="http://localhost:9090/" method="post">
用户名:<input type="text" name="username">
密 码:<input type="text" name="password">
<input type="submit" value="登录">
</form>
</body>
</html>
接着我们编写login函数完成表单提交任务
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method)
if r.Method == "GET" {
t, _ := template.ParseFiles("login.html")
// func (t *Template) Execute(wr io.Writer, data interface{}) error {
t.Execute(w, nil)
} else {
r.ParseForm()
fmt.Println("username:", r.Form["username"])
fmt.Println("password:", r.Form["password"])
}
}
在提交完表单后,我们需要解析表单提交url传递的参数,并将其绑定到我们的模板上
func urlAnalysis(w http.ResponseWriter, r *http.Request) {
// 解析url传递的参数
r.ParseForm()
for k, v := range r.Form {
fmt.Println("key:", k)
// join() 方法用于把数组中的所有元素放入一个字符串。
// 元素是通过指定的分隔符进行分隔的
fmt.Println("val:", strings.Join(v, ""))
}
// 输出到客户端
name := r.Form["username"]
pass := r.Form["password"]
tem,err := template.ParseFiles("table.html")
if err != nil{
fmt.Println("读取文件失败,err", err)
return
}
var user User
user.Username = name[0]
user.Password = pass[0]
tem.Execute(w, user)
}
运行函数,进入本地9090端口
输入用户名和密码进行登录得到提交表单的表格