Go语言的创建HTTP服务器

通过hello World Web服务器宣告你的存在

标准库存中的net/http包提供了多种创建HTTP服务器的方法,它还提供了一个基本路由器。

使用Go语言编写的基础HTTP服务器,程序清单如下:

package main

import (
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello World\n"))
}

func main() {
	http.HandleFunc("/", helloWorld)
	http.ListenAndServe(":8000", nil)
}

运行结果,命令行内容一直没出来,在“http://localhost:8000/”网页上出现一句话:“Hello World”。

使用方法HandleFunc创建路由。这个方法接受一个模式和一个函数,其中前者描述了路径,而后者指定如何对发送到该路径的请求做出响应。

为响应客户端,使用方法ListenAndServe来启动一个服务器,这个服务器监听localhost和端口8000.

查看请求和响应

curl是一款用于发起HTTP请求的命令行工具。需要安装curl.

输入命令行如下:

curl --version

代码如下:

curl 7.77.0 (x86_64-apple-darwin21.0) libcurl/7.77.0 (SecureTransport) LibreSSL/2.8.3 zlib/1.2.11 nghttp2/1.42.0
Release-Date: 2021-05-26
Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: alt-svc AsynchDNS GSS-API HSTS HTTP2 HTTPS-proxy IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL UnixSockets

使用curl发出请求

安装curl后,就可在开发和调试Web服务器时使用它。不使用Web浏览器,而使用curl来向Web服务器发送各种请求以及查看响应。

打开终端并运行这个服务器,代码如下:

go run main.go

再打开另一个终端,执行下面的命令,其中的选项-is指定打印报头。如下:

curl -is http://localhost:8000

运行结果如下:

HTTP/1.1 200 OK
Date: Mon, 31 Jan 2022 14:10:10 GMT
Content-Length: 12
Content-Type: text/plain; charset=utf-8

Hello World

这个响应使用的协议为HTTP 1.1,状态码为200 。

报头Date详细地描述了响应的发送时间。

报头Content-Length详细地指出了响应的长度,这里是12字节。

报头Content-Type指出了内容的类型以及使用的编码。在这里,响应的内容类型为text/plain,是使用utf-8进行编码的。

最后输出的是响应体,这里是Hello World。

详谈路由:

HandleFunc用于注册对URL地址映射进行响应的函数。简单地说着,HandleFunc创建一个路由表,让HTTP服务器能够正确地做出响应。

http.HandleFunc("/",helloworld)
http.HandleFunc("/users/",usersHandler)
http.HandleFunc("/projects/",projectsHandler)

每当用户向/发出请求时,都将调用函数helloWorld,每当用户向/users/发出请求时,都将调用函数sersHandler,依此类推。

使用处理程序函数

处理404错误

默认路由器的行为是将所有没有指定处理程序的请求都定向到/。回到第一个示例,如果用户请求的页面不存在,将调用给/指定的处理程序,从而返回响应Hello World和状态码200 。

代码如下:

package main

import (
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	w.Write([]byte("Hello World\n"))
}

func main() {
	http.HandleFunc("/", helloWorld)
	http.ListenAndServe(":8000", nil)
}

使用go run命令行时,输入另外一个命令行如下:

curl -is http://localhost:8000/asdfa

运行结果如下:

HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=utf-8
X-Content-Type-Options: nosniff
Date: Fri, 04 Feb 2022 07:25:38 GMT
Content-Length: 19

404 page not found

设置报头

处理程序函数可使用ResponseWriter来添加报头。如下所示:

w.Header().Set("Content-Type", "application/json; charset=utf-8")

在响应中添加报头,代码如下:

package main

import (
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	w.Header().Set("Content-Type", "application/json; charset=utf-8")
	w.Write([]byte(`{"hello": "world"}`))
}

func main() {
	http.HandleFunc("/", helloWorld)
	http.ListenAndServe(":8000", nil)
}

使用go run命令行时,输入另外一个命令行如下:

curl -is http://localhost:8000/

运行结果如下:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Fri, 04 Feb 2022 07:33:24 GMT
Content-Length: 18

{"hello": "world"}

响应以不同类型的内容

以不同类型的内容进行响应,代码如下:

package main

