cubefs

Форк
0
219 строк · 5.6 Кб
1
// Copyright 2022 The CubeFS Authors.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
14

15
package rpc
16

17
import (
18
	"bytes"
19
	"crypto/md5"
20
	"encoding/json"
21
	"fmt"
22
	"io"
23
	"io/ioutil"
24
	"net/http"
25
	"os"
26
	"path"
27
	"runtime"
28
	"strings"
29

30
	"github.com/cubefs/cubefs/blobstore/util/version"
31
)
32

33
// headers
34
const (
35
	HeaderContentType   = "Content-Type"
36
	HeaderContentLength = "Content-Length"
37
	HeaderContentRange  = "Content-Range"
38
	HeaderContentMD5    = "Content-MD5"
39
	HeaderUA            = "User-Agent"
40

41
	// trace
42
	HeaderTraceLog  = "Trace-Log"
43
	HeaderTraceTags = "Trace-Tags"
44

45
	// crc checker
46
	HeaderCrcEncoded    = "X-Crc-Encoded"
47
	HeaderAckCrcEncoded = "X-Ack-Crc-Encoded"
48
)
49

50
// mime
51
const (
52
	MIMEStream            = "application/octet-stream"
53
	MIMEJSON              = "application/json"
54
	MIMEXML               = "application/xml"
55
	MIMEPlain             = "text/plain"
56
	MIMEPOSTForm          = "application/x-www-form-urlencoded"
57
	MIMEMultipartPOSTForm = "multipart/form-data"
58
	MIMEYAML              = "application/x-yaml"
59
)
60

61
// encoding
62
const (
63
	GzipEncodingType = "gzip"
64
)
65

66
// UserAgent user agent
67
var UserAgent = "Golang blobstore/rpc package"
68

69
type (
70
	// ValueGetter fill argument's field from url values or http params.
71
	ValueGetter func(string) string
72
	// Parser is the interface implemented by argument types
73
	// that can parse themselves from url.Values.
74
	Parser interface {
75
		Parse(ValueGetter) error
76
	}
77

78
	// priority of marshaler and unmarshaler (default is json).
79
	//  - - - - - - - - - - - - - - - - - - - - - -
80
	//  |         | marshaler   | unmarshaler     |
81
	//  | higher  |
82
	//  |   ^     | MarshalerTo | UnmarshalerFrom |
83
	//  |   |     | Marshaler   | Unmarshaler     |
84
	//  |   |     | JSON Marshal| JSON Unmarshal  |
85
	//  |  lower  |
86
	//  - - - - - - - - - - - - - - - - - - - - - -
87

88
	// Actions on RPC.
89
	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
90
	//  |     APP       |  Client     |    TCP    |  Server     |
91
	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
92
	//  | Request Type  | marshaler   | - - - - > | unmarshaler |
93
	//  |                                              |        |
94
	//  |                                              \/       |
95
	//  | Response Type | unmarshaler | < - - - - | marshaler   |
96
	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
97

98
	// Marshaler is the interface implemented by types that
99
	// can marshal themselves into bytes, second parameter
100
	// is content type.
101
	Marshaler interface {
102
		Marshal() ([]byte, string, error)
103
	}
104
	// MarshalerTo is the interface implemented by types that
105
	// can marshal themselves into writer, the first parameter
106
	// is content type. (Not Recommended).
107
	// The underlying writer is a *bytes.Buffer.
108
	// Context.RespondWithReader is better than MarshalerTo on Server Side.
109
	MarshalerTo interface {
110
		MarshalTo(responseBody io.Writer) (string, error)
111
	}
112
	// Unmarshaler is the interface implemented by types
113
	// that can unmarshal themselves from bytes.
114
	Unmarshaler interface {
115
		Unmarshal([]byte) error
116
	}
117
	// UnmarshalerFrom is the interface implemented by types
118
	// that can unmarshal themselves from body reader.
119
	// The body underlying implementation is a *io.LimitedReader.
120
	UnmarshalerFrom interface {
121
		UnmarshalFrom(requestBody io.Reader) error
122
	}
123

124
	// HTTPError interface of error with http status code
125
	HTTPError interface {
126
		// StatusCode http status code
127
		StatusCode() int
128
		// ErrorCode special defined code
129
		ErrorCode() string
130
		// Error detail message
131
		Error() string
132
	}
133
)
134

135
// ProgressHandler http progress handler
136
type ProgressHandler interface {
137
	Handler(http.ResponseWriter, *http.Request, func(http.ResponseWriter, *http.Request))
138
}
139

140
// NoneBody no body of request of response.
141
var NoneBody Marshaler = noneBody{}
142

143
type noneBody struct{}
144

145
func (noneBody) Marshal() ([]byte, string, error) {
146
	return []byte{}, "", nil
147
}
148

149
type marshalledBody struct {
150
	ContentLength int
151
	ContentType   string
152
	Body          io.Reader
153
}
154

155
func marshalObj(obj interface{}) (*marshalledBody, error) {
156
	var (
157
		buffer []byte
158
		ct     string = MIMEJSON
159
		err    error
160
	)
161
	if obj == nil {
162
		buffer = jsonNull[:]
163
	} else if o, ok := obj.(MarshalerTo); ok {
164
		w := bytes.NewBuffer(nil)
165
		ct, err = o.MarshalTo(w)
166
		if err != nil {
167
			return nil, err
168
		}
169
		return &marshalledBody{
170
			ContentLength: w.Len(),
171
			ContentType:   ct,
172
			Body:          w,
173
		}, nil
174

175
	} else if o, ok := obj.(Marshaler); ok {
176
		buffer, ct, err = o.Marshal()
177
	} else {
178
		buffer, err = json.Marshal(obj)
179
	}
180
	if err != nil {
181
		return nil, err
182
	}
183
	return &marshalledBody{
184
		ContentLength: len(buffer),
185
		ContentType:   ct,
186
		Body:          bytes.NewReader(buffer),
187
	}, nil
188
}
189

190
func programVersion() string {
191
	sp := strings.Fields(strings.TrimSpace(version.Version()))
192
	if len(sp) == 0 || sp[0] == "develop" {
193
		data, err := ioutil.ReadFile(os.Args[0])
194
		if err != nil {
195
			return "_"
196
		}
197
		return fmt.Sprintf("%x", md5.Sum(data))[:10]
198
	}
199
	if len(sp) > 10 {
200
		return sp[0][:10]
201
	}
202
	return sp[0]
203
}
204

205
func init() {
206
	hostname, _ := os.Hostname()
207
	ua := fmt.Sprintf("%s/%s (%s/%s; %s) %s/%s",
208
		path.Base(os.Args[0]),
209
		programVersion(),
210
		runtime.GOOS,
211
		runtime.GOARCH,
212
		runtime.Version(),
213
		hostname,
214
		fmt.Sprint(os.Getpid()),
215
	)
216
	if UserAgent != ua {
217
		UserAgent = ua
218
	}
219
}
220

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.