/
transport_http.go
152 lines (127 loc) · 4.16 KB
/
transport_http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Code generated by truss.
// Rerunning truss will overwrite this file.
// DO NOT EDIT!
package svc
// This file provides server-side bindings for the HTTP transport.
// It utilizes the transport/http.Server.
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
"strings"
"golang.org/x/net/context"
"github.com/go-kit/kit/log"
httptransport "github.com/go-kit/kit/transport/http"
"github.com/pkg/errors"
// This service
pb "github.com/adamryman/ambition-users/users-service"
)
var (
_ = fmt.Sprint
_ = bytes.Compare
_ = strconv.Atoi
_ = httptransport.NewServer
_ = ioutil.NopCloser
_ = pb.RegisterUsersServer
_ = io.Copy
_ = errors.Wrap
)
// MakeHTTPHandler returns a handler that makes a set of endpoints available
// on predefined paths.
func MakeHTTPHandler(ctx context.Context, endpoints Endpoints, logger log.Logger) http.Handler {
m := http.NewServeMux()
return m
}
func errorEncoder(_ context.Context, err error, w http.ResponseWriter) {
code := http.StatusInternalServerError
msg := err.Error()
w.WriteHeader(code)
json.NewEncoder(w).Encode(errorWrapper{Error: msg})
}
type errorWrapper struct {
Error string `json:"error"`
}
// Server Decode
// EncodeHTTPGenericResponse is a transport/http.EncodeResponseFunc that encodes
// the response as JSON to the response writer. Primarily useful in a server.
func EncodeHTTPGenericResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
return json.NewEncoder(w).Encode(response)
}
// Helper functions
// PathParams takes a url and a gRPC-annotation style url template, and
// returns a map of the named parameters in the template and their values in
// the given url.
//
// PathParams does not support the entirety of the URL template syntax defined
// in third_party/googleapis/google/api/httprule.proto. Only a small subset of
// the functionality defined there is implemented here.
func PathParams(url string, urlTmpl string) (map[string]string, error) {
rv := map[string]string{}
pmp := BuildParamMap(urlTmpl)
expectedLen := len(strings.Split(strings.TrimRight(urlTmpl, "/"), "/"))
recievedLen := len(strings.Split(strings.TrimRight(url, "/"), "/"))
if expectedLen != recievedLen {
return nil, fmt.Errorf("Expected a path containing %d parts, provided path contains %d parts", expectedLen, recievedLen)
}
parts := strings.Split(url, "/")
for k, v := range pmp {
rv[k] = parts[v]
}
return rv, nil
}
// BuildParamMap takes a string representing a url template and returns a map
// indicating the location of each parameter within that url, where the
// location is the index as if in a slash-separated sequence of path
// components. For example, given the url template:
//
// "/v1/{a}/{b}"
//
// The returned param map would look like:
//
// map[string]int {
// "a": 2,
// "b": 3,
// }
func BuildParamMap(urlTmpl string) map[string]int {
rv := map[string]int{}
parts := strings.Split(urlTmpl, "/")
for idx, part := range parts {
if strings.ContainsAny(part, "{}") {
param := RemoveBraces(part)
rv[param] = idx
}
}
return rv
}
// RemoveBraces replace all curly braces in the provided string, opening and
// closing, with empty strings.
func RemoveBraces(val string) string {
val = strings.Replace(val, "{", "", -1)
val = strings.Replace(val, "}", "", -1)
return val
}
func headersToContext(ctx context.Context, r *http.Request) context.Context {
for k, _ := range r.Header {
// The key is added both in http format (k) which has had
// http.CanonicalHeaderKey called on it in transport as well as the
// strings.ToLower which is the grpc metadata format of the key so
// that it can be accessed in either format
ctx = context.WithValue(ctx, k, r.Header.Get(k))
ctx = context.WithValue(ctx, strings.ToLower(k), r.Header.Get(k))
}
return ctx
}
func HTTPDecodeLogger(next httptransport.DecodeRequestFunc, logger log.Logger) httptransport.DecodeRequestFunc {
return func(ctx context.Context, r *http.Request) (interface{}, error) {
logger.Log("method", r.Method, "url", r.URL.String())
rv, err := next(ctx, r)
if err != nil {
logger.Log("method", r.Method, "url", r.URL.String(), "Error", err)
}
return rv, err
}
}