Skip to content
Snippets Groups Projects
Commit 78dbf6d3 authored by Steffen Sæther's avatar Steffen Sæther
Browse files

Upload New File

parent c2a21d19
Branches
No related tags found
No related merge requests found
package endpoints
import (
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
)
// BookCountResponse represents the structure of the response for book count endpoint.
type BookCountResponse struct {
Language string `json:"language"`
Books int `json:"books"`
Authors int `json:"authors"`
Fraction float64 `json:"fraction"`
}
type Books struct {
Count int `json:"count"`
Next string `json:"next"`
Previous string `json:"previous"`
Results []Result `json:"results"`
}
type Result struct {
Authors []Author `json:"authors"`
}
type Author struct {
Name string `json:"name"`
}
// BookCountHandler handles requests to the /librarystats/v1/bookcount/ endpoint.
func BookCountHandler(w http.ResponseWriter, r *http.Request) {
languages := r.URL.Query().Get("language")
// Split the language codes into a slice.
languageCodes := strings.Split(languages, ",")
// Placeholder values for books, authors, and total books.
var totalBooks int
var uniqueAuthors = make(map[string]struct{}) // Use a map as a set for unique authors
var allBooks int
// Create a slice to store results for each language.
var response []BookCountResponse
// Iterate through each language code.
for _, language := range languageCodes {
// Placeholder for the URL of the first page of results.
gutendexAPIURL := fmt.Sprintf("http://129.241.150.113:8000/books/?languages=%v", language)
// Fetch all pages of results.
for gutendexAPIURL != "" {
req, err := http.NewRequest("GET", gutendexAPIURL, nil)
if err != nil {
http.Error(w, "Failed to create a new request", http.StatusInternalServerError)
return
}
req.Header.Add("Content-Type", "application/json")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
http.Error(w, "Failed to send a request to Gutendex API", http.StatusInternalServerError)
return
}
defer res.Body.Close()
// Decode the response.
body, err := io.ReadAll(res.Body)
if err != nil {
http.Error(w, "Failed to read Gutendex API response", http.StatusInternalServerError)
return
}
var books Books
err = json.Unmarshal(body, &books)
if err != nil {
http.Error(w, "Failed to decode Gutendex API response", http.StatusInternalServerError)
return
}
// Increment total books and unique authors for each language.
totalBooks = books.Count
for _, book := range books.Results {
for _, author := range book.Authors {
uniqueAuthors[author.Name] = struct{}{}
}
}
// Update total books for the first page only.
if allBooks == 0 {
allBooks = getBooksCount(w)
}
// Update the URL to the next page of results.
gutendexAPIURL = books.Next
}
// Calculate fraction.
var fraction float64
if allBooks > 0 {
fraction = float64(totalBooks) / float64(allBooks)
}
// Append results for the current language to the response slice.
response = append(response, BookCountResponse{
Language: language,
Books: totalBooks,
Authors: len(uniqueAuthors),
Fraction: fraction,
})
// Clear the set of unique authors for the next language.
uniqueAuthors = make(map[string]struct{})
}
// Send the response.
sendJSONResponse(w, response)
}
func getBooksCount(w http.ResponseWriter) int {
gutendexCount := "http://129.241.150.113:8000/books/"
req, err := http.NewRequest("GET", gutendexCount, nil)
if err != nil {
http.Error(w, "Failed to create a new request", http.StatusInternalServerError)
return 1
}
req.Header.Add("Content-Type", "application/json")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
http.Error(w, "Failed to send a request to Gutendex API", http.StatusInternalServerError)
return 1
}
defer res.Body.Close()
// Decode the response.
body, err := io.ReadAll(res.Body)
if err != nil {
http.Error(w, "Failed to read Gutendex API response", http.StatusInternalServerError)
return 1
}
var books Books
err = json.Unmarshal(body, &books)
if err != nil {
http.Error(w, "Failed to decode Gutendex API response", http.StatusInternalServerError)
return 1
}
return books.Count
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment