Go编写http server

Go编写http server,第1张

        一般来说,理解 HTTP 构建的网络应用,只要关注客户端(clinet)和服务端(server),两个端的交互来自客户端的 request,以及服务端的response。所谓的http服务器,主要在于如何接受客户端的 request,并向服务端返回response。

        Http接收和响应来自客户端的HTTP请求,需要用到golang自带的net.http包,实现动态请求处理。Go语言内置的net/http包提供了HTTP客户端和服务端的实现。

        在接受的过程中路由(router)十分重要,路由url到函数的映射,而这里的路由目的就是为了找到处理器函数(handler),函数将对来自客户端request进行处理,同时构建response返回至服务器

一、路由

路由就是url到函数的映射

route就是你访问一个页面的地址。router就是由一群地址组成的东西。

当访问/healthz路径时,会执行healthz函数

服务器端

       简单来说,对于服务器,当接收到客户端发来的HTTP请求,会根据请求的URL,来找到相应的映射函数,然后执行该函数,并将函数的返回值发送给客户端。

静态资源服务器:url映射函数可以理解为一个文件读取 *** 作

动态资源服务器:url映射可以理解为从数据库读取 *** 作,或是数据处理

客户端

路由的映射函数通常是进行一些DOM的显示和隐藏 *** 作。

二、HTTP请求的接收与处理流程

1、客户端将请求发送到服务器(指定URL)。
2、服务器将请求指向到正确的处理器,然后由该处理器对请求进行处理。
3、处理器处理请求,执行必要的动作。
4、处理器将结果返回给客户端。

三、开始创建http server 

        在理解以上概念后,就要进入http server的创建了。创建httpserver有两个步骤,首先是注册路由,接下来就是其次就是实例化一个server对象,开始监听来自客户端request。

注册路由

通过这个包的http.HandleFunc函数,我们可一个注册一个请求处理器,该函数的第一个参数是请求路径的字符串,第二个参数即为处理请求的函数主体func(ResponseWriter, * Request) 类型的函数。

 http.HandleFunc("/", httpAccessFunc)
http.Handle和http.HandleFunc区分

Go 网络编程:使用 Handler 和 HandlerFunc - 简书

简单的httpserver
package main

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

func main() {
    http.HandleFunc("/healthz", healthz)
    //handle定义请求访问该服务器里的/healthz路径,就有下面healthz去处理,healthz一般为健康检查
    err := http.ListenAndServe(":80", nil)
    if err != nil {
        log.Fatal(err)
        }
    }
//定义handle处理函数,只要该healthz被调用,就会写入ok
func healthz(w http.ResponseWriter, request *http.Request) {
    io.WriteString(w, "ok")
}
编写http server

要求:

1、接收客户端 request,并将 request 中带的 header 写入 response header

2、读取当前系统的环境变量中的 VERSION 配置,并写入 response header

3、Server 端记录访问日志包括客户端 IP,HTTP 返回码,输出到 server 端的标准输出

4、当访问 localhost/healthz 时,应返回 200

package main

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

func main() {
	HttpServerStart(8080)
	log.Fatal(http.ListenAndServe("localhost:8000", nil))
}

func HttpServerStart(port int) {
	log.SetPrefix("Info:")                  //为每条日志文本前增加一个info:前缀
	log.SetFlags(log.Ldate | log.Llongfile) //可以获取当前设置的选项,Ldate:输出当地时区的日期;Llongfile:输出长文件名+行号

	http.HandleFunc("/", httpAccessFunc) //http.HandleFunc接收两个参数,一个是路由匹配的字符串,另外一个是 func(ResponseWriter, *Request) 类型的函数
	http.HandleFunc("healthz", healthzFunc)

	err := http.ListenAndServe(":"+strconv.Itoa(port), nil)
	if err != nil {
		log.Fatal(err) //输出日志后,调用os.Exit(1)退出程序
	}
}

func healthzFunc(w http.ResponseWriter, r *http.Request) {
	HealthzCode := "200"
	w.Write([]byte(HealthzCode))
}

func httpAccessFunc(w http.ResponseWriter, r *http.Request) {
	if len(r.Header) > 0 {
		for k, v := range r.Header {
			log.Printf("%s=%s", k, v[0])

			//1. request header写入response header
			w.Header().Set(k, v[0])
		}
	}

	log.Printf("\n\n\n")

	r.ParseForm() //解析所有请求数据,否则无法获取数据
	if len(r.Form) > 0 {
		for k, v := range r.Form {
			log.Printf("%s=%s", k, v[0])
		}
	}
	log.Printf("\n\n\n")

	os.Setenv("VERSION", "JDK version 1.11.0") //设置环境值的值

	//2. 获取环境变量"VERSION"
	name := os.Getenv("VERSION")
	log.Printf("VERSION Env: ", name)

	log.Printf("\n\n\n")

	//3.获取Client IP,并且打印出来
	ip, _, err := net.SplitHostPort(r.RemoteAddr)
	if err != nil {
		fmt.Println("err:", err)
	}

	if net.ParseIP(ip) != nil {
		fmt.Println("ip ===>>%s\n", ip)
		log.Println(ip)
	}

	fmt.Println("http Status Code ===>>%s\n", http.StatusOK)
	log.Println(http.StatusOK)

	//response响应
	w.WriteHeader(http.StatusOK)

	w.Write([]byte("Server Access,Success!"))
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/994175.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存