package httpapi import "net/http" // ContractVersion is the version of the ratified contract this build serves // (`docs/architecture/14-api-contract/openapi.yaml`, `info.version`). // // It is a CONSTANT and it is the only place a non-streaming client learns which contract it is // talking to. While the major is `0` a differing MINOR carries breaking changes by design, so a // client generated against another one refuses to work and says so — which is why this must be // raised in the same commit as the code that implements a new minor, and never as a courtesy // afterwards. const ContractVersion = "0.4.0" // Capabilities is what this deployment can do: one flat document, the same for every account. type Capabilities struct { // Pairs is what this deployment can translate, and what it merely knows about. Unavailable ones // are LISTED rather than omitted: "absent" and "listed as unavailable" are different facts to a // user waiting for one. Pairs []LanguagePair // IntakeEnabled is whether this deployment takes books at all. False is a read-only instance, // and without the field a client discovers that only by spending a user's upload. IntakeEnabled bool IntakeMaxBytes int64 // ExportFormats is what `POST /books/{bookId}/exports` accepts. Empty means none are built here, // which is the honest answer while the export path is not built (deferred to P8). ExportFormats []string // PageSizeDefault is how many rows a collection returns when `limit` is omitted. It is the // DEPLOYMENT's number rather than a constant of the contract, and every read path takes its // default from the same place this answers from. PageSizeDefault int } // LanguagePair is one direction, as the wire carries it. type LanguagePair struct { Source string Target string Available bool } type wireCapabilities struct { ContractVersion string `json:"contract_version"` LanguagePairs []wireLanguagePair `json:"language_pairs"` IntakeEnabled bool `json:"intake_enabled"` IntakeMaxBytes int64 `json:"intake_max_bytes"` ExportFormats []string `json:"export_formats"` PageSizeDefault int `json:"page_size_default"` } type wireLanguagePair struct { Source string `json:"source"` Target string `json:"target"` State string `json:"state"` } func (h *v0) capabilities(w http.ResponseWriter, r *http.Request) { if _, ok := principal(w, r); !ok { return } out := wireCapabilities{ ContractVersion: ContractVersion, LanguagePairs: make([]wireLanguagePair, 0, len(h.caps.Pairs)), IntakeEnabled: h.caps.IntakeEnabled, IntakeMaxBytes: h.caps.IntakeMaxBytes, ExportFormats: h.caps.ExportFormats, PageSizeDefault: h.caps.PageSizeDefault, } if out.ExportFormats == nil { out.ExportFormats = []string{} // an empty collection is an empty array, never null } for _, p := range h.caps.Pairs { state := "unavailable" if p.Available { state = "available" } out.LanguagePairs = append(out.LanguagePairs, wireLanguagePair{Source: p.Source, Target: p.Target, State: state}) } h.writeJSON(w, r, http.StatusOK, out) }