Golang:使用net/http实现一个简易的http服务器

文档

1、实现一个简易的服务端

go 复制代码
package main

import (
    "fmt"
    "net/http"
)

// 请求处理函数
func helloHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("hello world!"))
}

func main() {

    // 路由
    http.HandleFunc("/", helloHandler)

    // 启动服务
    fmt.Printf("http server starting at http://127.0.0.1:9090\n")

    err := http.ListenAndServe(":9090", nil)

    if err != nil {
        fmt.Printf("http server failed, err:%v\n", err)
        return
    }
}

请求示例

bash 复制代码
$ curl http://127.0.0.1:9090/
hello world!

示例

2、实现一个类似 https://httpbin.org/的服务,返回请求的信息

go 复制代码
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
    "strings"
)

type Result struct {
    Args    map[string]string      `json:"args"`
    Headers map[string]string      `json:"headers"`
    Form    map[string]string      `json:"form"`
    Json    map[string]interface{} `json:"json"`
    Method  string                 `json:"method"`
    Data    string                 `json:"data"`
    Url     string                 `json:"url"`
    Origin  string                 `json:"origin"`
}

func echoHandler(w http.ResponseWriter, r *http.Request) {
    defer r.Body.Close()

    ret := &Result{}
    ret.Method = r.Method
    ret.Origin = r.RemoteAddr

    // 完整url
    scheme := "http://"
    if r.TLS != nil {
        scheme = "https://"
    }

    ret.Url = strings.Join([]string{scheme, r.Host, r.RequestURI}, "")

    // raw data
    data, _ := io.ReadAll(r.Body)
    ret.Data = string(data)

    // form
    // r.ParseForm()
    // ret.Form = make(map[string]string)
    // for key, _ := range r.PostForm {
    //  ret.Form[key] = r.PostForm.Get(key)
    // }

    // 通过raw data解析
    ret.Form = make(map[string]string)
    form, err := url.ParseQuery(string(data))
    if err != nil {
        for key, _ := range form {
            ret.Form[key] = form.Get(key)
        }
    }

    // json
    ret.Json = make(map[string]interface{})
    json.Unmarshal(data, &ret.Json)

    // args
    ret.Args = make(map[string]string)
    for key, _ := range r.URL.Query() {
        ret.Args[key] = r.URL.Query().Get(key)
    }

    // header
    ret.Headers = make(map[string]string)

    for key, _ := range r.Header {
        ret.Headers[key] = r.Header.Get(key)
    }

    body, _ := json.Marshal(ret)
    w.Write(body)
}

func main() {

    // 路由
    http.HandleFunc("/", echoHandler)

    // 启动服务
    fmt.Printf("http server starting at http://127.0.0.1:9090\n")

    err := http.ListenAndServe(":9090", nil)

    if err != nil {
        fmt.Printf("http server failed, err:%v\n", err)
        return
    }
}

注意:由于请求体只能读取一次,所以form和rawData只能取到一个

通过客户端发起请求

go 复制代码
package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io"
    "net/http"
    "net/url"
)

func main() {
    targetUrl := "http://127.0.0.1:9090"

    // url args
    u, _ := url.ParseRequestURI(targetUrl)

    params := url.Values{}
    params.Set("name", "Tom")
    params.Set("age", "18")

    u.RawQuery = params.Encode() // URL encode

    // json
    data := make(map[string]interface{})
    data["name"] = "Tom"
    data["age"] = 12

    resqdata, _ := json.Marshal(data)

    client := &http.Client{}
    req, _ := http.NewRequest("POST", u.String(), bytes.NewReader(resqdata))

    // header
    req.Header.Add("X-Token", "token")
    req.Header.Add("Content-Type", "application/json")

    resp, _ := client.Do(req)
    defer resp.Body.Close()

    body, _ := io.ReadAll(resp.Body)
    fmt.Println(string(body))

}

返回结果

json 复制代码
{
    "args": {
        "age": "18",
        "name": "Tom"
    },
    "headers": {
        "Accept-Encoding": "gzip",
        "Content-Length": "23",
        "Content-Type": "application/json",
        "User-Agent": "Go-http-client/1.1",
        "X-Token": "token"
    },
    "form": {},
    "json": {
        "age": 12,
        "name": "Tom"
    },
    "method": "POST",
    "data": "{\"age\":12,\"name\":\"Tom\"}",
    "url": "http://127.0.0.1:9090/?age=18&name=Tom",
    "origin": "127.0.0.1:62103"
}

可以看到,我们的服务端可以正确获取到请求的参数信息和json请求体,以及请求头部信息

【参考 】

  1. 深入探索Go语言net/http包:构建高性能的Web服务
  2. Golang:发起http请求-GET带参数、POST发送Form和JSON数据
相关推荐
Apifox.3 小时前
什么是 HTTP POST 请求?初学者指南与示范
后端·http·学习方法·web
一颗星的征途5 小时前
宝塔-Linux模板常用命令-centos7
linux·运维·服务器
H-J-L5 小时前
Web基础与HTTP协议
前端·http·php
super_Dev_OP6 小时前
Web3 ETF的主要功能
服务器·人工智能·信息可视化·web3
象野VH6 小时前
HTTPS数字证书验证论述
网络协议·http·https
开开心心kai6 小时前
不花钱如何让网站启用HTTPS访问
网络·网络协议·安全·http·https
小梁不秃捏6 小时前
计算机网络之以太网
服务器·计算机网络·信息与通信
AllenLeungX6 小时前
Linux 安装 sftp
linux·运维·服务器
嘉木996 小时前
https创建证书
网络协议·http·https
modelsetget7 小时前
使用 HTTPS 已成为网站的标配了
网络协议·http·https