How to request http request in Golang

kpark340kpark340 Member
edited April 1 in Review my code

There are examples to use Oxford Dictionary Api in Python, Ruby, Java, and Node, but I can't find a way to do that in Golang.

I've been doing this by setting the headers. Can anyone help me on this?

package main

import (
"fmt"
"net/http"
"log"
"io/ioutil"
)

func main() {
client := &http.Client{}
app_id := "test_id"
app_key := "test_key"
language := "en"
word_id := "love"
url := "https://od-api.oxforddictionaries.com:443/api/v/entries/" + language + "/" + word_id
fmt.Println(url)
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("Authorization", "application/json")
req.Header.Set("api_id", app_id)
req.Header.Set("api_key", app_key)
resp, _ := client.Do(req)
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
log.Println(string(body))
}

Comments

  • SimoneSimone Administrator admin

    Hi @kpark340
    Good question, I'm not sure - let me find out if there are any other developers using the API with Golang, and I'll forward your question to them.
    Bear with me!
    Simone

  • AmosDuveenAmosDuveen Member, Administrator, Moderator admin

    Hi @kpark340,

    I'm making enquiries for anyone with a familiarity with Golang, but in the mean time, can you please check the URL stem you are using?

    The one you quote above is .../api/v/entries/... but it sould be .../api/v1/entries/....

  • kkirschekkirsche Member
    edited April 8

    @kpark340

    Below is the code I use to pull dictionary responses. Note that this uses gbotmetrics which hooks into the module's prometheus metrics, and uses a function called RetrieveOxfordDictionaryAPICredentials which retrieves the API credentials from an external password vault system. With some modifications though, this should allow you to do what you are looking for.

    // DoOxfordDictionary is the Oxford Dictionary module's action function.
    func DoOxfordDictionary(post *model.Post) []string {
            gbotmetrics.ModulesLastExecuted.WithLabelValues("oxford_dictionary").SetToCurrentTime()
            // split the string on the space (!cmd query), then join the query back together
            q := strings.Join(strings.Split(post.Message, " ")[1:], " ")
            safeQ := url.QueryEscape(q)
    
            u := fmt.Sprintf("https://od-api.oxforddictionaries.com:443/api/v1/entries/en/%s", safeQ)
    
            client := &http.Client{
                    Timeout: 10 * time.Second,
            }
            req, err := http.NewRequest("GET", u, nil)
            if err != nil {
                    gbotmetrics.ModulesAction.WithLabelValues("oxford_dictionary", "failure").Inc()
                    return []string{
                            "failed to create new HTTP request with error",
                            err.Error(),
                    }
            }
    
            sec, err := gbotvault.RetrieveOxfordDictionaryAPICredentials()
            if err != nil {
                    gbotmetrics.ModulesAction.WithLabelValues("oxford_dictionary", "failure").Inc()
                    return []string{
                            "failed to retrieve Oxford Dictionary API credentials from Vault",
                            err.Error(),
                    }
            }
    
            req.Header.Add("app_id", sec.AppID)
            req.Header.Add("app_key", sec.AppKey)
            req.Header.Add("Accept", "application/json")
            resp, err := client.Do(req)
            if err != nil {
                    gbotmetrics.ModulesAction.WithLabelValues("oxford_dictionary", "failure").Inc()
                    return []string{
                            "failed to execute HTTP request with error",
                            err.Error(),
                    }
            }
    
            result := []string{fmt.Sprintf("found the following entries for the word %s:", q)}
            if resp.StatusCode == 200 {
                    defer resp.Body.Close()
                    oxfordJSON := DictionaryEntriesResponse{}
                    err := json.NewDecoder(resp.Body).Decode(&oxfordJSON)
                    if err != nil {
                            gbotmetrics.ModulesAction.WithLabelValues("oxford_dictionary", "failure").Inc()
                            return []string{
                                    "failed to decode JSON response from API with error",
                                    err.Error(),
                            }
                    }
    
                    for _, res := range oxfordJSON.Results {
                            for _, lexentry := range res.LexicalEntries {
                                    for _, entry := range lexentry.Entries {
                                            for _, sense := range entry.Senses {
                                                    for _, definition := range sense.Definitions {
                                                            result = append(result, definition)
                                                    }
                                            }
                                    }
                            }
                    }
            } else {
                    gbotmetrics.ModulesAction.WithLabelValues("oxford_dictionary", "failure").Inc()
                    return []string{
                            fmt.Sprintf("received status `%s` from Oxford Dictionary API", resp.Status),
                    }
            }
    
            gbotmetrics.ModulesAction.WithLabelValues("oxford_dictionary", "success").Inc()
            return result
    }
    
    // DictionaryEntriesResponse is the response object we get back from the Oxford Dictionary
    // API as defined at the following URL:
    // https://developer.oxforddictionaries.com/documentation#!/Dictionary32entries/get_entries_source_lang_word_id
    type DictionaryEntriesResponse struct {
            Metadata struct {
                    Provider string `json:"provider"`
            } `json:"metadata"`
            Results []struct {
                    ID             string `json:"id"`
                    Language       string `json:"language"`
                    LexicalEntries []struct {
                            Entries []struct {
                                    Etymologies         []string `json:"etymologies"`
                                    GrammaticalFeatures []struct {
                                            Text string `json:"text"`
                                            Type string `json:"type"`
                                    } `json:"grammaticalFeatures"`
                                    HomographNumber string `json:"homographNumber"`
                                    Senses          []struct {
                                            Definitions []string `json:"definitions"`
                                            Domains     []string `json:"domains"`
                                            Examples    []struct {
                                                    Registers []string `json:"registers,omitempty"`
                                                    Text      string   `json:"text"`
                                            } `json:"examples"`
                                            ID               string   `json:"id"`
                                            ShortDefinitions []string `json:"short_definitions"`
                                            Registers        []string `json:"registers,omitempty"`
                                            Subsenses        []struct {
                                                    Definitions []string `json:"definitions"`
                                                    Domains     []string `json:"domains"`
                                                    Examples    []struct {
                                                            Text string `json:"text"`
                                                    } `json:"examples"`
                                                    ID               string   `json:"id"`
                                                    ShortDefinitions []string `json:"short_definitions"`
                                            } `json:"subsenses,omitempty"`
                                            ThesaurusLinks []struct {
                                                    EntryID string `json:"entry_id"`
                                                    SenseID string `json:"sense_id"`
                                            } `json:"thesaurusLinks,omitempty"`
                                    } `json:"senses"`
                            } `json:"entries"`
                            Language        string `json:"language"`
                            LexicalCategory string `json:"lexicalCategory"`
                            Pronunciations  []struct {
                                    AudioFile        string   `json:"audioFile"`
                                    Dialects         []string `json:"dialects"`
                                    PhoneticNotation string   `json:"phoneticNotation"`
                                    PhoneticSpelling string   `json:"phoneticSpelling"`
                            } `json:"pronunciations"`
                            Text string `json:"text"`
                    } `json:"lexicalEntries"`
                    Type string `json:"type"`
                    Word string `json:"word"`
            } `json:"results"`
    }
    
  • gurparitgurparit Member
    edited April 8

    @kpark340

    Your headers are wrong

    Before:
    req.Header.Set("Authorization", "application/json") <--- this should be Accept
    req.Header.Set("api_id", app_id) < --- this should be app_id
    req.Header.Set("api_key", app_key) <--- this should be app_key

    After:
    req.Header.Set("Accept", "application/json")
    req.Header.Set("app_id", app_id)
    req.Header.Set("app_key", app_key)

  • jlucas419jlucas419 Member
    edited April 8

    Hello, I was kinda surprised the Admins were able to tell what language I was using lol but anyways.

    As gurparit said, the headers should be "Add" instead of "Set".

    req.Header.Add("Accept", "application/json")
    req.Header.Add("app_id", appID)
    req.Header.Add("app_key", appKey)

  • rwslondonrwslondon Member

    The administrator, Simone, asked me to sign up to the forum because I have been accessing the api for two years with a program written in Go. I found this:

    cc := &rest.ClientConfig{
    Url: fmt.Sprintf(%s/entries/en/%s, oedUrl, o.lemma),
    RequestMethod: rest.GET,
    CustomHeaders: rest.CustomHeaders{
    "Accept": "application/json",
    "app_id": oedId,
    "app_key": oedKey,
    },
    PostQuery: nil,
    PostForm: nil,
    Response: o.oedDefinition,
    ErrResponse: nil,
    }

    I'm pretty rusty with this code because it's been two years. But as I follow where the declaration above leads, i find this...

    First, the url I'm hitting is "https://od-api.oxforddictionaries.com/api/v1/entries/en/REQUESTED_WORD", which is different from the url the OP is hitting. Maybe I'm using an old version of the api.

    Second, in contradiction to some of the previous commenters, my program does use Set -- and not Add -- when I send custom headers through a call to the helper package. So I don't think this is the OP's problem. But note that my header setting for "application/json" is "Accept" -- not "Authorization", as the OP has. This may be the problem.

    Third, I am marshalling the OED api's json response into a nested set of Go structs (o.oedDefinition in the example above). KKirsche is doing the same thing in the example above. This is the right idea.

    Hope this helps.

  • rwslondonrwslondon Member

    ...One other thing which jumps out at me as I look at the OP's code. Errors in Go should ALWAYS be checked, even when you feel that the call could never fail. So these lines...

    req, _ := http.NewRequest("GET", url, nil)
    resp, _ := client.Do(req)
    body, _ := ioutil.ReadAll(resp.Body)

    ...Should all be converted into these lines:

    req, err := http.NewRequest("GET", url, nil)

    if err != nil {
    fmt.Println("Error found: %s\n", err.Error())
    }

    resp, err := client.Do(req)

    if err != nil {
    fmt.Println("Error found: %s\n", err.Error())
    }

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {
    fmt.Println("Error found: %s\n", err.Error())
    }

  • SimoneSimone Administrator admin

    Many thanks everyone who replied!

    @kpark340, apart from the replies above, another API user asked me to post the link to their GitHub repository, where you can see the detail of their open source project using Golang.

    I hope this all has been useful!

  • rtait843rtait843 Member

    FYI i wrote a Slack bot (/dict) that uses the Oxford API and (I think/hope) fairly idiomatic Go. Hope this helps future golangers!

    https://github.com/rickt/slack-dictionary-bot

    -RMT

Sign In or Register to comment.