import (
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	switch r.Header.Get("Accept") {
	case "application/json":
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Write([]byte(`{"message": "Hello World"}`))
	case "application/xml":
		w.Header().Set("Content-Type", "application/xml; charset=utf-8")
		w.Write([]byte(`Hello World`))
	default:
		w.Header().Set("Content-Type", "application/json; charset=utf-8")
		w.Write([]byte("Hello World\n"))
	}

}

func main() {
	http.HandleFunc("/", helloWorld)
	http.ListenAndServe(":8000", nil)
}

使用go run命令行时,输入另外一个命令行如下:

curl -si -H 'Accept: application/json' http://localhost:8000

运行结果如下:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Date: Fri, 04 Feb 2022 08:31:23 GMT
Content-Length: 26

{"message": "Hello World"}

 使用go run命令行时,输入另外一个命令行如下:

curl -si -H 'Accept: application/xml' http://localhost:8000

命令行的运行结果如下:

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Date: Fri, 04 Feb 2022 08:30:36 GMT
Content-Length: 68

Hello World

响应不同类型的请求

代码如下:

package main

import (
	"net/http"
)

func helloWorld(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	switch r.Method {
	case "GET":
		w.Write([]byte("Received a GET request\n"))
	case "POST":
		w.Write([]byte("Received a POST request\n"))
	default:
		w.WriteHeader(http.StatusNotImplemented)
		w.Write([]byte(http.StatusText(http.StatusNotImplemented)) + "\n")
	}

}

func main() {
	http.HandleFunc("/", helloWorld)
	http.ListenAndServe(":8000", nil)
}

代码错误如下: 

# command-line-arguments
./main.go:19:62: invalid operation: ([]byte)(http.StatusText(http.StatusNotImplemented)) + "\n" (mismatched types []byte and untyped string)

只能删除"\n",这个,才能运行成功。 

使用go run命令行时,输入另外一个命令行如下:

curl -si -X GET http://localhost:8000

命令行的运行结果如下:

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2022 09:01:49 GMT
Content-Length: 23
Content-Type: text/plain; charset=utf-8

Received a GET request

 使用go run命令行时,输入另外一个命令行如下:

curl -si -X POST http://localhost:8000

命令行的运行结果如下:

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2022 09:02:16 GMT
Content-Length: 24
Content-Type: text/plain; charset=utf-8

Received a POST request

获取GET和POST请求中的数据

处理不同请求中的数据,代码如下:

package main

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

func helloWorld(w http.ResponseWriter, r *http.Request) {
	if r.URL.Path != "/" {
		http.NotFound(w, r)
		return
	}
	switch r.Method {
	case "GET":
		for k, v := range r.URL.Query() {
			fmt.Printf("%s:  %s\n", k, v)
		}
		w.Write([]byte("Received a GET request\n"))
	case "POST":
		reqBody, err := ioutil.ReadAll(r.Body)
		if err != nil {
			log.Fatal(err)
		}
		fmt.Printf("%s\n", reqBody)
		w.Write([]byte("Received a POST request\n"))
	default:
		w.WriteHeader(http.StatusNotImplemented)
		w.Write([]byte(http.StatusText(http.StatusNotImplemented)))
	}

}

func main() {
	http.HandleFunc("/", helloWorld)
	http.ListenAndServe(":8000", nil)
}

使用go run命令行时,输入另外一个命令行如下:

curl -si "http://localhost:8000/?foo=1&bar=2"

命令行的运行结果如下:使用curl向这个Web服务器发出包含一些查询参数的GET请求。

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2022 08:55:50 GMT
Content-Length: 23
Content-Type: text/plain; charset=utf-8

Received a GET request

代码的运行结果如下:

bar:  [2]
foo:  [1]

使用go run命令行时,输入另外一个命令行如下:

curl -si POST -d "some data to send" http://localhost:8000/

命令行的运行结果如下:使用curl向这个Web服务器发出POST请求。

HTTP/1.1 200 OK
Date: Fri, 04 Feb 2022 08:59:10 GMT
Content-Length: 24
Content-Type: text/plain; charset=utf-8

Received a POST request

代码的运行结果如下:

some data to send

你可能感兴趣的:(Go语言,服务器,http,golang)