>  기사  >  백엔드 개발  >  golang은 http 요청을 캡슐화합니다.

golang은 http 요청을 캡슐화합니다.

PHPz
PHPz원래의
2023-05-11 12:00:07614검색

인터넷이 발전하면서 HTTP 요청은 백엔드 개발의 표준이 되었으며 프런트엔드에서 네트워크 요청을 시작하는 방법이기도 합니다. Golang의 표준 라이브러리에는 완전한 HTTP 클라이언트와 서버를 제공하는 내장 net/http 패키지가 있습니다. 그러나 HTTP 요청 라이브러리를 캡슐화하면 개발 프로세스 중에 HTTP 요청을 보다 효율적이고 편리하게 시작할 수 있습니다. 이 기사에서는 Golang HTTP 요청 라이브러리를 캡슐화하는 방법에 대해 설명합니다.

1. 요구 사항 분석

HTTP 요청 라이브러리를 패키징하기 전에 라이브러리를 더 잘 설계하고 개발하기 위해 몇 가지 요구 사항과 기능을 명확히 해야 합니다. 여기에서 우리는 완전한 HTTP 요청 라이브러리가 다음 기능을 가져야 한다고 믿습니다:

  1. GET, POST, PUT 및 DELETE와 같은 HTTP 메서드를 지원합니다.
  2. 요청 헤더, 요청 본문 및 요청 매개변수 설정을 지원합니다.
  3. 시간 초과 및 재시도 시간 설정을 지원합니다.
  4. 다른 데이터 유형으로의 반환 값 형식을 지원합니다.

위의 요구 사항과 기능을 기반으로 HTTP 요청 라이브러리 설계 및 개발을 시작할 수 있습니다.

2. 설계 및 구현

2.1 설계 포인트

HTTP 요청 라이브러리를 설계할 때 가용성이 높고 확장 가능하며 사용하기 쉬운 요청 라이브러리를 달성하기 위해 몇 가지 핵심 사항을 고려해야 합니다. 특히 다음 측면을 고려해야 합니다.

  1. 네트워크 문제.

HTTP 요청을 할 때 연결 시간 초과, 요청 시간 초과 등의 네트워크 문제를 고려해야 합니다. 따라서 우리의 HTTP 요청 라이브러리는 연결 시간 초과 및 요청 시간 초과 설정을 지원해야 합니다.

  1. 예외 처리.

HTTP 요청을 시작하면 네트워크 예외, 반환 값 예외 등 예측할 수 없는 다양한 예외가 발생할 수 있습니다. HTTP 요청 라이브러리를 더욱 강력하게 만들려면 http 상태 코드, 예외 정보 등을 기반으로 이러한 예외를 처리해야 합니다.

  1. RESTful API 지원.

RESTful API에서는 JSON 데이터나 폼 데이터 등을 제출해야 하는 경우가 많습니다. 따라서 HTTP 요청 라이브러리에서는 이러한 데이터의 제출 및 구문 분석을 지원해야 합니다.

  1. 반환 값 처리.

HTTP 요청을 시작한 후에는 반환 값을 처리해야 합니다. 일반적으로 서로 다른 API 인터페이스의 반환 값 형식이 다를 수 있으므로 API 인터페이스의 반환 값 형식에 따라 해당 처리를 지원해야 합니다.

2.2 구현 프로세스

위의 설계 포인트를 기반으로 HTTP 요청 라이브러리 구현을 시작할 때 다음 단계를 따를 수 있습니다.

  1. HTTP 요청의 구조를 정의합니다.

HTTP 요청 라이브러리를 캡슐화할 때 HTTP 요청 정보를 캡슐화해야 합니다. 특히, HTTP 요청에 필요한 정보를 저장하고 전송하기 위해 HTTP 요청 구조를 정의할 수 있습니다. 다음은 HTTP 요청 구조의 예입니다.

type Request struct {
    URL        string
    Method     string
    Headers    map[string]string
    Body       []byte
    Params     map[string]string
    Timeout    int
    RetryTimes int
}
  1. 는 HTTP 요청을 시작합니다.

HTTP 요청 구조를 정의한 후에는 Golang의 표준 라이브러리를 통해 HTTP 요청을 보낼 수 있습니다.

예를 들어, http.NewRequest() 메서드를 사용하여 HTTP 요청을 생성할 수 있습니다:

req, err := http.NewRequest(req.Method, req.URL, bytes.NewBuffer(req.Body))
if err != nil {
    return nil, err
}

http.Transport의 DialContext() 메서드를 사용하여 연결 시간 초과 및 요청 시간 초과를 설정합니다:

client := &http.Client{
        Transport: &http.Transport{
            DialContext: (&net.Dialer{
                Timeout:   time.Duration(req.Timeout) * time.Second,
                KeepAlive: time.Duration(req.Timeout) * time.Second,
            }).DialContext,
            MaxIdleConns:        100,              // http.ConnectionPool数量
            IdleConnTimeout:     90 * time.Second, // http.ConnectionPool中连接的空闲超时时间
            TLSHandshakeTimeout: 10 * time.Second,
            ExpectContinueTimeout: 1 * time.Second,
        }
    }

다음으로 다음을 수행할 수 있습니다. Do( ) 메소드를 사용하면 HTTP 요청을 시작하고 반환 값을 얻습니다.

resp, err := client.Do(req)
if err != nil {
    return nil, err
}

HTTP 요청을 성공적으로 시작한 후에는 악의적인 요청으로 인한 메모리 누수를 방지하기 위해 리소스를 해제해야 합니다.

