1

Background story: I'm retrieving details using a GET method. I managed to get the program to parse the output given by the server into a JSON file titled "output.json".

Problem: Every time I make different requests, the output will overwrite any previous content in the output.json file. Is it possible to make a new JSON file for every request? I am rather new to GoLang and any help will be very useful :)

Note: I am only showing the method that is being used to call the API, if need to, I will show the rest of my code.

Here is my method used:

func render(endpoint string, w http.ResponseWriter, r *http.Request) {
    // check if request has cookie set
    if cookie, err := r.Cookie(COOKIE_NAME); err != nil {
        // else redirect to OAuth Authorization EP
        redirectToOAuth(w, r, endpoint)
    } else {
        session := cookie.Value
        accessToken := sessions[session]

        // pipe api endpoint
        ep := fmt.Sprintf("%s/%s", fidorConfig.FidorApiUrl, endpoint)
        if api_req, err := http.NewRequest("GET", ep, nil); err != nil {
            w.WriteHeader(500)
            w.Write([]byte(err.Error()))
        } else {
            api_req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", accessToken))
            api_req.Header.Set("Accept", "application/vnd.fidor.de; version=1,text/json") 

            client := &http.Client{}
            if api_resp, err := client.Do(api_req); err != nil {
                w.WriteHeader(500)
                w.Write([]byte(err.Error()))
            } else {
                if api_resp.StatusCode == 401 { // token probably expired
                    handleLogout(w, r, endpoint)
                    return
                }

                w.Header().Set("Content-Type", "application/json")
                w.WriteHeader(api_resp.StatusCode)


                defer api_resp.Body.Close()
                out, err := os.Create("output.json")
                if err != nil {
                    // panic?
                }
                defer out.Close()
                io.Copy(out, api_resp.Body)

            }
        }
    }
}
Michael Hampton
  • 9,737
  • 4
  • 55
  • 96
Gordon Soh
  • 23
  • 6
  • It's not clear to me what exactly it is that you want. Do you want to create a new file for every request? Or do you want the content of each new request to be appended to the existing file? – mkopriva May 22 '18 at 06:38
  • @mkopriva yes, every request will create a new file. Is that possible? – Gordon Soh May 22 '18 at 06:43
  • In that case you need to create a new file for each request, right now you're using the hardcoded name "output.json" which will cause any previous file of that same name to be overwritten. That means that for each request you need to use a unique name for the output file. – mkopriva May 22 '18 at 07:47
  • ... depending on how robust you need your code to be you could use a simple global counter, or an atomic one, a timestamp, or a random value. Using these you can then generate a unique name for the file. – mkopriva May 22 '18 at 07:51
  • I see, do you have any references I can go to look? @mkopriva – Gordon Soh May 22 '18 at 07:53
  • Take a look at the `time` package, its `Time` type's `Unix` method, and then at the `strconv` package and its `ParseInt` function. – mkopriva May 22 '18 at 08:00

2 Answers2

1

If you want to append time in your filename (like @Florian suggested), you can do something like this when you are creating file:

out, err := os.Create(fmt.Sprintf("output-%d.json", time.Now().Unix()))
// filename => output-1257894000.json

Here time.Now().Unix() returns the number of seconds elapsed since January 1, 1970 UTC (aka Unix time). So each time it will create different json file.

More info about time: https://golang.org/pkg/time/#Time.Unix

leninhasda
  • 1,620
  • 11
  • 18
0

If you don't want your file to be overwritten you can either give the file a different name (for example by appending the current time using time.Now()) or you can append the output to the file, so the output.json contains all json files.

Florian
  • 177
  • 1
  • 11
  • Hi @Florian, I tried using time.Now() in os.Create but I got an error from my console. Here is the error: cannot use time.Now() (type time.Time) as type string in argument to os.Create. Any advice? – Gordon Soh May 22 '18 at 07:33
  • You need to format the timestamp to a string. You can either use the unixtime `strconv.FormarInt(time.Now().Unix(), 10)` or a formated timestamp (See this tutorial: https://yourbasic.org/golang/format-parse-string-time-date-example/) – Florian May 23 '18 at 08:15