httputil.go 2.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13
// Copyright 2017 Vector Creations Ltd
//
// Licensed 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.
T
tanggen 已提交
14 15 16
//
//
// Modifications copyright (C) 2020 Finogeeks Co., Ltd
17

18
package httputil
19 20

import (
T
tanggen 已提交
21 22
	"context"
	"io/ioutil"
23 24
	"net/http"

T
tanggen 已提交
25 26 27 28
	"github.com/finogeeks/ligase/common/jsonerror"
	util "github.com/finogeeks/ligase/skunkworks/gomatrixutil"
	log "github.com/finogeeks/ligase/skunkworks/log"
	jsoniter "github.com/json-iterator/go"
29 30
)

T
tanggen 已提交
31 32
var json = jsoniter.ConfigCompatibleWithStandardLibrary

33 34 35
// UnmarshalJSONRequest into the given interface pointer. Returns an error JSON response if
// there was a problem unmarshalling. Calling this function consumes the request body.
func UnmarshalJSONRequest(req *http.Request, iface interface{}) *util.JSONResponse {
T
tanggen 已提交
36 37 38 39 40 41
	content, _ := ioutil.ReadAll(req.Body)
	if len(content) == 0 {
		return nil
	}

	if err := json.Unmarshal(content, iface); err != nil {
42 43 44
		// TODO: We may want to suppress the Error() return in production? It's useful when
		// debugging because an error will be produced for both invalid/malformed JSON AND
		// valid JSON with incorrect types for values.
45
		return &util.JSONResponse{
T
tanggen 已提交
46
			Code: http.StatusBadRequest,
47
			JSON: jsonerror.BadJSON("The request body could not be decoded into valid JSON. " + err.Error()),
48 49 50 51
		}
	}
	return nil
}
52 53 54 55 56

// LogThenError logs the given error then returns a matrix-compliant 500 internal server error response.
// This should be used to log fatal errors which require investigation. It should not be used
// to log client validation errors, etc.
func LogThenError(req *http.Request, err error) util.JSONResponse {
T
tanggen 已提交
57 58 59
	fields := util.GetLogFields(req.Context())
	fields = append(fields, log.KeysAndValues{"error", err}...)
	log.Errorw("request failed", fields)
60 61
	return jsonerror.InternalServerError()
}
T
tanggen 已提交
62 63 64 65 66 67 68 69 70 71

// LogThenErrorCtx logs the given error then returns a matrix-compliant 500 internal server error response.
// This should be used to log fatal errors which require investigation. It should not be used
// to log client validation errors, etc.
func LogThenErrorCtx(ctx context.Context, err error) (int, *jsonerror.MatrixError) {
	fields := util.GetLogFields(ctx)
	fields = append(fields, log.KeysAndValues{"error", err}...)
	log.Errorw("request failed", fields)
	return http.StatusInternalServerError, jsonerror.Unknown("Internal Server Error")
}