在我的情况下,我如何以正确的方式旋转代码?戈兰

发布于 2025-02-11 18:32:37 字数 1389 浏览 2 评论 0原文

几乎有两个相同的功能可以执行大致相同的事情。在这种情况下,组织代码避免重复的正确方法是什么? httpgetter()函数访问云平台API并获取JSON响应,然后我在另一个函数中对其进行解析,并基于它从模板中形成Terraform。 getToken()函数几乎做同一件事,只需获得一个令牌,然后在httpgetter()函数中使用它。

var accessToken = getToken()


func httpGetter(method, url string) (*http.Response, []byte) {
    client := &http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        fmt.Println(err)
    }
    req.Header.Add("Accept", "application/json;version=35.0")
    req.Header.Add("Authorization", "Bearer "+accessToken)
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
    }
    return res, body
}

func getToken() string {
    url := "https://cloud-platform-api.com/api/sessions"
    method := "POST"
    client := &http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        fmt.Println(err)
    }
    req.Header.Add("Accept", "application/*+xml;version=35.0")
    req.Header.Add("Authorization", "Basic <auth-hash>")
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    if err != nil {
        fmt.Println(err)
    }
    accessToken := res.Header.Get("x-vmware-vcloud-access-token")
    return accessToken
}

There are almost two identical functions that do approximately the same thing. What would be the right way to organize the code to avoid repetition in this case? The httpGetter() function accesses cloud platform API and gets JSON response, which I then parsed in another function and based on it I form terraform manifest from the template. The getToken() function does almost the same thing, just gets a token, which is then used in the httpGetter() function.

var accessToken = getToken()


func httpGetter(method, url string) (*http.Response, []byte) {
    client := &http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        fmt.Println(err)
    }
    req.Header.Add("Accept", "application/json;version=35.0")
    req.Header.Add("Authorization", "Bearer "+accessToken)
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.Println(err)
    }
    return res, body
}

func getToken() string {
    url := "https://cloud-platform-api.com/api/sessions"
    method := "POST"
    client := &http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        fmt.Println(err)
    }
    req.Header.Add("Accept", "application/*+xml;version=35.0")
    req.Header.Add("Authorization", "Basic <auth-hash>")
    res, err := client.Do(req)
    if err != nil {
        fmt.Println(err)
    }
    defer res.Body.Close()
    if err != nil {
        fmt.Println(err)
    }
    accessToken := res.Header.Get("x-vmware-vcloud-access-token")
    return accessToken
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盗心人 2025-02-18 18:32:37

首先,如果您知道该方法是getter,则不需要传递方法参数,因此签名将变成以下类似。另外,您已经返回*http.Response回到呼叫者,现在将是呼叫者决定如何使用响应 +呼叫者在http中该怎么办呼叫失败,请返回错误,让呼叫者决定。

func HttpGet(url string) (*http.Response, error)

现在您还需要post带有身体的方法(在某些情况下),因此

func HttpPost(URL string, body []byte) (*http.Response, error)

现在有另一个功能来管理签名并具有通用代码,您可以拥有一种私人方法,该方法将仅在此文件中使用或您 揭示该方法(由您决定)

type Headers map[string]string

func http(method, URL string, body []byte, headers Headers) (*http.Response, error) { // we pass headers here so that the caller can pass custom headers for request
    client := &http.Client{}
    req, err := http.NewRequest(method, url, body)
    if err != nil {
        return nil, err
    }

    req.Header.Add("Accept", "application/json;version=35.0") // common static header you can keep as it is

    for key, value := range headers {
       req.Header.Add(key, value)
    }
    
    return client.Do(req)
}

还可以使用这两种方法的呼叫来

func HttpGet(url string, headers Headers) (*http.Response, error) {
  return http(http.MethodGet, URL, nil, headers)
}

func HttpPost(url string, body []byte, headers Headers) (*http.Response, error) {
  return http(http.MethodPost, url, body, headers)
}

,现在您可以使用它来通过呼叫者来传递auth令牌,例如:

func getToken() {
  res, err := httpPost("https://cloud-platform-api.com/api/sessions", nil, 
    map[string]string{
      "Authorization": "Basic <auth-hash>",
    }

  if err != nil {
    // do something with error
  }

  if res.StatusCode == http.StatusCreated {
     // do what you want with the success response like unmarshalling to JSON
  }
}

对于您不需要传递标题的情况,你可以做

 res, err := httpGet("some-url", nil) // you pass header as nil

First thing first if you know the method is a getter then you don't need to pass the method param so the signature would become something like below. Also, you are already returning a *http.Response back to the caller now it will be the callers decision on what to do with the response + the caller should decide what to do in case of if the HTTP call fails so return error and let the caller decide.

func HttpGet(url string) (*http.Response, error)

Now you also want POST method with body (in some cases) so have another function

func HttpPost(URL string, body []byte) (*http.Response, error)

Now to manage both signature and have a common code you could have a private method that will be just used in this file or you could also expose that method (it is up to you)

type Headers map[string]string

func http(method, URL string, body []byte, headers Headers) (*http.Response, error) { // we pass headers here so that the caller can pass custom headers for request
    client := &http.Client{}
    req, err := http.NewRequest(method, url, body)
    if err != nil {
        return nil, err
    }

    req.Header.Add("Accept", "application/json;version=35.0") // common static header you can keep as it is

    for key, value := range headers {
       req.Header.Add(key, value)
    }
    
    return client.Do(req)
}

Using this your call from the two methods would look like

func HttpGet(url string, headers Headers) (*http.Response, error) {
  return http(http.MethodGet, URL, nil, headers)
}

func HttpPost(url string, body []byte, headers Headers) (*http.Response, error) {
  return http(http.MethodPost, url, body, headers)
}

Now you can use this to pass the auth token from the caller like:

func getToken() {
  res, err := httpPost("https://cloud-platform-api.com/api/sessions", nil, 
    map[string]string{
      "Authorization": "Basic <auth-hash>",
    }

  if err != nil {
    // do something with error
  }

  if res.StatusCode == http.StatusCreated {
     // do what you want with the success response like unmarshalling to JSON
  }
}

and for cases where you don't need to pass header, you can do

 res, err := httpGet("some-url", nil) // you pass header as nil
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文