悠家娱乐|| Linux 中国,构建一个即时消息应用(四):消息( 二 )
首先 , 它将请求正文解码为包含消息内容的结构 。 然后 , 它验证内容不为空并且少于480个字符 。
varrxSpaces=regexp.MustCompile(''s+'')funcremoveSpaces(sstring)string{ifs==''''{returns}lines:=make([]string,0)for_,line:=rangestrings.Split(s,''n''){line=rxSpaces.ReplaceAllLiteralString(line,'''')line=strings.TrimSpace(line)ifline!=''''{lines=append(lines,line)}}returnstrings.Join(lines,''n'')}
这是删除空格的函数 。 它遍历每一行 , 删除两个以上的连续空格 , 然后回非空行 。
验证之后 , 它将启动一个SQL事务 。 首先 , 它查询对话中的参与者是否存在 。
funcqueryParticipantExistance(ctxcontext.Context,tx*sql.Tx,userID,conversationIDstring)(bool,error){ifctx==nil{ctx=context.Background()}varexistsbooliferr:=tx.QueryRowContext(ctx,`SELECTEXISTS(SELECT1FROMparticipantsWHEREuser_id=$1ANDconversation_id=$2)`,userID,conversationID).Scan(&exists);err!=nil{returnfalse,err}returnexists,nil}
我将其提取到一个函数中 , 因为稍后可以重用 。
如果用户不是对话参与者 , 我们将返回一个404NOTFound错误 。
然后 , 它插入消息并更新对话last_message_id 。 从这时起 , 由于我们不允许删除消息 , 因此last_message_id不能为NULL 。
接下来提交事务 , 并在goroutine中更新参与者messages_read_at 。
funcupdateMessagesReadAt(ctxcontext.Context,userID,conversationIDstring)error{ifctx==nil{ctx=context.Background()}if_,err:=db.ExecContext(ctx,`UPDATEparticipantsSETmessages_read_at=now()WHEREuser_id=$1ANDconversation_id=$2`,userID,conversationID);err!=nil{returnerr}returnnil}
在回复这条新消息之前 , 我们必须通知一下 。 这是我们将要在下一篇文章中编写的实时部分 , 因此我在那里留一了个注释 。
获取消息
这个端点处理对/api/conversations/{conversationID}/messages的GET请求 。 它用一个包含会话中所有消息的JSON数组进行响应 。 它还具有更新参与者messages_read_at的副作用 。
funcgetMessages(whttp.ResponseWriter,r*http.Request){ctx:=r.Context()authUserID:=ctx.Value(keyAuthUserID).(string)conversationID:=way.Param(ctx,''conversationID'')tx,err:=db.BeginTx(ctx,&sql.TxOptions{ReadOnly:true})iferr!=nil{respondError(w,fmt.Errorf(''couldnotbegintx:%v'',err))return}defertx.Rollback()isParticipant,err:=queryParticipantExistance(ctx,tx,authUserID,conversationID)iferr!=nil{respondError(w,fmt.Errorf(''couldnotqueryparticipantexistance:%v'',err))return}if!isParticipant{http.Error(w,''Conversationnotfound'',http.StatusNotFound)return}rows,err:=tx.QueryContext(ctx,`SELECTid,content,created_at,user_id=$1ASmineFROMmessagesWHEREmessages.conversation_id=$2ORDERBYmessages.created_atDESC`,authUserID,conversationID)iferr!=nil{respondError(w,fmt.Errorf(''couldnotquerymessages:%v'',err))return}deferrows.Close()messages:=make([]Message,0)forrows.Next(){varmessageMessageiferr=rows.Scan(&message.ID,&message.Content,&message.CreatedAt,&message.Mine,);err!=nil{respondError(w,fmt.Errorf(''couldnotscanmessage:%v'',err))return}messages=append(messages,message)}iferr=rows.Err();err!=nil{respondError(w,fmt.Errorf(''couldnotiterateovermessages:%v'',err))return}iferr=tx.Commit();err!=nil{respondError(w,fmt.Errorf(''couldnotcommittxtogetmessages:%v'',err))return}gofunc(){iferr=updateMessagesReadAt(nil,authUserID,conversationID);err!=nil{log.Printf(''couldnotupdatemessagesreadat:%vn'',err)}}()respond(w,messages,http.StatusOK)}
- 薄情娱乐咖|还能登上人生巅峰,贾诩简直就是张绣的“人生导师”,打一手烂牌
- 悠家娱乐|Pro渲染图,前辈泪流满面加速降价,曝光华为Mate40
- 悠家娱乐|前辈即将残忍让路价崩,曝光华为麒麟9000的跑分已经出来
- 忧家娱乐|前辈闻声价崩疯抢模式,曝光华为mate40后置摄像头排布
- 娱乐那些事儿|蓝牙耳机挂脖式好还是无线好?挂脖式性价比蓝牙耳机排名
- 悠家娱乐|前辈提前价崩简直厉害,我们期待的就剩华为Mate40了
- cnBeta|研究人员担心BleedingTooth蓝牙漏洞给Linux系统带来风险
- 悠家娱乐|一加8无奈下跌黯然神伤,骁龙865版一加8T闪亮登场
- 忧家娱乐|用鸡毛掸子伪装,苏联冷战时期“发射器猎人”模式射频信号追踪器
- 忧家娱乐|2017 年抵御了史上最大的 DDoS 攻击,谷歌称