为了账号安全,请及时绑定邮箱和手机立即绑定

使用 PostgreSQL 和 json-api 的发布请求返回一个空体

使用 PostgreSQL 和 json-api 的发布请求返回一个空体

Go
莫回无 2023-06-12 16:56:50
在 POST 请求之后,我期望将最后插入的记录编组到 json 中,但返回一个空体。我做的不好吗?package modelsimport (    "encoding/json"    "errors"    "flag"    "fmt"    "log"    "net/http"    "strconv"    "github.com/go-chi/chi"    "github.com/google/jsonapi"    "github.com/thedevsaddam/renderer"    "github.com/xo/dburl")var rnd = renderer.New()var flagVerbose = flag.Bool("v", false, "verbose")var FlagURL = flag.String("url", "postgres://postgres:@127.0.0.1/sweb", "url")// Page represents a row from 'public.pages'.type Page struct {    Tag   string `jsonapi:"attr,tag"`      // tag    Body  string `jsonapi:"attr,body"`     // body    Slug  string `jsonapi:"attr,slug"`     // slug    Title string `jsonapi:"attr,title"`    // title    ID    int    `jsonapi:"primary,pages"` // id    Link  string `jsonapi:"attr,link"`     // link    // xo fields    _exists, _deleted bool}func (page Page) JSONAPILinks() *jsonapi.Links {    return &jsonapi.Links{        "self": fmt.Sprintf("https://%d", page.ID),    }}我相信这是罪魁祸首。插入记录后,它应该返回指定的最后插入的记录。func (p *Page) PInsert(db XODB) (*Page, error) {    var err error    // if already exist, bail    if p._exists {        return p, errors.New("insert failed: already exists")    }    // sql insert query, primary key provided by sequence    const sqlstr = `INSERT INTO public.pages (` +        `tag, body, slug, title` +        `) VALUES (` +        `$1, $2, $3, $4` +        `) RETURNING id, tag, body, title`    // run query    XOLog(sqlstr, p.Tag, p.Body, p.Slug, p.Title)    err = db.QueryRow(sqlstr, p.Tag, p.Body, p.Slug, p.Title).Scan(&p.ID, &p.Tag, &p.Body, &p.Title)    if err != nil {        return p, err    }    // set existence    p._exists = true    return p, nil}更新更新数据库中的页面并返回最后插入的记录。这同样适用于更新功能这是我认为问题发生的最后一个功能。最后插入的记录应该编组到 json 中。
查看完整描述

1 回答

?
www说

TA贡献1775条经验 获得超8个赞

您的最后一段代码包含许多错误。相关部分(没有无用和混淆的 Printlns)是:


p, err := page.PSave(db)

if err != nil {

    if err := jsonapi.MarshalPayload(w, p); err != nil {

        http.Error(w, err.Error(), http.StatusInternalServerError)

    }

}


w.Header().Set("Content-Type", jsonapi.MediaType)

w.WriteHeader(http.StatusCreated)

主要的错误是json.MarshalPayload它只在err != nil. 换句话说,只有在保存失败时才序列化该页面。


第二个错误是jsonapi.MarshalPayload将Write调用http.ResponseWriter. 这会将所有后续调用 Header().Set变成WriteHeader空操作。


更正确的代码看起来像这样。


// 1. Save the page in the database, bail on error

p, err := page.PSave(db)

if err != nil {

    http.Error(w, err.Error(), http.StatusInternalServerError)

    return 

}


// 2. Marshal the page into an intermediate buffer, bail on error

var buf bytes.Buffer

if err := jsonapi.MarshalPayload(&buf, p); err != nil {

    http.Error(w, err.Error(), http.StatusInternalServerError)

    return 

}


// 3. Write the entire response; failures to write the intermediate buffer

// cannot be communicated over HTTP

w.Header().Set("Content-Type", jsonapi.MediaType)

w.WriteHeader(http.StatusCreated)

if _, err := buf.WriteTo(w); err != nil {

    log.Printf("failed to write response: %v", err)

    return 

}


查看完整回答
反对 回复 2023-06-12
  • 1 回答
  • 0 关注
  • 95 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信