blob: b33003723188cdeb2b0d96066f2c203783dd03e6 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package rest
import (
"bytes"
"errors"
"io"
"net/http"
"github.com/apache/servicecomb-service-center/pkg/log"
"github.com/apache/servicecomb-service-center/pkg/util"
"github.com/go-chassis/cari/discovery"
"github.com/go-chassis/cari/pkg/errsvc"
"github.com/go-chassis/go-chassis/v2/pkg/codec"
)
var errNilRequestBody = errors.New("request body is nil")
func WriteError(w http.ResponseWriter, code int32, detail string) {
err := discovery.NewError(code, detail)
WriteServiceError(w, err)
}
func WriteServiceError(w http.ResponseWriter, err error) {
e, ok := err.(*errsvc.Error)
if !ok {
WriteError(w, discovery.ErrInternal, err.Error())
return
}
status := e.StatusCode()
b, err := codec.Encode(e)
if err != nil {
log.Error("json marshal failed", err)
status = http.StatusInternalServerError
b = util.StringToBytesWithNoCopy(err.Error())
}
w.Header().Set(HeaderContentType, ContentTypeJSON)
w.WriteHeader(status)
_, err = w.Write(b)
if err != nil {
log.Error("write err response failed", err)
}
}
// WriteResponse writes http response
// If the resp is nil or represents success, response status is http.StatusOK,
// response content is obj.
// If the resp represents fail, response status is from the code in the
// resp, response content is from the message in the resp.
func WriteResponse(w http.ResponseWriter, r *http.Request, resp *discovery.Response, obj interface{}) {
if resp != nil && resp.GetCode() != discovery.ResponseSuccess {
WriteError(w, resp.GetCode(), resp.GetMessage())
return
}
if obj == nil {
w.Header().Set(HeaderContentType, ContentTypeText)
w.WriteHeader(http.StatusOK)
return
}
util.SetRequestContext(r, CtxResponseObject, obj)
var (
data []byte
err error
)
switch body := obj.(type) {
case []byte:
data = body
default:
data, err = codec.Encode(body)
if err != nil {
WriteError(w, discovery.ErrInternal, err.Error())
return
}
}
w.Header().Set(HeaderContentType, ContentTypeJSON)
w.WriteHeader(http.StatusOK)
_, err = w.Write(data)
if err != nil {
log.Error("write response failed", err)
}
}
func WriteSuccess(w http.ResponseWriter, r *http.Request) {
WriteResponse(w, r, nil, nil)
}
// ReadBody can re-read the request body
func ReadBody(r *http.Request) ([]byte, error) {
if r.Body == nil {
return nil, errNilRequestBody
}
data, err := io.ReadAll(r.Body)
if err != nil {
return nil, err
}
r.Body = io.NopCloser(bytes.NewReader(data))
return data, nil
}