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数据
相关推荐
云飞云共享云桌面3 分钟前
东莞智能装备工厂10个solidworks共享一台服务器做装配体设计
运维·服务器·网络·云计算·电脑
xuxie998 分钟前
N12 arm-clk时钟
运维·服务器·网络
香芋超新星21 分钟前
服务器根目录爆满导致 PyTorch 安装失败(Errno 28 No space left on device)
服务器·pytorch·深度学习
jessecyj23 分钟前
Nginx中$http_host、$host、$proxy_host的区别
运维·nginx·http
soldierluo27 分钟前
openclaw接入企业微信
服务器·人工智能·windows·企业微信
Alphapeople30 分钟前
安装华为CANN模型导出工具
linux·运维·服务器
Yupureki37 分钟前
《Linux系统编程》16.进程间通信-共享内存
linux·运维·服务器·c语言·数据结构·c++
嵌入式小能手38 分钟前
飞凌嵌入式ElfBoard-环境变量之添加修改环境变量setenv
服务器·前端·javascript
ayaya_mana43 分钟前
NPS 内网穿透,二次开源版新增多种连接协议(含 P2P 配置)
linux·运维·服务器·网络协议·内网穿透·p2p·nps
2401_877274241 小时前
System V 共享内存:Linux 最高性能 IPC 的设计与实现
linux·服务器·c语言