defer resp.Body.Close()
  1. 예외 처리.

HTTP 요청을 시작할 때 네트워크 예외, 반환 값 예외 등 예측할 수 없는 다양한 예외가 발생할 수 있습니다. 따라서 이러한 예외는 HTTP 요청 라이브러리에서 처리되어야 합니다.

예를 들어 HTTP 상태 코드와 응답 본문을 기반으로 HTTP 요청 예외를 확인할 수 있습니다. 예외가 발생하면 예외 유형에 따라 해당 오류 정보를 반환할 수 있으므로 개발 과정에서 적시에 발견하고 처리할 수 있습니다.

  1. RESTful API 지원.

RESTful API를 호출할 때 JSON 데이터, 양식 데이터 등 다양한 제출 형식을 지원해야 합니다. HTTP 요청 라이브러리를 더욱 다양하게 만들기 위해 ContentType 속성 필드를 추가하여 다양한 제출 형식을 지원할 수 있습니다. 동시에 JSON 데이터를 제출할 때 데이터를 JSON 형식으로 인코딩해야 합니다.

  1. 반환 값 처리.

인터페이스를 호출한 후 반환 값을 처리해야 합니다. 일반적으로 서로 다른 API 인터페이스의 반환 값 형식이 다를 수 있으므로 API 인터페이스의 반환 값 형식에 따라 상위 계층 응용 프로그램에서 해당 처리를 수행해야 합니다. 예를 들어 반환 값의 형식에 따라 역직렬화 방법을 설정할 수 있습니다.

2.3 코드 구현

위의 설계 포인트를 기반으로 HTTP 요청 라이브러리 구현을 시작할 때 다음 코드 구현을 참조할 수 있습니다.

package httpreq

import (
    "bytes"
    "encoding/json"
    "io/ioutil"
    "net"
    "net/http"
    "time"
)

type Request struct {
    URL        string
    Method     string
    Headers    map[string]string
    Body       []byte
    Params     map[string]string
    Timeout    int
    RetryTimes int
    ContentType string
}

type Response struct {
    StatusCode int
    Body       []byte
}

func Do(req Request) (*Response, error) {
    if req.Method == "" {
        req.Method = http.MethodGet
    }

    // 处理请求参数
    if req.Params != nil {
        req.URL = AddQueryParams(req.URL, req.Params)
    }

    // 创建一个请求
    httpRequest, err := http.NewRequest(req.Method, req.URL, bytes.NewBuffer(req.Body))
    if err != nil {
        return nil, err
    }

    // 处理请求头
    if req.Headers != nil {
        for k, v := range req.Headers {
            httpRequest.Header.Set(k, v)
        }
    }

    // 设置ContentType
    if req.ContentType != "" {
        httpRequest.Header.Set("Content-Type", req.ContentType)
    }

    // 设置请求超时
    httpClient := &http.Client{
        Transport: &http.Transport{
            DialContext: (&net.Dialer{
                Timeout:   time.Duration(req.Timeout) * time.Second,
                KeepAlive: time.Duration(req.Timeout) * time.Second,
            }).DialContext,
            MaxIdleConns:        100,              // http.ConnectionPool数量
            IdleConnTimeout:     90 * time.Second, // http.ConnectionPool中连接的空闲超时时间
            TLSHandshakeTimeout: 10 * time.Second,
            ExpectContinueTimeout: 1 * time.Second,
        },
    }

    // 发起请求
    resp, err := httpClient.Do(httpRequest)
    if err != nil {
        return nil, err
    }

    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        return nil, err
    }

    // 处理异常
    if resp.StatusCode >= 400 {
        return nil, NewError(resp.StatusCode, body)
    }

    return &Response{StatusCode: resp.StatusCode, Body: body}, nil
}

func AddQueryParams(url string, params map[string]string) string {
    var queryParams string
    for k, v := range params {
        queryParams = queryParams + "&" + k + "=" + v
    }
    url = url + "?" + queryParams[1:]
    return url
}

func NewError(statusCode int, body []byte) error {
    errorMsg := string(body)
    if errorMsg == "" {
        errorMsg = http.StatusText(statusCode)
    }
    return &httpError{StatusCode: statusCode, Message: errorMsg}
}

type httpError struct {
    StatusCode int
    Message    string
}

func (e *httpError) Error() string {
    return e.Message
}

func (r *Response) BindJSON(v interface{}) error {
    return json.Unmarshal(r.Body, v)
}

func (r *Response) BindText() string {
    return string(r.Body)
}

3.

위의 논의를 통해 Golang HTTP 요청 라이브러리를 캡슐화하는 것이 특별히 어렵지 않다는 것을 알 수 있습니다. 핵심은 우리의 요구 사항을 명확히 하고 네트워크 요청의 일부 세부 사항을 이해해야 한다는 것입니다. 그런 다음 표준 라이브러리에서 제공하는 메서드를 사용하여 Golang에서 뛰어난 HTTP 요청 라이브러리를 캡슐화할 수 있습니다. 동시에 구현 프로세스 중에 예외 처리, RESTful API 지원, 반환 값 처리 등과 같은 일부 세부 사항도 고려해야 합니다. 신중한 설계와 구현을 통해 고품질 HTTP 요청 라이브러리를 개발하여 Golang 개발을 더욱 효율적이고 편리하게 만들 수 있습니다.

위 내용은 golang은 http 요청을 캡슐화합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.