Go Web 与 Nginx 集成 - Go Web 开发实战笔记

4,510 阅读4分钟

概述

Nginx 是一个高性能的 HTTP 和反向代理 web 服务器,尤其擅长处理静态资源(html、js、css、image)。

Go 是一个独立的 HTTP 服务器,当 Go Web 服务器 与 Nginx 服务器集成时, nginx 可以提供其它功能服务,例如访问日志,cc 攻击,静态服务等,Go 只要专注于业务逻辑和功能就好,通过集成 nginx 配置代理就可以实现多应用同时部署。

Nginx 处理静态页面,Go Web 处理路由服务

前端静态网页通过 Nginx 服务器代理访问 Go Web 服务器接口,实现 Web 前后端分离,前后端解耦。
示例代码如下:
Go 服务器:
/goweb/src/nginx/MyServer.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func login(w http.ResponseWriter, r *http.Request)  {
	r.ParseForm()
	username := r.Form["username"][0]
	password := r.Form["password"][0]

	if username == "john" && password == "4321" {
		fmt.Fprintf(w, "success")
	} else {
		fmt.Fprintf(w, "failed")
	}
}

func main() {
	http.HandleFunc("/mylogin", login)

	fmt.Println("服务器已经启动,请在浏览器地址栏中输入 http://localhost:8900")
	// 启动 HTTP 服务,并监听端口号
	err := http.ListenAndServe(":8900", nil)

	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

客户端:
login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<form action="/mylogin" method="post">
    <p>用户名:<input type="text" name="username" /></p>
    <p>密  码:<input type="password" name="password" /></p>
    <p><input type="submit" value="登录" /></p>
</form>
</body>
</html>

把 login.html 静态文件放到 Nginx 服务器的 www 目录下。

Nginx 服务器配置:
nginx.conf

在 nginx.conf 文件里的 http {} 花括号里的 server {} 里添加如下配置:

location /mylogin {
    proxy_pass http://127.0.0.1:8900;
}

配置完成后,启动 Go 服务器 和 启动 Nginx 服务器,然后通过网址访问 Nginx 服务器下的静态登录页面(例如:http://localhost:8080/login.html),尝试登录操作。

本示例原理是:登录页面 通过 Nginx 服务器代理访问 Go 服务接口,实现登录功能。

注意:
本示例可以通过添加前缀实现支持多个路由的 Go Web 服务器集成。只需做如下部分改动:

Go 服务器:
/goweb/src/nginx/MyServer.go

...

func main() {
	http.HandleFunc("/service/mylogin", login)
	
...

客户端:
login.html

..
<body>
<form action="/service/mylogin" method="post">
..

Nginx 服务器配置:
nginx.conf

...
location /service {
    proxy_pass http://127.0.0.1:8900;
}
...

使用 AJAX 提交数据

客户端除了使用 form 表单通过 Nginx 代理向 Go 服务器提交数据外,还可以使用 ajax 提交数据。
示例代码如下:
Go 服务器:
/goweb/src/nginx/MyServer.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func login(w http.ResponseWriter, r *http.Request)  {
	r.ParseForm()
	username := r.Form["username"][0]
	password := r.Form["password"][0]

	if username == "john" && password == "4321" {
		fmt.Fprintf(w, "success")
	} else {
		fmt.Fprintf(w, "failed")
	}
}

func main() {
	http.HandleFunc("/service/login", login)

	fmt.Println("服务器已经启动,请在浏览器地址栏中输入 http://localhost:8900")
	// 启动 HTTP 服务,并监听端口号
	err := http.ListenAndServe(":8900", nil)

	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

客户端:
ajaxlogin.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body>
    <p>用户名:<input type="text" id="username" /></p>
    <p>密  码:<input type="password" id="password" /></p>
    <p><input type="submit" value="登录" onclick="login()" /></p>

<script type="text/javascript">
function login()  {
    $.post('/service/login', {
        username: $("#username").val(),
        password: $("#password").val()
    }, function (data, status) {
        alert('登录是否成功:' + data)
    })
}
</script>
</body>
</html>

Nginx 服务器配置:
nginx.conf

...
location /service {
    proxy_pass http://127.0.0.1:8900;
}
...

启动 Go 服务器 和 启动 Nginx 服务器,然后通过网址访问 Nginx 服务器下的静态登录页面(例如:http://localhost:8080/ajaxlogin.html),尝试登录操作。

用 AJAX 设置页面中动态的部分

go web 除了使用模板(template)来展示网页的动态内容外,还可以通过 AJAX 获取需要显示的内容并展示出来。
示例代码如下:
Go 服务器:
/goweb/src/nginx/MyServer.go

package main

import (
	"fmt"
	"log"
	"net/http"
)

func login(w http.ResponseWriter, r *http.Request)  {
	r.ParseForm()
	username := r.Form["username"][0]
	password := r.Form["password"][0]

	if username == "john" && password == "4321" {
		fmt.Fprintf(w, "success")
	} else {
		fmt.Fprintf(w, "failed")
	}
}

// 用 AJAX 设置页面中的动态部分
func data(w http.ResponseWriter, r *http.Request)  {
	fmt.Fprintf(w, `{"user":"用户名", "pw":"密  码"}`)
}

func main() {
	http.HandleFunc("/service/login", login)
	http.HandleFunc("/service/data", data)

	fmt.Println("服务器已经启动,请在浏览器地址栏中输入 http://localhost:8900")
	// 启动 HTTP 服务,并监听端口号
	err := http.ListenAndServe(":8900", nil)

	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

客户端:
ajaxlogin.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
</head>
<body onload="onload()">
    <p><label id="us"></label>:<input type="text" id="username" /></p>
    <p><label id="pw"></label>:<input type="password" id="password" /></p>
    <p><input type="submit" value="登录" onclick="login()" /></p>

<script type="text/javascript">
function login()  {
    $.post('/service/login', {
        username: $("#username").val(),
        password: $("#password").val()
    }, function (data, status) {
        alert('登录是否成功:' + data)
    })
}
function onload() {
    $.post("service/data", function (data, status) {
        var obj = JSON.parse(data)
        $("#us").text(obj.user)
        $("#pw").text(obj.pw)
    })
}
</script>
</body>
</html>

启动 Go 服务器 和 启动 Nginx 服务器,然后访问页面查看是否能正常显示登录页面。

实现部分动态的页面

可以通过使用 go web 模板(template)来实现部分网页的组件元素在服务器生成,然后通过客户端网页 iframe 嵌套的方式渲染页面,最终实现部分动态的页面。

Go 服务器:
/goweb/src/nginx/MyServer.go

package main

import (
	"fmt"
	"html/template"
	"log"
	"net/http"
)

func login(w http.ResponseWriter, r *http.Request)  {
	r.ParseForm()
	username := r.Form["username"][0]
	password := r.Form["password"][0]

	if username == "john" && password == "4321" {
		fmt.Fprintf(w, "success")
	} else {
		fmt.Fprintf(w, "failed")
	}
}

// 用 AJAX 设置页面中的动态部分
func data(w http.ResponseWriter, r *http.Request)  {
	fmt.Fprintf(w, `{"user":"用户名", "pw":"密  码"}`)
}

// 实现部分动态的页面
func showLoginPage(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("content-type", "text/html;charset=utf-8");
	t,err := template.ParseFiles("./src/nginx/login.tpl")
	if err != nil {
		fmt.Println(err)
	}
	type Data struct {
		User string
		PW string
	}
	data := Data{"用户名", "密码"}
	t.Execute(w,data)
}

func main() {
	http.HandleFunc("/service/login", login)
	http.HandleFunc("/service/data", data)
	http.HandleFunc("/service/showLoginPage", showLoginPage)

	fmt.Println("服务器已经启动,请在浏览器地址栏中输入 http://localhost:8900")
	// 启动 HTTP 服务,并监听端口号
	err := http.ListenAndServe(":8900", nil)

	if err != nil {
		log.Fatal("ListenAndServe:", err)
	}
}

Go 模版:
/goweb/src/nginx/login.tpl

<form action="/service/login" method="post">
    <p>{{ .User }}:<input type="text" name="username" /></p>
    <p>{{ .PW }}:<input type="password" name="password" /></p>
    <p><input type="submit" value="登录" /></p>
</form>

客户端:
login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<p>静态部分</p>
<p>以下是 iframe 动态模版部分:</p>
<iframe src="/service/showLoginPage" frameborder="0"></iframe>
</body>
</html>

启动 Go 服务器 和 启动 Nginx 服务器,然后访问页面查看是否能正常显示登录页面,登录功能是否正常。