跳转至

使用GO部署和请求HTTP服务

作为HTTP服务器提供RESTful API

下面的服务器示例实现了如下功能

  1. 基本响应: GET / --> hello, world
  2. 长耗时响应: GET /timeout --> timeout = 5
  3. 流式响应: GET /stream --> Data 0\nData 1\nData 2\nData 3\nData 4\n (当流式响应结束,客户端将触发EOF)
Go
package main

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

func streamHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/plain")

    // 设置缓冲区大小
    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming not supported", http.StatusInternalServerError)
        return
    }

    // 模拟生成数据并发送给客户端
    for i := 0; i < 5; i++ {
        fmt.Fprintf(w, "Data %d\n", i)
        flusher.Flush()             // 刷新缓冲区,将数据发送给客户端
        time.Sleep(1 * time.Second) // 模拟每隔一秒发送一次数据
    }
}

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Write([]byte("hello, world"))
    })

    http.HandleFunc("/timeout", func(w http.ResponseWriter, r *http.Request) {
        time.Sleep(time.Second * 5)
        w.Write([]byte("timeout = 5"))
    })

    http.HandleFunc("/stream", streamHandler)

    http.ListenAndServe(":8000", nil)
}

作为HTTP客户端发起请求

下面的HTTP客户端示例实现了如下功能

  1. 基本请求: GET http://127.0.0.1:8000/ --> hello, world
  2. 长耗时请求: GET http://127.0.0.1:8000/timeout --> timeout = 5(将会超时)
  3. 流式请求(使用resty包): GET http://127.0.0.1:8000/stream --> Data 0\nData 1\nData 2\nData 3\nData 4\n (当流式响应结束,客户端将触发EOF)
Go
package main

import (
    "fmt"
    "io"
    "log"
    "net/http"
    "time"

    "github.com/go-resty/resty/v2"
)

func handleError(err error) {
    if err != nil {
        log.Fatalln(err)
    }
}

func restyStreamDemo() {
    resp, err := resty.New().R().
        SetDoNotParseResponse(true).
        Get("http://127.0.0.1:8000/stream")
    handleError(err)

    rawBody := resp.RawBody()
    defer rawBody.Close()

    buf := make([]byte, 1024)
    for {
        n, err := rawBody.Read(buf)
        if n > 0 {
            fmt.Print(string(buf[:n]))
        }
        if err == io.EOF {
            break
        }
        handleError(err)
    }
}

func baseDemo() {
    req, err := http.NewRequest("GET", "http://127.0.0.1:8000/", nil)
    handleError(err)

    c := &http.Client{}

    resp, err := c.Do(req)
    handleError(err)

    log.Println("Response Code:", resp.StatusCode)
    body, err := io.ReadAll(resp.Body)
    handleError(err)
    log.Println("Response Body:", string(body))
}

func timeoutDemo() {
    req, err := http.NewRequest("GET", "http://127.0.0.1:8000/timeout", nil)
    handleError(err)

    c := &http.Client{
        Timeout: 3 * time.Second,
    }

    _, err = c.Do(req)
    handleError(err) // will panic
}

func main() {
    baseDemo()
    restyStreamDemo()
    timeoutDemo()
}

测试结果

Text Only
// http://127.0.0.1:8000/
2024/04/08 23:20:15 Response Code: 200
2024/04/08 23:20:15 Response Body: hello, world

// http://127.0.0.1:8000/steam
Data 0
Data 1
Data 2
Data 3
Data 4

// http://127.0.0.1:8000/timeout
2024/04/08 23:20:23 Get "http://127.0.0.1:8000/timeout": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
exit status 1

参考