Generare e gestire un DOI con Go

Il DOI (Digital Object Identifier) è uno standard utilizzato per identificare in modo univoco contenuti digitali, come articoli scientifici, dataset, e pubblicazioni. In questo articolo vedremo come generare e gestire un DOI in Go, simulando l'interazione con le API di registrazione (come quelle di Crossref o DataCite).

1. Cos'è un DOI

Un DOI è una stringa alfanumerica, solitamente composta da un prefisso e un suffisso separati da uno slash. Ad esempio: 10.1234/abcde.2025.001. I DOI sono generalmente registrati tramite enti certificati che offrono API per la creazione, aggiornamento e risoluzione.

2. Generazione di un DOI

La generazione può essere fatta localmente creando una stringa che segua la sintassi corretta. Ecco un semplice esempio in Go:


package main

import (
    "crypto/rand"
    "fmt"
)

func generateDOI(prefix string) string {
    suffix := make([]byte, 6)
    rand.Read(suffix)
    for i := range suffix {
        suffix[i] = "abcdefghijklmnopqrstuvwxyz0123456789"[suffix[i]%36]
    }
    return fmt.Sprintf("%s/%s", prefix, string(suffix))
}

func main() {
    doi := generateDOI("10.1234")
    fmt.Println("DOI generato:", doi)
}

3. Registrazione tramite API

Dopo aver generato un DOI, bisogna registrarlo presso un ente come DataCite. Ecco un esempio di chiamata HTTP POST per registrare un DOI:


package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "net/http"
)

type Metadata struct {
    Data struct {
        Type       string `json:"type"`
        Attributes struct {
            DOI   string `json:"doi"`
            Title string `json:"titles"`
            // Altri metadati
        } `json:"attributes"`
    } `json:"data"`
}

func registerDOI(doi, title string) error {
    metadata := Metadata{}
    metadata.Data.Type = "dois"
    metadata.Data.Attributes.DOI = doi
    metadata.Data.Attributes.Title = title

    payload, _ := json.Marshal(metadata)
    req, _ := http.NewRequest("POST", "https://api.test.datacite.org/dois", bytes.NewBuffer(payload))
    req.Header.Set("Content-Type", "application/vnd.api+json")
    req.SetBasicAuth("USERNAME", "PASSWORD")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusCreated {
        return fmt.Errorf("Errore nella registrazione: %s", resp.Status)
    }
    return nil
}

4. Aggiornamento e gestione

Per aggiornare un DOI registrato, si può effettuare una richiesta HTTP PUT verso lo stesso endpoint:


// Simile alla funzione precedente ma con metodo PUT
req, _ := http.NewRequest("PUT", "https://api.test.datacite.org/dois/10.1234/xyz123", bytes.NewBuffer(payload))

5. Risoluzione di un DOI

I DOI possono essere risolti tramite un semplice redirect usando il sito https://doi.org/. Ad esempio:


package main

import (
    "fmt"
    "net/http"
)

func resolveDOI(doi string) error {
    url := fmt.Sprintf("https://doi.org/%s", doi)
    resp, err := http.Get(url)
    if err != nil {
        return err
    }
    defer resp.Body.Close()

    fmt.Println("Redirect a:", resp.Request.URL)
    return nil
}

Conclusione

Generare e gestire un DOI in Go è un processo relativamente semplice, ma che richiede attenzione nella costruzione dei metadati e nell'interazione con le API ufficiali. Per l'uso in produzione è essenziale gestire l'autenticazione in modo sicuro e rispettare le specifiche dell’ente registratore.

Torna su