How to publish CBOR data as a dag in kubo

I used to use go-ipfs-api and I could simply publish my CBOR data using DagPutWithOpts. Since this has been deprecated I’m trying to use the client/rpc, but I’m completely lost. I have tried for weeks. Asking ChatGPT just increased the frustration, as it seems to think I can just add the CBOR data as unixfs and the publish the CID to IPNS. But that doesn’t work. This just result in the data being download as raw bytes, the data is not in dag-cbor format as before.

( I test this by publishing and just clicking the name in http://127.0.0.1:45005/ipfs/bafybeiamycmd52xvg6k3nzr6z3n33de6a2teyhquhj4kspdtnvetnkrfim/#/settings )

I have ended up with this incredibly kludgy code:

cid, err := internal.IPFSDagPutWithOptions(data, “dag-cbor”, “dag-cbor”, true, “sha2-256”, false)
if err != nil {
return “”, fmt.Errorf(“doc/publish: failed to put document to IPFS: %w”, err)
}

// Publish publishes a simple CBOR struct to IPFS and returns the CID.
// This is a kludge, as the kubo client/rpc is not working.
// The parameters are consistent with the correspconding IPFS API call.
// Ref. HTTP APIs for IPFS | IPFS Docs
func IPFSDagPutWithOptions(data byte, inputCodec string, storeCodec string, pin bool, hash string, allowBigBlock bool) (string, error) {

// Create a buffer to write our multipart form data
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)

// Create a form field writer for field ‘file’
part, err := writer.CreateFormField(“file”)
if err != nil {
return “”, err
}

// Write CBOR data into the multipart form field
_, err = part.Write(data)
if err != nil {
return “”, err
}

// Close the writer
err = writer.Close()
if err != nil {
return “”, err
}

// Build the URL with query parameters
params := url.Values{}
params.Add(“store-codec”, storeCodec)
params.Add(“input-codec”, inputCodec)
params.Add(“pin”, convert.Bool2Str(pin))
params.Add(“hash”, hash)
params.Add(“allow-big-block”, convert.Bool2Str(allowBigBlock))

apiUrl := GetIPFSAPIUrl() + “/dag/put”
apiUrl += “?” + params.Encode()

// Prepare the HTTP request
req, err := http.NewRequest(“POST”, apiUrl, body)
if err != nil {
return “”, err
}

// Set the content type, this will contain the boundary.
req.Header.Set(“Content-Type”, writer.FormDataContentType())

// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return “”, err
}
defer resp.Body.Close()

// Read the response body
respBody, err := io.ReadAll(resp.Body)
if err != nil {
return “”, err
}
log.Debugf(“doc/publish: response.Body: %s”, string(respBody))

// Unmarshal the JSON data into the struct
var ipfsResp DagPutResponse
err = json.Unmarshal(respBody, &ipfsResp)
if err != nil {
return “”, err
}

return ipfsResp.Cid.CidString, nil
}

This can’t possibly be the best modern solution. So how am I to publish CBOR as a dag using client/rpc?