Ananto30/ask-hadith

View on GitHub
api/book.go

Summary

Maintainability
A
0 mins
Test Coverage
/*
Package handler provides the HTTP handlers for the serverless API.
This file contains the handler for the /book endpoint.
*/
package handler

import (
    "fmt"
    "net/http"
    "strings"

    "go.mongodb.org/mongo-driver/bson"
)

// GetHadithByBookRefNo returns a hadith by its collection ID, book number and
// book reference number. These are all required query parameters.
func GetHadithByBookRefNo(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()

    collectionID := r.URL.Query().Get("collection_id")
    book := r.URL.Query().Get("book")
    refNo := r.URL.Query().Get("ref_no")
    if reason, ok := validateGetHadithByBookRefNoQueryParams(collectionID, book, refNo); !ok {
        sendBadRequestResp(w, reason)
        return
    }

    client, err := getMongoClient()
    if err != nil {
        sendServerErrorResp(w, err)
        return
    }
    collection := client.Database("hadith").Collection("hadiths")

    var resp BookResponse
    if err := collection.FindOne(
        ctx,
        bson.M{
            "collection_id": collectionID,
            "book_no":       book,
            "book_ref_no":   refNo,
        },
    ).
        Decode(&resp); err != nil {
        sendServerErrorResp(w, err)
        return
    }

    resp.Base64 = hadithToBase64(*resp.HadithResponse)

    sendResp(w, resp)
}

func validateGetHadithByBookRefNoQueryParams(collectionID, book, refNo string) (string, bool) {
    if reason, ok := validateCollectionID(collectionID); !ok {
        return reason, false
    }
    if reason, ok := validateBook(book); !ok {
        return reason, false
    }
    if reason, ok := validateRefNo(refNo); !ok {
        return reason, false
    }

    return "", true
}

func validateCollectionID(collectionID string) (string, bool) {
    if collectionID == "" {
        return "collection_id is required", false
    }
    if !contains(shortNames, collectionID) {
        return fmt.Sprintf("collection_id must be one of %s", strings.Join(shortNames, ", ")), false
    }

    return "", true
}

func validateBook(book string) (string, bool) {
    if book == "" {
        return "book is required", false
    }
    if !isNumber(book) {
        return "book must be a number", false
    }

    return "", true
}

func validateRefNo(refNo string) (string, bool) {
    if refNo == "" {
        return "ref_no is required", false
    }
    if !isNumber(refNo) {
        return "ref_no must be a number", false
    }

    return "", true
}

type BookResponse struct {
    *HadithResponse `bson:",inline" json:",inline"`
    Base64          string `json:"base64"`
}