DEV Community

Cover image for Interacting with the Dev.to Article API - Again Sort Of
Steve Layton
Steve Layton

Posted on • Updated on

Interacting with the Dev.to Article API - Again Sort Of

ATLG Sidebar

Cleanup

Welcome back! We're staying on the "sidebar" again this week, with a couple of small tweaks to make the code a tad more readable. I've also updated the GitHub repo with the code from the last couple of posts. So everything should be up to date!


Refactor Go Go Go

We're going to skip over the full code walkthrough since only a few minute details have changed. @ladydascalie was nice enough to point out a couple of small bits that could improve. I thought I'd cover them real quick in a bid to etch them into my mind, and pass them on. The first comes from my two URL "format" functions. While they are "correct" do exactly what they should, they are a bit verbose.

// FormatPagedRequest returns *http.Request ready to do() to get one page
func (dtc DevtoClient) FormatPagedRequest(param, paramValue string) (r *http.Request, err error) {
  URL := dtc.DevtoAPIURL + "articles/?" + param + "=" + paramValue
  fmt.Printf("%v\n", URL)
  r, err = http.NewRequest(http.MethodGet, URL, nil)
  if err != nil {
    return nil, err
  }
  return r, nil
}

// FormatArticleRequest returns http.Request ready to do() and get an article
func (dtc DevtoClient) FormatArticleRequest(i int32) (r *http.Request, err error) {
  URL := fmt.Sprintf(dtc.DevtoAPIURL+"articles/%d", i)
  r, err = http.NewRequest(http.MethodGet, URL, nil)
  if err != nil {
    return nil, err
  }
  return r, nil
}
Enter fullscreen mode Exit fullscreen mode

See how we are returning *http.Request, error from both functions? Noticed anything else? That's right http.NewRequest() also returns *http.Request, error! That means we can remove our error check and return the results of the new request instead.

// FormatPagedRequest returns *http.Request ready to do() to get one page
func (dtc DevtoClient) FormatPagedRequest(param, paramValue string) (*http.Request, error) {
  URL := dtc.DevtoAPIURL + "articles/?" + param + "=" + paramValue
  fmt.Printf("%v\n", URL)
  return http.NewRequest(http.MethodGet, URL, nil)
}

// FormatArticleRequest returns http.Request ready to do() and get an article
func (dtc DevtoClient) FormatArticleRequest(i int32) (*http.Request, error) {
  URL := fmt.Sprintf(dtc.DevtoAPIURL+"articles/%d", i)
  return http.NewRequest(http.MethodGet, URL, nil)
}
Enter fullscreen mode Exit fullscreen mode

A little bit of refactoring allows us to move our error check up one level and not check the same thing twice.


Look Ma No Err

The second little tweak is the result of a missed error check. Which I'm a little surprised wasn't caught in linting. But, I suppose that's what we get for not giving our code a thorough re-reading.

json.Unmarshal(body, &articles)
Enter fullscreen mode Exit fullscreen mode

Ahh if err != nil! Now we are writing some Go!

    err = json.Unmarshal(body, &articles)
    if err != nil {
      panic(err)
    }
Enter fullscreen mode Exit fullscreen mode

Next time

As I said, short and sweet this week! I'm actually thinking about doing at least one more post with this code base. I'd like to clean up all the panic()'s and try to build some sort of retry system. We could use a struct to keep track of the article ID, the last HTTP error code, and the number of retries attempted so far. If dtc.Client.Do(r) results in an HTTP status code of anything other then a 200 we can add it to the struct to retry. We would then wait for the complete run, then look at the struct and range through that if needed. Simple. Right? I guess we'll see next week.


You can find the code for this and most of the other Attempting to Learn Go posts in the repo on GitHub.



Top comments (0)